mirror of
https://github.com/zed-industries/zed.git
synced 2024-10-25 07:55:56 +00:00
Better balancing of chunks on push
This commit is contained in:
parent
f303a1d5fe
commit
6e30fdbf5c
1 changed files with 34 additions and 30 deletions
|
@ -2,6 +2,7 @@ use super::Point;
|
|||
use crate::sum_tree::{self, SeekBias, SumTree};
|
||||
use anyhow::{anyhow, Result};
|
||||
use arrayvec::ArrayString;
|
||||
use smallvec::SmallVec;
|
||||
use std::{cmp, ops::Range, str};
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -37,36 +38,10 @@ impl Rope {
|
|||
self.check_invariants();
|
||||
}
|
||||
|
||||
pub fn push(&mut self, mut text: &str) {
|
||||
let mut suffix = ArrayString::<[_; CHUNK_BASE]>::new();
|
||||
self.chunks.with_last_mut(
|
||||
|chunk| {
|
||||
if chunk.0.len() + text.len() <= 2 * CHUNK_BASE {
|
||||
chunk.0.push_str(text);
|
||||
text = "";
|
||||
} else if chunk.0.len() < CHUNK_BASE {
|
||||
let mut split_ix = CHUNK_BASE - chunk.0.len();
|
||||
while !text.is_char_boundary(split_ix) {
|
||||
split_ix += 1;
|
||||
}
|
||||
let split = text.split_at(split_ix);
|
||||
chunk.0.push_str(split.0);
|
||||
text = split.1;
|
||||
} else {
|
||||
let mut split_ix = CHUNK_BASE;
|
||||
while !chunk.0.is_char_boundary(split_ix) {
|
||||
split_ix += 1;
|
||||
}
|
||||
suffix.push_str(&chunk.0[split_ix..]);
|
||||
chunk.0.truncate(split_ix);
|
||||
}
|
||||
},
|
||||
&(),
|
||||
);
|
||||
|
||||
let mut chunks = vec![];
|
||||
pub fn push(&mut self, text: &str) {
|
||||
let mut chunks = SmallVec::<[_; 16]>::new();
|
||||
let mut chunk = ArrayString::new();
|
||||
for ch in suffix.chars().chain(text.chars()) {
|
||||
for ch in text.chars() {
|
||||
if chunk.len() + ch.len_utf8() > 2 * CHUNK_BASE {
|
||||
chunks.push(Chunk(chunk));
|
||||
chunk = ArrayString::new();
|
||||
|
@ -76,7 +51,36 @@ impl Rope {
|
|||
if !chunk.is_empty() {
|
||||
chunks.push(Chunk(chunk));
|
||||
}
|
||||
self.chunks.extend(chunks, &());
|
||||
|
||||
let mut chunks = chunks.into_iter();
|
||||
let mut first_chunk = chunks.next();
|
||||
self.chunks.with_last_mut(
|
||||
|last_chunk| {
|
||||
if let Some(chunk) = first_chunk.as_mut() {
|
||||
if last_chunk.0.len() + chunk.0.len() <= 2 * CHUNK_BASE {
|
||||
last_chunk.0.push_str(&first_chunk.take().unwrap().0);
|
||||
} else {
|
||||
let mut text = ArrayString::<[_; 4 * CHUNK_BASE]>::new();
|
||||
text.push_str(&last_chunk.0);
|
||||
text.push_str(&chunk.0);
|
||||
|
||||
let mut midpoint = text.len() / 2;
|
||||
while !text.is_char_boundary(midpoint) {
|
||||
midpoint += 1;
|
||||
}
|
||||
let (left, right) = text.split_at(midpoint);
|
||||
last_chunk.0.clear();
|
||||
last_chunk.0.push_str(left);
|
||||
chunk.0.clear();
|
||||
chunk.0.push_str(right);
|
||||
}
|
||||
}
|
||||
},
|
||||
&(),
|
||||
);
|
||||
|
||||
self.chunks
|
||||
.extend(first_chunk.into_iter().chain(chunks), &());
|
||||
self.check_invariants();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue