diff --git a/zed/src/editor/buffer/rope.rs b/zed/src/editor/buffer/rope.rs index bb441e96d3..c866b37389 100644 --- a/zed/src/editor/buffer/rope.rs +++ b/zed/src/editor/buffer/rope.rs @@ -7,7 +7,7 @@ use std::{cmp, ops::Range, str}; const CHUNK_BASE: usize = 2; #[cfg(not(test))] -const CHUNK_BASE: usize = 8; +const CHUNK_BASE: usize = 16; #[derive(Clone, Default, Debug)] pub struct Rope { @@ -20,7 +20,20 @@ impl Rope { } pub fn append(&mut self, rope: Rope) { - self.chunks.push_tree(rope.chunks, &()); + let mut chunks = rope.chunks.cursor::<(), ()>(); + chunks.next(); + + while let Some((last_chunk, first_chunk)) = self.chunks.last().zip(chunks.item()) { + if last_chunk.0.len() < CHUNK_BASE || first_chunk.0.len() < CHUNK_BASE { + self.push(&first_chunk.0); + chunks.next(); + } else { + break; + } + } + + self.chunks.push_tree(chunks.suffix(&()), &()); + self.check_invariants(); } pub fn push(&mut self, mut text: &str) { @@ -48,7 +61,7 @@ impl Rope { let split = chunk.0.split_at(take_len); suffix.push_str(split.1); - chunk.0 = ArrayString::from(split.0).unwrap(); + chunk.0.truncate(take_len); } } }, @@ -68,6 +81,25 @@ impl Rope { chunks.push(Chunk(chunk)); } self.chunks.extend(chunks, &()); + self.check_invariants(); + } + + fn check_invariants(&self) { + #[cfg(test)] + { + let mut chunks = self.chunks.cursor::<(), ()>().peekable(); + chunks.next(); + while let Some(chunk) = chunks.next() { + if chunks.peek().is_some() { + assert!( + chunk.0.len() >= CHUNK_BASE, + "Underflowing chunk: {:?}\nChunks: {:?}", + chunk, + self.chunks.items() + ); + } + } + } } pub fn slice(&self, range: Range) -> Rope { @@ -90,7 +122,7 @@ impl Rope { slice.push(&end_chunk.0[..range.end - cursor.start()]); } } - + slice.check_invariants(); slice }