yaml parser string slices
This commit is contained in:
@@ -10,6 +10,9 @@ use crate::{Error, Result};
|
|||||||
/// Unity files use the YAML 1.1 multi-document format, where each document
|
/// Unity files use the YAML 1.1 multi-document format, where each document
|
||||||
/// starts with `---`. This function splits the file into individual documents.
|
/// starts with `---`. This function splits the file into individual documents.
|
||||||
///
|
///
|
||||||
|
/// Returns string slices referencing the original content, avoiding allocations.
|
||||||
|
/// Callers can convert slices to owned strings with `.to_string()` if needed.
|
||||||
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
@@ -19,48 +22,45 @@ use crate::{Error, Result};
|
|||||||
/// let docs = split_yaml_documents(content).unwrap();
|
/// let docs = split_yaml_documents(content).unwrap();
|
||||||
/// assert_eq!(docs.len(), 2);
|
/// assert_eq!(docs.len(), 2);
|
||||||
/// ```
|
/// ```
|
||||||
pub fn split_yaml_documents(content: &str) -> Result<Vec<String>> {
|
pub fn split_yaml_documents<'a>(content: &'a str) -> Result<Vec<&'a str>> {
|
||||||
let mut documents = Vec::new();
|
let mut documents = Vec::new();
|
||||||
let mut current_doc = String::new();
|
let mut doc_start: Option<usize> = None;
|
||||||
let mut in_document = false;
|
let mut pos = 0;
|
||||||
let mut header_lines = Vec::new();
|
|
||||||
|
// Use split_inclusive to keep newlines, making byte position tracking easier
|
||||||
|
for line in content.split_inclusive('\n') {
|
||||||
|
// Get the line content without line endings for checking
|
||||||
|
let trimmed = line.trim_end_matches(&['\r', '\n'][..]);
|
||||||
|
|
||||||
for line in content.lines() {
|
|
||||||
// Skip empty lines before first document
|
// Skip empty lines before first document
|
||||||
if line.trim().is_empty() && !in_document && current_doc.is_empty() {
|
if trimmed.is_empty() && doc_start.is_none() {
|
||||||
|
pos += line.len();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle YAML headers (%YAML and %TAG)
|
// Skip YAML headers (%YAML and %TAG)
|
||||||
if line.starts_with('%') {
|
if trimmed.starts_with('%') {
|
||||||
if !in_document {
|
pos += line.len();
|
||||||
header_lines.push(line);
|
|
||||||
}
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if this is a document separator
|
// Check if this is a document separator
|
||||||
if line.starts_with("---") {
|
if trimmed.starts_with("---") {
|
||||||
// If we have a current document, save it
|
// Save previous document if exists
|
||||||
if !current_doc.is_empty() {
|
if let Some(start) = doc_start {
|
||||||
documents.push(current_doc.trim().to_string());
|
documents.push(content[start..pos].trim());
|
||||||
current_doc.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start a new document with this line
|
// Mark the start of the new document
|
||||||
current_doc.push_str(line);
|
doc_start = Some(pos);
|
||||||
current_doc.push('\n');
|
|
||||||
in_document = true;
|
|
||||||
} else if in_document {
|
|
||||||
// Add line to current document
|
|
||||||
current_doc.push_str(line);
|
|
||||||
current_doc.push('\n');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pos += line.len();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the last document if it exists
|
// Add the last document if it exists
|
||||||
if !current_doc.is_empty() {
|
if let Some(start) = doc_start {
|
||||||
documents.push(current_doc.trim().to_string());
|
documents.push(content[start..].trim());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate we found at least one document
|
// Validate we found at least one document
|
||||||
|
|||||||
Reference in New Issue
Block a user