loro_delta/delta_rope/
compose.rs

1use super::*;
2
3struct DeltaReplace<'a, V, Attr> {
4    value: &'a V,
5    attr: &'a Attr,
6    delete: usize,
7}
8
9impl<V: DeltaValue, Attr: DeltaAttr> DeltaRope<V, Attr> {
10    pub fn compose(&mut self, other: &Self) {
11        // TODO: Need to implement a slow mode that is guaranteed to be correct, then we can fuzz on it
12        if self.is_empty() {
13            *self = other.clone();
14            return;
15        }
16
17        // trace!("Composing {:#?}\n{:#?}", &self, &other);
18        let mut index = 0;
19
20        let mut push_rest = false;
21        for item in other.iter() {
22            if index >= self.len() {
23                self.push_retain(index - self.len(), Attr::default());
24                push_rest = true;
25            }
26
27            if push_rest {
28                self.push(item.clone());
29                continue;
30            }
31
32            match item {
33                DeltaItem::Retain { len, attr } => {
34                    if self.len() < index + len {
35                        self.push_retain(index + len - self.len(), Default::default());
36                    }
37                    if !attr.attr_is_empty() {
38                        self.update_attr_in_range(index..index + len, attr);
39                    }
40                    index += len;
41                }
42                DeltaItem::Replace {
43                    value: this_value,
44                    attr: this_attr,
45                    delete,
46                } => {
47                    self._compose_replace(
48                        DeltaReplace {
49                            value: this_value,
50                            attr: this_attr,
51                            delete: *delete,
52                        },
53                        &mut index,
54                    );
55                }
56            }
57        }
58
59        // trace!("Composed {:#?}", &self);
60    }
61
62    pub fn delete(&mut self, mut index: usize, len: usize) {
63        self._compose_replace(
64            DeltaReplace {
65                value: &Default::default(),
66                attr: &Default::default(),
67                delete: len,
68            },
69            &mut index,
70        );
71    }
72
73    fn _compose_replace(
74        &mut self,
75        delta_replace_item @ DeltaReplace {
76            value: this_value,
77            attr: this_attr,
78            delete,
79        }: DeltaReplace<V, Attr>,
80        index: &mut usize,
81    ) {
82        let mut should_insert = this_value.rle_len() > 0;
83        let mut left_del_len = delete;
84        if *index > self.len() {
85            self.push_retain(*index - self.len(), Attr::default());
86        }
87
88        if delete > 0 && *index != self.len() {
89            let range = *index..(*index + left_del_len).min(self.len());
90            let from = self.tree.query::<LengthFinder>(&range.start).unwrap();
91            let to = self.tree.query::<LengthFinder>(&range.end).unwrap();
92            if from.cursor.leaf == to.cursor.leaf {
93                self._replace_on_single_leaf(from, to, left_del_len, delta_replace_item);
94                should_insert = false;
95                left_del_len = 0;
96            } else {
97                self._replace_batch_leaves(from, to, &mut left_del_len);
98            }
99        }
100
101        if left_del_len > 0 || should_insert {
102            let replace = DeltaItem::Replace {
103                value: if should_insert {
104                    this_value.clone()
105                } else {
106                    Default::default()
107                },
108                attr: if should_insert {
109                    this_attr.clone()
110                } else {
111                    Default::default()
112                },
113                delete: left_del_len,
114            };
115            self.insert_values(*index, [replace]);
116        }
117
118        *index += this_value.rle_len();
119    }
120
121    fn _replace_batch_leaves(
122        &mut self,
123        from: generic_btree::QueryResult,
124        to: generic_btree::QueryResult,
125        left_del_len: &mut usize,
126    ) {
127        self.tree.update(from.cursor..to.cursor, &mut |item| {
128            // This method will split the leaf node before calling this closure.
129            // So it's guaranteed that the item is contained in the range.
130            if *left_del_len == 0 {
131                return None;
132            }
133
134            match item {
135                DeltaItem::Retain { len, .. } => {
136                    assert!(*len <= *left_del_len);
137                    *left_del_len -= *len;
138                    let diff = -(*len as isize);
139                    *item = DeltaItem::Replace {
140                        delete: *len,
141                        value: Default::default(),
142                        attr: Default::default(),
143                    };
144                    Some(Len {
145                        data_len: diff,
146                        delta_len: 0,
147                    })
148                }
149                DeltaItem::Replace { value, attr, .. } => {
150                    if *left_del_len >= value.rle_len() {
151                        let diff = value.rle_len() as isize;
152                        *left_del_len -= value.rle_len();
153                        *value = Default::default();
154                        *attr = Default::default();
155                        Some(Len {
156                            data_len: -diff,
157                            delta_len: -diff,
158                        })
159                    } else {
160                        unreachable!()
161                    }
162                }
163            }
164        });
165    }
166
167    fn _replace_on_single_leaf(
168        &mut self,
169        from: generic_btree::QueryResult,
170        to: generic_btree::QueryResult,
171        left_del_len: usize,
172        DeltaReplace {
173            value: this_value,
174            attr: this_attr,
175            delete: _,
176        }: DeltaReplace<V, Attr>,
177    ) {
178        self.tree.update_leaf(from.cursor.leaf, |item| match item {
179            DeltaItem::Retain {
180                len: retain_len, ..
181            } => {
182                let start = from.cursor.offset;
183                let end = to.cursor.offset;
184                debug_assert!(end <= *retain_len);
185                let (l, r) = item.update_with_split(start..end, |item| {
186                    *item = DeltaItem::Replace {
187                        delete: left_del_len,
188                        value: this_value.clone(),
189                        attr: this_attr.clone(),
190                    };
191                });
192
193                (true, l, r)
194            }
195            DeltaItem::Replace { value, delete, .. } => {
196                let start = from.cursor.offset;
197                let end = to.cursor.offset;
198                let value_len = value.rle_len();
199                let value_start = start.min(value_len);
200                let value_end = value_len.min(end);
201                {
202                    // We need to remove the part of value that is between start and end.
203                    // If the range is out of the bounds of the value, we record extra deletions
204                    // on the `delete` field of this item.
205                    let left = left_del_len.saturating_sub(value_end - value_start);
206                    *delete += left;
207                }
208
209                let (l, r) = item.update_with_split(value_start..value_end, |item| {
210                    *item = DeltaItem::Replace {
211                        value: this_value.clone(),
212                        attr: this_attr.clone(),
213                        delete: 0,
214                    };
215                });
216
217                (true, l, r)
218            }
219        });
220    }
221}