diff --git a/src/services/context.rs b/src/services/context.rs index 8c59f91..f682cbf 100644 --- a/src/services/context.rs +++ b/src/services/context.rs @@ -321,18 +321,18 @@ impl ContextBuilder { // Compare non-whitespace character streams. // Correctly handles line wrapping while detecting actual content changes. - let old_text: String = removed_in_span + // Use streaming Iterator::eq to avoid allocating two full Strings and + // to short-circuit on the first differing character. + let old_chars = removed_in_span .iter() .flat_map(|l| l.chars()) - .filter(|c| !c.is_whitespace()) - .collect(); - let new_text: String = added_in_span + .filter(|c| !c.is_whitespace()); + let new_chars = added_in_span .iter() .flat_map(|l| l.chars()) - .filter(|c| !c.is_whitespace()) - .collect(); + .filter(|c| !c.is_whitespace()); - Some(old_text == new_text) + Some(old_chars.eq(new_chars)) } /// Classify changes within a symbol span with doc-vs-code distinction. @@ -393,18 +393,18 @@ impl ContextBuilder { return None; } - // Check whitespace-only first (same logic as classify_span_change) - let old_text: String = removed_in_span + // Check whitespace-only first (same logic as classify_span_change). + // Stream the filtered char iterators through Iterator::eq to avoid + // allocating intermediate Strings and short-circuit on inequality. + let old_chars = removed_in_span .iter() .flat_map(|l| l.chars()) - .filter(|c| !c.is_whitespace()) - .collect(); - let new_text: String = added_in_span + .filter(|c| !c.is_whitespace()); + let new_chars = added_in_span .iter() .flat_map(|l| l.chars()) - .filter(|c| !c.is_whitespace()) - .collect(); - if old_text == new_text { + .filter(|c| !c.is_whitespace()); + if old_chars.eq(new_chars) { return Some(SpanChangeKind::WhitespaceOnly); } diff --git a/src/services/differ.rs b/src/services/differ.rs index 1d04f34..930f434 100644 --- a/src/services/differ.rs +++ b/src/services/differ.rs @@ -283,9 +283,13 @@ impl AstDiffer { } fn bodies_semantically_equal(old_body: Option<&str>, new_body: Option<&str>) -> bool { - let strip = |s: &str| -> String { s.chars().filter(|c| !c.is_whitespace()).collect() }; match (old_body, new_body) { - (Some(o), Some(n)) => strip(o) == strip(n), + // Stream filtered char iterators through Iterator::eq to avoid + // allocating intermediate Strings and short-circuit on inequality. + (Some(o), Some(n)) => o + .chars() + .filter(|c| !c.is_whitespace()) + .eq(n.chars().filter(|c| !c.is_whitespace())), (None, None) => true, _ => false, }