crdt_richtext/
rich_text.rs

1use std::{
2    cmp::Ordering,
3    fmt::Display,
4    ops::{Bound, RangeBounds},
5    sync::Arc,
6};
7
8use append_only_bytes::AppendOnlyBytes;
9
10use fxhash::FxHashMap;
11use generic_btree::{
12    rle::{HasLength, Mergeable, Sliceable},
13    BTree, MoveEvent, QueryResult,
14};
15use smallvec::SmallVec;
16
17use crate::{
18    rich_text::{ann::insert_anchors_at_same_elem, op::OpContent, rich_tree::utf16::get_utf16_len},
19    Anchor, AnchorType, Annotation, ClientID, Counter, IdSpan, OpID, Style,
20};
21
22use self::{
23    ann::{insert_anchor_to_char, AnchorSetDiff, AnnIdx, AnnManager, Span, StyleCalculator},
24    cursor::CursorMap,
25    encoding::{decode, encode},
26    op::{Op, OpStore},
27    rich_tree::{
28        query::{IndexFinder, IndexType},
29        rich_tree_btree_impl::RichTreeTrait,
30        CacheDiff, Elem,
31    },
32    vv::VersionVector,
33};
34
35mod ann;
36mod cursor;
37mod encoding;
38mod id_map;
39mod iter;
40mod op;
41mod rich_tree;
42#[cfg(test)]
43mod test;
44#[cfg(feature = "test")]
45pub mod test_utils;
46pub mod vv;
47
48pub struct RichText {
49    bytes: AppendOnlyBytes,
50    content: BTree<RichTreeTrait>,
51    cursor_map: CursorMap,
52    store: OpStore,
53    pending_ops: Vec<Op>,
54    ann: AnnManager,
55    /// this is the styles starting from the very beginning,
56    /// which have start anchor of None
57    init_styles: StyleCalculator,
58}
59
60impl RichText {
61    pub fn new(client_id: u64) -> Self {
62        let cursor_map: CursorMap = Default::default();
63        let update_fn = cursor_map.gen_update_fn();
64        let mut content: BTree<RichTreeTrait> = BTree::new();
65        content.set_listener(Some(update_fn));
66        RichText {
67            bytes: AppendOnlyBytes::new(),
68            content,
69            cursor_map,
70            store: OpStore::new(client_id),
71            pending_ops: Default::default(),
72            ann: AnnManager::new(),
73            init_styles: StyleCalculator::default(),
74        }
75    }
76
77    #[inline]
78    fn next_id(&self) -> OpID {
79        self.store.next_id()
80    }
81
82    #[inline]
83    pub fn insert_utf16(&mut self, index: usize, string: &str) {
84        self.insert_inner(index, string, IndexType::Utf16);
85    }
86
87    #[inline]
88    pub fn insert(&mut self, index: usize, string: &str) {
89        self.insert_inner(index, string, IndexType::Utf8);
90    }
91
92    fn insert_inner(&mut self, index: usize, string: &str, index_type: IndexType) {
93        if string.is_empty() {
94            return;
95        }
96
97        fn can_merge_new_slice(
98            elem: &Elem,
99            id: OpID,
100            right: Option<OpID>,
101            slice: &append_only_bytes::BytesSlice,
102        ) -> bool {
103            elem.id.client == id.client
104                && elem.id.counter + elem.atom_len() as Counter == id.counter
105                && elem.right == right
106                && !elem.is_dead()
107                && elem.string.can_merge(slice)
108                && !elem.has_after_anchor()
109        }
110
111        let start = self.bytes.len();
112        self.bytes.push_str(string);
113        let slice = self.bytes.slice(start..);
114        let cache_diff = Some(CacheDiff::new_len_diff(
115            string.len() as isize,
116            get_utf16_len(&slice) as isize,
117        ));
118        let id = self.next_id();
119        if index == 0 {
120            let first_leaf = self.content.first_leaf();
121            let right_origin = self
122                .content
123                .get_node(first_leaf)
124                .elements()
125                .first()
126                .map(|x| x.id);
127            self.store
128                .insert_local(OpContent::new_insert(None, right_origin, slice.clone()));
129            self.content
130                .prepend(Elem::new(id, None, right_origin, slice));
131            return;
132        }
133
134        // need to find left op id
135        let path = self.find_ideal_insert_pos(index, index_type);
136        let left;
137        let right;
138        let op_slice = slice.clone();
139        {
140            // find left and right
141            let mut node = self.content.get_node(path.leaf);
142            let offset = path.offset;
143            let index = path.elem_index;
144            if offset != 0 {
145                left = Some(node.elements()[index].id.inc((offset - 1) as u32));
146            } else {
147                left = Some(node.elements()[index - 1].id_last());
148            }
149            if offset < node.elements()[index].rle_len() {
150                right = Some(node.elements()[index].id.inc(offset as u32));
151            } else if index + 1 < node.elements().len() {
152                right = Some(node.elements()[index + 1].id);
153            } else if let Some(next) = self.content.next_same_level_node(path.leaf) {
154                node = self.content.get_node(next);
155                right = Some(node.elements()[0].id);
156            } else {
157                right = None;
158            }
159        }
160
161        self.content.update_leaf(path.leaf, |elements| {
162            // insert new element
163            debug_assert!(path.elem_index < elements.len());
164            let mut offset = path.offset;
165            let mut index = path.elem_index;
166            if offset == 0 {
167                // ensure not at the beginning of an element
168                assert!(index > 0);
169                index -= 1;
170                offset = elements[index].rle_len();
171            }
172
173            if offset == elements[index].rle_len() {
174                if can_merge_new_slice(&elements[index], id, right, &slice) {
175                    // can merge directly
176                    elements[index].merge_slice(&slice);
177                    self.cursor_map
178                        .update(MoveEvent::new_move(path.leaf, &elements[index]));
179                    return (true, cache_diff);
180                }
181
182                elements.insert(index + 1, Elem::new(id, left, right, slice));
183                self.cursor_map
184                    .update(MoveEvent::new_move(path.leaf, &elements[index + 1]));
185                return (true, cache_diff);
186            }
187
188            // need to split element
189            let right_half = elements[index].split(offset);
190            elements.splice(
191                index + 1..index + 1,
192                [Elem::new(id, left, right, slice), right_half],
193            );
194            self.cursor_map
195                .update(MoveEvent::new_move(path.leaf, &elements[index + 1]));
196            (true, cache_diff)
197        });
198
199        self.store
200            .insert_local(OpContent::new_insert(left, right, op_slice));
201    }
202
203    /// When user insert text at index, there may be tombstones at the given position.
204    /// We need to find the ideal position among the tombstones to insert.
205    /// Insertion at different position may have different styles.
206    ///
207    /// The ideal position is:
208    ///
209    /// - Before tombstones with before anchor
210    /// - After tombstones with after anchor
211    ///
212    /// Sometimes the insertion may not have a ideal position for example an after anchor
213    /// may exist before a before anchor.
214    ///
215    /// The current method is quite straightforward, it will scan from the end backward and stop at
216    /// the first position that is not a tombstone or has an after anchor.
217    ///
218    /// The returned result points to the position the new insertion should be at.
219    /// It uses the rle_len() rather than the content_len().
220    ///
221    /// - rle_len() includes the length of deleted string
222    /// - content_len() does not include the length of deleted string
223    fn find_ideal_insert_pos(&mut self, index: usize, index_type: IndexType) -> QueryResult {
224        let mut path = self.content.query::<IndexFinder>(&(index, index_type));
225        loop {
226            let node = self.content.get_node(path.leaf);
227
228            // avoid offset == 0, as it makes it hard to find `left` for insertion later
229            while path.offset == 0 && path.elem_index > 0 {
230                path.elem_index -= 1;
231                path.offset = node.elements()[path.elem_index].rle_len();
232                if node.elements()[path.elem_index].has_after_anchor() {
233                    break;
234                }
235            }
236
237            // skip tombstones if it does not have after anchor
238            while path.elem_index > 0
239                && node.elements()[path.elem_index].is_dead()
240                && !node.elements()[path.elem_index].has_after_anchor()
241            {
242                path.elem_index -= 1;
243                path.offset = node.elements()[path.elem_index].rle_len();
244            }
245
246            if path.offset == 0 && path.elem_index == 0 {
247                // cannot find `left` for insertion by this, so we need to go to left node
248                while path.offset == 0 && path.elem_index == 0 {
249                    match self.content.prev_same_level_node(path.leaf) {
250                        Some(prev) => {
251                            let node = self.content.get_node(prev);
252                            path.elem_index = node.len();
253                            path.offset = 0;
254                            path.leaf = prev;
255                        }
256                        None => unreachable!(), // we already handled the index == 0, this cannot happen
257                    }
258                }
259            } else {
260                break;
261            }
262        }
263        path
264    }
265
266    pub fn delete_utf16(&mut self, range: impl RangeBounds<usize>) {
267        self.delete_inner(range, IndexType::Utf16);
268    }
269
270    pub fn delete(&mut self, range: impl RangeBounds<usize>) {
271        self.delete_inner(range, IndexType::Utf8);
272    }
273
274    fn delete_inner(&mut self, range: impl RangeBounds<usize>, index_type: IndexType) {
275        let start = match range.start_bound() {
276            Bound::Included(start) => *start,
277            Bound::Excluded(start) => *start + 1,
278            Bound::Unbounded => 0,
279        };
280        let end = match range.end_bound() {
281            Bound::Included(end) => *end + 1,
282            Bound::Excluded(end) => *end,
283            Bound::Unbounded => self.len(),
284        };
285
286        if start == end {
287            return;
288        }
289
290        let start_result = self.content.query::<IndexFinder>(&(start, index_type));
291        let end_result = self.content.query::<IndexFinder>(&(end, index_type));
292        let mut deleted = SmallVec::<[(OpID, usize); 4]>::new();
293
294        // deletions don't remove things from the tree, they just mark them as dead
295        let mut delete_fn = |elem: &mut Elem| {
296            if elem.local_delete() {
297                deleted.push((elem.id, elem.rle_len()));
298                (-(elem.rle_len() as isize), -(elem.utf16_len as isize))
299            } else {
300                (0, 0)
301            }
302        };
303        self.content.update_with_filter(
304            &start_result..&end_result,
305            &mut |slice| {
306                match (slice.start, slice.end) {
307                    (Some((start_idx, start_offset)), Some((end_idx, end_offset)))
308                        if start_idx == end_idx =>
309                    {
310                        // delete within one element
311                        if start_idx >= slice.elements.len() {
312                            return (false, None);
313                        }
314
315                        let elem = &mut slice.elements[start_idx];
316                        if elem.is_dead() {
317                            return (false, None);
318                        }
319
320                        let (additions, diff) =
321                            elem.update(start_offset, end_offset, &mut delete_fn);
322                        let (len_diff, utf16_len_diff) = diff.unwrap();
323                        if !additions.is_empty() {
324                            let len = additions.len();
325                            slice
326                                .elements
327                                .splice(start_idx + 1..start_idx + 1, additions);
328                            Elem::try_merge_arr(slice.elements, start_idx, len + 1);
329                        } else if start_idx > 0 {
330                            Elem::try_merge_arr(slice.elements, start_idx - 1, 2);
331                        } else {
332                            Elem::try_merge_arr(slice.elements, start_idx, 1);
333                        }
334
335                        return (
336                            true,
337                            Some(CacheDiff::new_len_diff(len_diff, utf16_len_diff)),
338                        );
339                    }
340                    _ => {}
341                }
342
343                let mut len_diff = 0;
344                let mut utf16_len_diff = 0;
345                let mut end = match slice.end {
346                    Some((end_idx, end_offset)) => {
347                        if end_offset == 0 {
348                            end_idx
349                        } else {
350                            let elem = &mut slice.elements[end_idx];
351                            if !elem.is_dead() {
352                                let (additions, diff) = elem.update(0, end_offset, &mut delete_fn);
353                                if !additions.is_empty() {
354                                    slice.elements.splice(end_idx + 1..end_idx + 1, additions);
355                                }
356                                len_diff += diff.unwrap().0;
357                                utf16_len_diff += diff.unwrap().1;
358                            }
359                            end_idx + 1
360                        }
361                    }
362                    None => slice.elements.len(),
363                };
364
365                let start = match slice.start {
366                    Some((start_idx, start_offset)) => {
367                        if start_offset == 0 {
368                            start_idx
369                        } else {
370                            let elem = &mut slice.elements[start_idx];
371                            if !elem.is_dead() && start_offset < elem.rle_len() {
372                                let (additions, diff) =
373                                    elem.update(start_offset, elem.rle_len(), &mut delete_fn);
374                                if !additions.is_empty() {
375                                    end += additions.len();
376                                    slice
377                                        .elements
378                                        .splice(start_idx + 1..start_idx + 1, additions);
379                                }
380                                len_diff += diff.unwrap().0;
381                                utf16_len_diff += diff.unwrap().1;
382                            }
383                            start_idx + 1
384                        }
385                    }
386                    None => 0,
387                };
388
389                for elem in slice.elements[start..end].iter_mut() {
390                    let diff = delete_fn(elem);
391                    len_diff += diff.0;
392                    utf16_len_diff += diff.1;
393                }
394
395                let begin = start.saturating_sub(2);
396                Elem::try_merge_arr(slice.elements, begin, end + 2 - begin);
397                (
398                    true,
399                    Some(CacheDiff::new_len_diff(len_diff, utf16_len_diff)),
400                )
401            },
402            &|cache| cache.len > 0,
403        );
404
405        for (start, len) in deleted {
406            let op = self
407                .store
408                .insert_local(OpContent::new_delete(start, len as i32));
409            // self.cursor_map.register_del(op);
410        }
411    }
412
413    /// Annotate the given range with style.
414    ///
415    /// Under the hood, it will assign anchors to the characters at the given start pos and end pos.
416    /// The range start OpID and end OpID are the OpID of those characters;
417    ///
418    /// Although the arg is a range bound, a `..` range doesn't necessary means the start anchor
419    /// and the end anchor is None. Because the range is also depends on the anchor type.
420    pub fn annotate_utf16(&mut self, range: impl RangeBounds<usize>, style: Style) {
421        self.annotate_inner(range, style, IndexType::Utf16)
422    }
423
424    /// Annotate the given range with style.
425    ///
426    /// Under the hood, it will assign anchors to the characters at the given start pos and end pos.
427    /// The range start OpID and end OpID are the OpID of those characters;
428    ///
429    /// Although the arg is a range bound, a `..` range doesn't necessary means the start anchor
430    /// and the end anchor is None. Because the range is also depends on the anchor type.
431    pub fn annotate(&mut self, range: impl RangeBounds<usize>, style: Style) {
432        self.annotate_inner(range, style, IndexType::Utf8)
433    }
434
435    fn annotate_inner(
436        &mut self,
437        range: impl RangeBounds<usize>,
438        style: Style,
439        index_type: IndexType,
440    ) {
441        let start = match range.start_bound() {
442            Bound::Included(start) => *start,
443            Bound::Excluded(start) => *start + 1,
444            Bound::Unbounded => 0,
445        };
446        let mut inclusive_end = match range.end_bound() {
447            Bound::Included(end) => *end,
448            Bound::Excluded(end) => *end - 1,
449            Bound::Unbounded => self.len_with(index_type) - 1,
450        };
451
452        if inclusive_end < start {
453            return;
454        }
455
456        inclusive_end = inclusive_end.min(self.len_with(index_type) - 1);
457        let start = if style.start_type == AnchorType::Before {
458            Some(self.content.query::<IndexFinder>(&(start, index_type)))
459        } else if start == 0 {
460            None
461        } else {
462            Some(
463                self.content
464                    .query::<IndexFinder>(&(start.saturating_sub(1), index_type)),
465            )
466        };
467        let inclusive_end = if style.end_type == AnchorType::Before {
468            if inclusive_end + 1 >= self.len_with(index_type) {
469                None
470            } else {
471                Some(
472                    self.content
473                        .query::<IndexFinder>(&(inclusive_end + 1, index_type)),
474                )
475            }
476        } else {
477            Some(
478                self.content
479                    .query::<IndexFinder>(&(inclusive_end, index_type)),
480            )
481        };
482
483        let start_id = start.map(|start| self.get_id_at_pos(start));
484        let end_id = inclusive_end.map(|end| self.get_id_at_pos(end));
485        let id = self.next_id();
486        let lamport = self.next_lamport();
487        let ann = Annotation {
488            id,
489            range_lamport: (lamport, id),
490            range: crate::AnchorRange {
491                start: Anchor {
492                    id: start_id,
493                    type_: style.start_type,
494                },
495                end: Anchor {
496                    id: end_id,
497                    type_: style.end_type,
498                },
499            },
500            behavior: style.behavior,
501            type_: style.type_.clone(),
502            meta: None,
503        };
504
505        let ann = Arc::new(ann);
506        let ann_idx = self.ann.register(ann.clone());
507
508        // insert new annotation idx to content tree
509        match (start, inclusive_end) {
510            (Some(start), Some(end)) => {
511                self.annotate_given_range(start, end, ann_idx, style);
512            }
513            (Some(start), None) => {
514                self.content.update_leaf(start.leaf, |elements| {
515                    ann::insert_anchor_to_char(
516                        elements,
517                        start.elem_index,
518                        start.offset,
519                        ann_idx,
520                        style.start_type,
521                        true,
522                    );
523                    (true, Some(AnchorSetDiff::from_ann(ann_idx, true).into()))
524                });
525                // the target ends when the doc ends,
526                // so we do not need to insert an end anchor
527            }
528            (None, Some(end)) => {
529                self.content.update_leaf(end.leaf, |elements| {
530                    ann::insert_anchor_to_char(
531                        elements,
532                        end.elem_index,
533                        end.offset,
534                        ann_idx,
535                        style.end_type,
536                        false,
537                    );
538                    (true, Some(AnchorSetDiff::from_ann(ann_idx, false).into()))
539                });
540                self.init_styles.insert_start(ann_idx);
541            }
542            (None, None) => {
543                self.init_styles.insert_start(ann_idx);
544                // the target ends when the doc ends, so we do not need to insert an end anchor
545            }
546        }
547
548        // register op to store
549        let op = self.store.insert_local(OpContent::new_ann(ann));
550        // self.cursor_map.register_ann(op);
551    }
552
553    fn annotate_given_range(
554        &mut self,
555        start: QueryResult,
556        end: QueryResult,
557        ann_idx: AnnIdx,
558        style: Style,
559    ) {
560        self.content
561            .update2_leaf(start.leaf, end.leaf, |elements, from| {
562                match from {
563                    Some(leaf) => {
564                        if leaf == end.leaf {
565                            // insert end anchor
566                            ann::insert_anchor_to_char(
567                                elements,
568                                end.elem_index,
569                                end.offset,
570                                ann_idx,
571                                style.end_type,
572                                false,
573                            );
574                        } else {
575                            // insert start anchor
576                            debug_assert_eq!(leaf, start.leaf);
577                            ann::insert_anchor_to_char(
578                                elements,
579                                start.elem_index,
580                                start.offset,
581                                ann_idx,
582                                style.start_type,
583                                true,
584                            );
585                        }
586
587                        true
588                    }
589                    None => {
590                        if start.elem_index == end.elem_index {
591                            assert_ne!(end.offset, elements[start.elem_index].rle_len());
592                            let new = insert_anchors_at_same_elem(
593                                &mut elements[start.elem_index],
594                                start.offset,
595                                end.offset,
596                                ann_idx,
597                                style.start_type,
598                                style.end_type,
599                            );
600
601                            elements.splice(start.elem_index + 1..start.elem_index + 1, new);
602                            return true;
603                        }
604
605                        assert!(end.elem_index > start.elem_index);
606                        ann::insert_anchor_to_char(
607                            elements,
608                            end.elem_index,
609                            end.offset,
610                            ann_idx,
611                            style.end_type,
612                            false,
613                        );
614                        ann::insert_anchor_to_char(
615                            elements,
616                            start.elem_index,
617                            start.offset,
618                            ann_idx,
619                            style.start_type,
620                            true,
621                        );
622
623                        true
624                    }
625                }
626            })
627    }
628
629    fn get_id_at_pos(&self, pos: QueryResult) -> OpID {
630        let node = self.content.get_node(pos.leaf);
631        // elem_index may be > elements.len()?
632        let elem = &node.elements()[pos.elem_index];
633        assert!(pos.offset < elem.rle_len());
634        elem.id.inc(pos.offset as u32)
635    }
636
637    pub fn iter(&self) -> impl Iterator<Item = Span> + '_ {
638        iter::Iter::new(self)
639    }
640
641    pub fn get_spans(&self) -> Vec<Span> {
642        self.iter().collect()
643    }
644
645    pub fn iter_range(&self, _range: impl RangeBounds<usize>) {
646        todo!()
647    }
648
649    pub fn len(&self) -> usize {
650        self.content.root_cache().len as usize
651    }
652
653    pub fn len_utf16(&self) -> usize {
654        self.content.root_cache().utf16_len as usize
655    }
656
657    fn len_with(&self, index_type: IndexType) -> usize {
658        match index_type {
659            IndexType::Utf8 => self.content.root_cache().len as usize,
660            IndexType::Utf16 => self.content.root_cache().utf16_len as usize,
661        }
662    }
663
664    pub fn is_empty(&self) -> bool {
665        self.len() == 0
666    }
667
668    pub fn utf16_len(&self) -> usize {
669        self.content.root_cache().utf16_len as usize
670    }
671
672    pub fn export(&self, vv: &VersionVector) -> Vec<u8> {
673        encode(self.store.export(vv))
674    }
675
676    pub fn import(&mut self, data: &[u8]) {
677        self.import_inner(decode(data));
678    }
679
680    fn apply(&mut self, op: Op) {
681        debug_log::group!("apply op");
682        'apply: {
683            match &op.content {
684                OpContent::Ann(ann) => {
685                    let ann_idx = self.ann.register(ann.clone());
686                    match ann.range.start.id {
687                        Some(start_id) => {
688                            let cursor = self.find_cursor(start_id);
689                            self.content.update_leaf(cursor.leaf, |elements| {
690                                let index = cursor.elem_index;
691                                let offset = cursor.offset;
692                                let type_ = ann.range.start.type_;
693                                let is_start = true;
694                                insert_anchor_to_char(
695                                    elements, index, offset, ann_idx, type_, is_start,
696                                );
697                                (
698                                    true,
699                                    Some(AnchorSetDiff::from_ann(ann_idx, is_start).into()),
700                                )
701                            });
702                        }
703                        None => {
704                            self.init_styles.insert_start(ann_idx);
705                        }
706                    }
707
708                    if let Some(end_id) = ann.range.end.id {
709                        let cursor = self.find_cursor(end_id);
710                        self.content.update_leaf(cursor.leaf, |elements| {
711                            let index = cursor.elem_index;
712                            let offset = cursor.offset;
713                            let type_ = ann.range.end.type_;
714                            let is_start = false;
715                            insert_anchor_to_char(
716                                elements, index, offset, ann_idx, type_, is_start,
717                            );
718                            (
719                                true,
720                                Some(AnchorSetDiff::from_ann(ann_idx, is_start).into()),
721                            )
722                        });
723                    }
724                }
725                OpContent::Text(text) => {
726                    let right = match self.find_right(text, &op) {
727                        Some(value) => value,
728                        None => break 'apply,
729                    };
730
731                    if let Some(right) = right {
732                        self.content.insert_by_query_result(
733                            right,
734                            Elem::new(op.id, text.left, text.right, text.text.clone()),
735                        );
736                    } else {
737                        self.content.push(Elem::new(
738                            op.id,
739                            text.left,
740                            text.right,
741                            text.text.clone(),
742                        ));
743                    }
744                }
745                OpContent::Del(del) => {
746                    let del = del.positive();
747                    self.update_elem_in_id_range(del.start, del.len as usize, |elem| {
748                        elem.apply_remote_delete()
749                    })
750                }
751            }
752        }
753
754        debug_log::group_end!();
755    }
756
757    fn find_right(&mut self, elt: &op::TextInsertOp, op: &Op) -> Option<Option<QueryResult>> {
758        // We use Fugue algorithm here, it has the property of "maximal non-interleaving"
759        // See paper *The Art of the Fugue: Minimizing Interleaving in Collaborative Text Editing*
760        let scan_start = self.find_next_cursor_of(elt.left);
761        if scan_start.is_none() {
762            // insert to the last
763            self.content
764                .push(Elem::new(op.id, elt.left, elt.right, elt.text.clone()));
765            return None;
766        }
767        let scan_start = scan_start.unwrap();
768        let iterator = self.content.iter_range(scan_start..);
769        let elt_left_origin = elt.left;
770        let elt_right_origin = elt.right;
771        let mut elt_right_parent: Option<Option<QueryResult>> = None; // calc lazily
772        let mut visited_id_spans: SmallVec<[IdSpan; 8]> = SmallVec::new();
773        let mut left = None;
774        let mut scanning = false;
775        for o_slice in iterator {
776            // a slice may contains several ops
777            let offset = o_slice.start.unwrap_or(0);
778            let o_left_origin = if offset == 0 {
779                o_slice.elem.left
780            } else {
781                Some(o_slice.elem.id.inc(offset as u32 - 1))
782            };
783
784            let end_offset = if let Some(right) = elt.right {
785                if o_slice.elem.contains_id(right) {
786                    (right.counter - o_slice.elem.id.counter) as usize
787                } else {
788                    o_slice.elem.rle_len()
789                }
790            } else {
791                o_slice.elem.rle_len()
792            };
793
794            if end_offset == offset {
795                break;
796            }
797            // o.leftOrigin < elt.leftOrigin
798            if o_left_origin != elt.left
799                && (o_left_origin.is_none()
800                    || visited_id_spans
801                        .iter()
802                        .all(|x| !x.contains(o_left_origin.unwrap())))
803            {
804                break;
805            }
806
807            visited_id_spans.push(IdSpan::new(
808                o_slice.elem.id.inc(offset as u32),
809                end_offset - offset,
810            ));
811
812            if o_left_origin == elt.left {
813                let o_right_origin = o_slice.elem.right;
814                if o_right_origin == elt_right_origin {
815                    if o_slice.elem.id.client > op.id.client {
816                        break;
817                    } else {
818                        scanning = false;
819                    }
820                } else {
821                    // We only need to compare the first element's right parent.
822                    // And the first element's right parent is the same as the slice's right parent
823                    // because they they share the rightOrigin
824                    let o_right_cursor = o_slice.elem.right.map(|x| self.find_cursor(x));
825                    let o_right_parent = o_right_cursor.and_then(|x| {
826                        if self.find_left_origin(x) == elt_left_origin {
827                            Some(x)
828                        } else {
829                            None
830                        }
831                    });
832
833                    if elt_right_parent.is_none() {
834                        let elt_right_cursor = elt.right.map(|x| self.find_cursor(x));
835                        elt_right_parent = Some(elt_right_cursor.and_then(|x| {
836                            if self.find_left_origin(x) == elt_left_origin {
837                                Some(x)
838                            } else {
839                                None
840                            }
841                        }));
842                    }
843
844                    match self.cmp_right_parent_pos(o_right_parent, elt_right_parent.unwrap()) {
845                        Ordering::Less => {
846                            scanning = true;
847                        }
848                        Ordering::Equal if o_slice.elem.id.client > op.id.client => {
849                            break;
850                        }
851                        _ => {
852                            scanning = false;
853                        }
854                    }
855                }
856            }
857
858            if !scanning {
859                // set before to the last element
860                let mut path = *o_slice.path();
861                path.offset = end_offset - 1;
862                left = Some(path);
863            }
864        }
865
866        // convert left to right
867        match left {
868            Some(left) => Some(self.content.shift_path_by_one_offset(left)),
869            None => Some(Some(scan_start)),
870        }
871    }
872
873    #[inline]
874    fn cmp_right_parent_pos(&self, a: Option<QueryResult>, b: Option<QueryResult>) -> Ordering {
875        match (a, b) {
876            (None, None) => Ordering::Equal,
877            (None, Some(_)) => Ordering::Greater,
878            (Some(_), None) => Ordering::Less,
879            (Some(a), Some(b)) => self.content.compare_pos(a, b),
880        }
881    }
882
883    /// Merge data from other data into self
884    pub fn merge(&mut self, other: &Self) {
885        let vv = self.store.vv();
886        let exported = other.export(&vv);
887        let exported = decode(&exported);
888        if cfg!(debug_assertions) || cfg!(feature = "test") {
889            let expected = other.store.export(&vv);
890            assert_eq!(exported, expected);
891        }
892
893        self.import_inner(exported);
894    }
895
896    fn import_inner(&mut self, exported: FxHashMap<ClientID, Vec<Op>>) {
897        let mut all_ops = Vec::new();
898        for (_, ops) in exported {
899            for mut op in ops {
900                let op = match self.store.can_apply(&op) {
901                    op::CanApply::Yes => op,
902                    op::CanApply::Trim(len) => {
903                        op.slice_(len as usize..);
904                        op
905                    }
906                    op::CanApply::Pending => {
907                        self.pending_ops.push(op);
908                        continue;
909                    }
910                    op::CanApply::Seen => {
911                        continue;
912                    }
913                };
914                self.store.insert(op.clone());
915                all_ops.push(op);
916            }
917        }
918        all_ops.sort_by(|a, b| a.lamport.cmp(&b.lamport));
919
920        // Handling delete ops afterwards can guarantee the causal order.
921        // Otherwise, the delete op may be applied before the insert op
922        // because of the merges of delete ops.
923        let mut deletions = Vec::new();
924        for op in all_ops.iter() {
925            if let OpContent::Del(_) = &op.content {
926                deletions.push(op.clone());
927            } else {
928                self.apply(op.clone());
929            }
930        }
931
932        for op in deletions {
933            self.apply(op);
934        }
935    }
936
937    pub fn version(&self) -> VersionVector {
938        self.store.vv()
939    }
940
941    fn update_elem_in_id_range(
942        &mut self,
943        mut id: OpID,
944        mut len: usize,
945        mut f: impl FnMut(&mut Elem),
946    ) {
947        // debug_log::group!("update");
948        // debug_log::debug_dbg!(id, len);
949        // debug_log::debug_dbg!(&self.content);
950        // debug_log::debug_dbg!(&self.cursor_map);
951        // debug_log::group_end!();
952        while len > 0 {
953            let (insert_leaf, mut leaf_del_len) = self.cursor_map.get_insert(id).unwrap();
954            leaf_del_len = leaf_del_len.min(len);
955            let leaf_del_len = leaf_del_len;
956            let mut left_len = leaf_del_len;
957            // Perf: we may optimize this by only update the cache once
958            self.content.update_leaf(insert_leaf, |elements| {
959                // dbg!(&elements, leaf_del_len);
960                // there may be many pieces need to be updated inside one leaf node
961                let mut index = 0;
962                loop {
963                    let elem = &elements[index];
964                    if !elem.overlap(id, leaf_del_len) {
965                        index += 1;
966                        continue;
967                    }
968
969                    let offset = if id.counter > elem.id.counter {
970                        (id.counter - elem.id.counter) as usize
971                    } else {
972                        0
973                    };
974                    let end = elem
975                        .rle_len()
976                        .min((id.counter + leaf_del_len as Counter - elem.id.counter) as usize);
977                    let (new, _) = elements[index].update(offset, end, &mut f);
978                    left_len -= end - offset;
979                    if !new.is_empty() {
980                        let new_len = new.len();
981                        elements.splice(index + 1..index + 1, new);
982                        index += new_len;
983                    }
984                    index += 1;
985                    if left_len == 0 {
986                        break;
987                    }
988                }
989                assert_eq!(left_len, 0);
990                // TODO: Perf can be optimized by merge the cache diff from f
991                (true, None)
992            });
993            id.counter += leaf_del_len as Counter;
994            len -= leaf_del_len;
995        }
996    }
997
998    fn find_cursor(&self, id: OpID) -> QueryResult {
999        // TODO: this method may use a hint to speed up
1000        let (insert_leaf, _) = self
1001            .cursor_map
1002            .get_insert(id)
1003            .expect("Cannot find target id");
1004        let node = self.content.get_node(insert_leaf);
1005        let mut elem_index = 0;
1006        let elements = &node.elements();
1007        while !elements[elem_index].contains_id(id) {
1008            // if range out of bound, then cursor_map is off
1009            elem_index += 1;
1010        }
1011
1012        let offset = (id.counter - elements[elem_index].id.counter) as usize;
1013        assert!(offset < elements[elem_index].atom_len());
1014        QueryResult {
1015            leaf: insert_leaf,
1016            elem_index,
1017            offset,
1018            found: true,
1019        }
1020    }
1021
1022    fn find_left_origin(&self, cursor: QueryResult) -> Option<OpID> {
1023        let offset = cursor.offset;
1024        let elem_index = cursor.elem_index;
1025        let node = self.content.get_node(cursor.leaf);
1026        let elements = node.elements();
1027        if offset == 0 {
1028            elements[elem_index].left
1029        } else {
1030            Some(elements[elem_index].id.inc(offset as u32 - 1))
1031        }
1032    }
1033
1034    fn find_next_cursor_of(&self, id: Option<OpID>) -> Option<QueryResult> {
1035        match id {
1036            Some(id) => {
1037                let cursor = self.find_cursor(id);
1038                self.content.shift_path_by_one_offset(cursor)
1039            }
1040            None => Some(QueryResult {
1041                leaf: self.content.first_leaf(),
1042                elem_index: 0,
1043                offset: 0,
1044                found: true,
1045            }),
1046        }
1047    }
1048
1049    #[inline(always)]
1050    fn next_lamport(&self) -> u32 {
1051        self.store.next_lamport()
1052    }
1053
1054    #[inline]
1055    #[allow(unused)]
1056    pub(crate) fn check(&self) {
1057        self.content.check();
1058    }
1059
1060    pub fn debug_log(&self, include_content: bool) {
1061        debug_log::debug_log!("Text len = {} (utf16={})", self.len(), self.utf16_len());
1062        debug_log::debug_log!("Nodes len = {}", self.content.node_len());
1063        debug_log::debug_log!("Op len = {}", self.store.op_len());
1064        if include_content {
1065            let mut content_inner = format!("{:#?}", &self.content);
1066            const MAX: usize = 100000;
1067            if content_inner.len() > MAX {
1068                for new_len in MAX.. {
1069                    if content_inner.is_char_boundary(new_len) {
1070                        content_inner.truncate(new_len);
1071                        break;
1072                    }
1073                }
1074            }
1075            debug_log::debug_log!("ContentTree = {}", content_inner);
1076            // println!("Text = {}", self);
1077            debug_log::debug_log!("Store = {:#?}", &self.store);
1078        }
1079    }
1080
1081    pub fn check_no_mergeable_neighbor(&self) {
1082        let mut leaf_idx = Some(self.content.first_leaf());
1083        while let Some(leaf) = leaf_idx {
1084            let node = self.content.get_node(leaf);
1085            let elements = node.elements();
1086            for i in 0..elements.len() - 1 {
1087                if elements[i].can_merge(&elements[i + 1]) {
1088                    self.debug_log(false);
1089                    panic!(
1090                        "Found mergeable neighbor: \n{:#?} \n{:#?}",
1091                        elements[i],
1092                        elements[i + 1]
1093                    );
1094                }
1095            }
1096
1097            leaf_idx = self.content.next_same_level_node(leaf);
1098        }
1099    }
1100}
1101
1102impl Display for RichText {
1103    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1104        for span in self.content.iter() {
1105            if span.is_dead() {
1106                continue;
1107            }
1108
1109            f.write_str(std::str::from_utf8(&span.string).unwrap())?;
1110        }
1111
1112        Ok(())
1113    }
1114}