commit 352ace0ec1352981d669baee0f211c2f4bdf3839
parent 23b2817320e75791ace9e7aa5d0d6900fbb7c932
Author: William Casarin <jb55@jb55.com>
Date: Fri, 13 Feb 2026 13:31:10 -0800
egui-md-stream: fix O(n²) collapse_text_elements
Replace Vec::remove loop with single-pass read/write pointer
approach. Vec::remove shifts all subsequent elements on each
call, making it quadratic. The new approach swaps in place and
truncates once at the end.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Diffstat:
1 file changed, 15 insertions(+), 6 deletions(-)
diff --git a/crates/egui-md-stream/src/inline.rs b/crates/egui-md-stream/src/inline.rs
@@ -371,16 +371,25 @@ fn parse_link(text: &str) -> Option<(String, String, usize)> {
/// Collapse adjacent Text elements into one.
fn collapse_text_elements(elements: &mut Vec<InlineElement>) {
- let mut i = 0;
- while i + 1 < elements.len() {
- if let (InlineElement::Text(a), InlineElement::Text(b)) = (&elements[i], &elements[i + 1]) {
+ if elements.len() < 2 {
+ return;
+ }
+
+ let mut write = 0;
+ for read in 1..elements.len() {
+ if let (InlineElement::Text(a), InlineElement::Text(b)) =
+ (&elements[write], &elements[read])
+ {
let combined = format!("{}{}", a, b);
- elements[i] = InlineElement::Text(combined);
- elements.remove(i + 1);
+ elements[write] = InlineElement::Text(combined);
} else {
- i += 1;
+ write += 1;
+ if write != read {
+ elements.swap(write, read);
+ }
}
}
+ elements.truncate(write + 1);
}
/// Streaming inline parser state.