Skip to content

Commit 4e72700

Browse files
bors[bot]Moritz Vetter
and
Moritz Vetter
authored
Merge #11573
11573: refactorings and FIXME fixes in text edit r=lnicola a=HansAuger This is mainly me learning some rust, and only anecdotally about addressing some `fixme`s. Feel free to nope :) There is a follow up PR in the pipeline which tackles the other two `fixme`s but it's a bit more invasive. So I wanted to get this out of the way Co-authored-by: Moritz Vetter <[email protected]>
2 parents a53915c + ff59147 commit 4e72700

File tree

1 file changed

+53
-17
lines changed

1 file changed

+53
-17
lines changed

crates/text_edit/src/lib.rs

+53-17
Original file line numberDiff line numberDiff line change
@@ -90,28 +90,22 @@ impl TextEdit {
9090
_ => (),
9191
}
9292

93-
let mut total_len = TextSize::of(&*text);
93+
let text_size = TextSize::of(&*text);
94+
let mut total_len = text_size.clone();
9495
for indel in &self.indels {
9596
total_len += TextSize::of(&indel.insert);
96-
total_len -= indel.delete.end() - indel.delete.start();
97+
total_len -= indel.delete.len();
9798
}
98-
let mut buf = String::with_capacity(total_len.into());
99-
let mut prev = 0;
100-
for indel in &self.indels {
101-
let start: usize = indel.delete.start().into();
102-
let end: usize = indel.delete.end().into();
103-
if start > prev {
104-
buf.push_str(&text[prev..start]);
105-
}
106-
buf.push_str(&indel.insert);
107-
prev = end;
99+
100+
if let Some(additional) = total_len.checked_sub(text_size.into()) {
101+
text.reserve(additional.into());
102+
}
103+
104+
for indel in self.indels.iter().rev() {
105+
indel.apply(text);
108106
}
109-
buf.push_str(&text[prev..text.len()]);
110-
assert_eq!(TextSize::of(&buf), total_len);
111107

112-
// FIXME: figure out a way to mutate the text in-place or reuse the
113-
// memory in some other way
114-
*text = buf;
108+
assert_eq!(TextSize::of(&*text), total_len);
115109
}
116110

117111
pub fn union(&mut self, other: TextEdit) -> Result<(), TextEdit> {
@@ -203,3 +197,45 @@ fn check_disjoint_and_sort(indels: &mut [impl std::borrow::Borrow<Indel>]) -> bo
203197
l.delete.end() <= r.delete.start() || l == r
204198
})
205199
}
200+
201+
#[cfg(test)]
202+
mod tests {
203+
use super::{TextEdit, TextEditBuilder, TextRange};
204+
205+
fn range(start: u32, end: u32) -> TextRange {
206+
TextRange::new(start.into(), end.into())
207+
}
208+
209+
#[test]
210+
fn test_apply() {
211+
let mut text = "_11h1_2222_xx3333_4444_6666".to_string();
212+
let mut builder = TextEditBuilder::default();
213+
builder.replace(range(3, 4), "1".to_string());
214+
builder.delete(range(11, 13));
215+
builder.insert(22.into(), "_5555".to_string());
216+
217+
let text_edit = builder.finish();
218+
text_edit.apply(&mut text);
219+
220+
assert_eq!(text, "_1111_2222_3333_4444_5555_6666")
221+
}
222+
223+
#[test]
224+
fn test_union() {
225+
let mut edit1 = TextEdit::delete(range(7, 11));
226+
let mut builder = TextEditBuilder::default();
227+
builder.delete(range(1, 5));
228+
builder.delete(range(13, 17));
229+
230+
let edit2 = builder.finish();
231+
assert!(edit1.union(edit2).is_ok());
232+
assert_eq!(edit1.indels.len(), 3);
233+
}
234+
235+
#[test]
236+
fn test_union_panics() {
237+
let mut edit1 = TextEdit::delete(range(7, 11));
238+
let edit2 = TextEdit::delete(range(9, 13));
239+
assert!(edit1.union(edit2).is_err());
240+
}
241+
}

0 commit comments

Comments
 (0)