@@ -27,15 +27,35 @@ pub struct ChangeSet {
27 pub(crate) changes: Vec<Operation>,
27 pub(crate) changes: Vec<Operation>,
28 /// The required document length. Will refuse to apply changes unless it matches.
28 /// The required document length. Will refuse to apply changes unless it matches.
29 len: usize,
29 len: usize,
33+impl Default for ChangeSet {
34+ fn default() -> Self {
32impl ChangeSet {
43impl ChangeSet {
44+ pub fn with_capacity(capacity: usize) -> Self {
46+ changes: Vec::with_capacity(capacity),
33 #[must_use]
52 #[must_use]
34 pub fn new(doc: &Rope) -> Self {
53 pub fn new(doc: &Rope) -> Self {
35 let len = doc.len_chars();
54 let len = doc.len_chars();
37− changes: vec![Operation::Retain(len)],
56+ changes: Vec::new(),
@@ -47,21 +67,6 @@ impl ChangeSet {
47 &self.changes
67 &self.changes
51− fn len_after(&self) -> usize {
55− for change in &self.changes {
57− Retain(i) => len += i,
58− Insert(s) => len += s.chars().count(),
65 // Changeset builder operations: delete/insert/retain
70 // Changeset builder operations: delete/insert/retain
66 fn delete(&mut self, n: usize) {
71 fn delete(&mut self, n: usize) {
67 use Operation::*;
72 use Operation::*;
@@ -69,6 +74,8 @@ impl ChangeSet {
72 if let Some(Delete(count)) = self.changes.last_mut() {
79 if let Some(Delete(count)) = self.changes.last_mut() {
73 *count += n;
80 *count += n;
@@ -83,6 +90,8 @@ impl ChangeSet {
93+ self.len_after += fragment.len();
86 let new_last = match self.changes.as_mut_slice() {
95 let new_last = match self.changes.as_mut_slice() {
87 [.., Insert(prev)] | [.., Insert(prev), Delete(_)] => {
96 [.., Insert(prev)] | [.., Insert(prev), Delete(_)] => {
88 prev.push_tendril(&fragment);
97 prev.push_tendril(&fragment);
@@ -101,6 +110,9 @@ impl ChangeSet {
114+ self.len_after += n;
104 if let Some(Retain(count)) = self.changes.last_mut() {
116 if let Some(Retain(count)) = self.changes.last_mut() {
105 *count += n;
117 *count += n;
@@ -112,7 +124,13 @@ impl ChangeSet {
112 /// In other words, If `this` goes `docA` → `docB` and `other` represents `docB` → `docC`, the
124 /// In other words, If `this` goes `docA` → `docB` and `other` represents `docB` → `docC`, the
113 /// returned value will represent the change `docA` → `docC`.
125 /// returned value will represent the change `docA` → `docC`.
114 pub fn compose(self, other: Self) -> Self {
126 pub fn compose(self, other: Self) -> Self {
115− debug_assert!(self.len_after() == other.len);
127+ debug_assert!(self.len_after == other.len);
129+ // composing fails in weird ways if one of the sets is empty
130+ // a: [] len: 0 len_after: 1 | b: [Insert(Tendril<UTF8>(inline: "\n")), Retain(1)] len 1
131+ if self.changes.is_empty() {
117 let len = self.changes.len();
135 let len = self.changes.len();
@@ -122,10 +140,7 @@ impl ChangeSet {
122 let mut head_a = changes_a.next();
140 let mut head_a = changes_a.next();
123 let mut head_b = changes_b.next();
141 let mut head_b = changes_b.next();
125− let mut changes = Self {
127− changes: Vec::with_capacity(len), // TODO: max(a, b), shrink_to_fit() afterwards
143+ let mut changes = Self::with_capacity(len); // TODO: max(a, b), shrink_to_fit() afterwards
131 use std::cmp::Ordering;
146 use std::cmp::Ordering;
@@ -228,6 +243,9 @@ impl ChangeSet {
246+ // starting len should still equal original starting len
247+ debug_assert!(changes.len == self.len);
@@ -251,7 +269,8 @@ impl ChangeSet {
251 pub fn invert(&self, original_doc: &Rope) -> Self {
269 pub fn invert(&self, original_doc: &Rope) -> Self {
252 assert!(original_doc.len_chars() == self.len);
270 assert!(original_doc.len_chars() == self.len);
254− let mut changes = Vec::with_capacity(self.changes.len());
272+ let mut changes = Self::with_capacity(self.changes.len());
255 let mut pos = 0;
274 let mut pos = 0;
256 let mut len = 0;
275 let mut len = 0;
@@ -259,24 +278,22 @@ impl ChangeSet {
259 use Operation::*;
278 use Operation::*;
260 match change {
279 match change {
261 Retain(n) => {
280 Retain(n) => {
262− changes.push(Retain(*n));
281+ changes.retain(*n);
263 pos += n;
282 pos += n;
266 Delete(n) => {
284 Delete(n) => {
267 let text = Cow::from(original_doc.slice(pos..pos + *n));
285 let text = Cow::from(original_doc.slice(pos..pos + *n));
268− changes.push(Insert(Tendril::from_slice(&text)));
286+ changes.insert(Tendril::from_slice(&text));
269 pos += n;
287 pos += n;
271 Insert(s) => {
289 Insert(s) => {
272 let chars = s.chars().count();
290 let chars = s.chars().count();
273− changes.push(Delete(chars));
291+ changes.delete(chars);
279− Self { changes, len }
296+ changes
282 /// Returns true if applied successfully.
299 /// Returns true if applied successfully.
@@ -309,7 +326,7 @@ impl ChangeSet {
309 /// `true` when the set is empty.
326 /// `true` when the set is empty.
310 #[inline]
327 #[inline]
311 pub fn is_empty(&self) -> bool {
328 pub fn is_empty(&self) -> bool {
312− matches!(self.changes.as_slice(), [] | [Operation::Retain(_)])
329+ self.changes.is_empty()
315 /// Map a position through the changes.
332 /// Map a position through the changes.
@@ -458,8 +475,8 @@ impl Transaction {
458 I: IntoIterator<Item = Change> + ExactSizeIterator,
475 I: IntoIterator<Item = Change> + ExactSizeIterator,
460 let len = doc.len_chars();
477 let len = doc.len_chars();
461− let acc = Vec::with_capacity(2 * changes.len() + 1); // rough estimate
479+ let mut changeset = ChangeSet::with_capacity(2 * changes.len() + 1); // rough estimate
462− let mut changeset = ChangeSet { changes: acc, len };
464 // TODO: verify ranges are ordered and not overlapping or change will panic.
481 // TODO: verify ranges are ordered and not overlapping or change will panic.
@@ -576,11 +593,13 @@ mod test {
576 Insert("abc".into()),
593 Insert("abc".into()),
581 let b = ChangeSet {
599 let b = ChangeSet {
582 changes: vec![Delete(10), Insert("world".into()), Retain(5)],
600 changes: vec![Delete(10), Insert("world".into()), Retain(5)],
586 let mut text = Rope::from("hello xz");
605 let mut text = Rope::from("hello xz");
@@ -597,8 +616,9 @@ mod test {
597 use Operation::*;
616 use Operation::*;
599 let changes = ChangeSet {
618 let changes = ChangeSet {
600− changes: vec![Retain(4), Delete(5), Insert("test".into()), Retain(3)],
619+ changes: vec![Retain(4), Insert("test".into()), Delete(5), Retain(3)],
604 let doc = Rope::from("世界3 hello xz");
624 let doc = Rope::from("世界3 hello xz");
@@ -627,6 +647,7 @@ mod test {
627 let cs = ChangeSet {
647 let cs = ChangeSet {
628 changes: vec![Retain(4), Insert("!!".into()), Retain(4)],
648 changes: vec![Retain(4), Insert("!!".into()), Retain(4)],
632 assert_eq!(cs.map_pos(0, Assoc::Before), 0); // before insert region
653 assert_eq!(cs.map_pos(0, Assoc::Before), 0); // before insert region
@@ -638,6 +659,7 @@ mod test {
638 let cs = ChangeSet {
659 let cs = ChangeSet {
639 changes: vec![Retain(4), Delete(4), Retain(4)],
660 changes: vec![Retain(4), Delete(4), Retain(4)],
642 assert_eq!(cs.map_pos(0, Assoc::Before), 0); // at start
664 assert_eq!(cs.map_pos(0, Assoc::Before), 0); // at start
643 assert_eq!(cs.map_pos(4, Assoc::Before), 4); // before a delete
665 assert_eq!(cs.map_pos(4, Assoc::Before), 4); // before a delete
@@ -655,6 +677,7 @@ mod test {
655 Delete(2),
677 Delete(2),
659 assert_eq!(cs.map_pos(2, Assoc::Before), 2);
682 assert_eq!(cs.map_pos(2, Assoc::Before), 2);
660 assert_eq!(cs.map_pos(2, Assoc::After), 2);
683 assert_eq!(cs.map_pos(2, Assoc::After), 2);
@@ -717,4 +740,18 @@ mod test {
717 assert_eq!(changes.changes, &[Insert("hello".into())]);
740 assert_eq!(changes.changes, &[Insert("hello".into())]);
718 // instead of insert h, insert e, insert l, insert l, insert o
741 // instead of insert h, insert e, insert l, insert l, insert o
745+ fn combine_with_empty() {
746+ let empty = Rope::from("");
747+ let mut a = ChangeSet::new(&empty);
749+ let mut b = ChangeSet::new(&empty);
750+ b.insert("a".into());
752+ let changes = a.compose(b);
755+ assert_eq!(changes.changes, &[Insert("a".into())]);