loro_internal/state/
tree_state.rs

1use either::Either;
2use enum_as_inner::EnumAsInner;
3use fractional_index::FractionalIndex;
4use fxhash::{FxHashMap, FxHashSet};
5use itertools::Itertools;
6use loro_common::{
7    ContainerID, IdFull, IdLp, LoroError, LoroResult, LoroTreeError, LoroValue, PeerID, TreeID,
8    DELETED_TREE_ROOT, ID,
9};
10use rand::SeedableRng;
11use rle::HasLength;
12use serde::Serialize;
13use std::collections::VecDeque;
14use std::fmt::Debug;
15use std::ops::{Deref, DerefMut};
16use std::sync::Weak;
17
18use super::{ApplyLocalOpReturn, ContainerState, DiffApplyContext};
19use crate::configure::Configure;
20use crate::container::idx::ContainerIdx;
21use crate::delta::{TreeDiff, TreeDiffItem, TreeExternalDiff};
22use crate::diff_calc::DiffMode;
23use crate::encoding::{EncodeMode, StateSnapshotDecodeContext, StateSnapshotEncoder};
24use crate::event::InternalDiff;
25use crate::op::Op;
26use crate::{
27    container::tree::tree_op::TreeOp,
28    delta::TreeInternalDiff,
29    event::{Diff, Index},
30    op::RawOp,
31};
32use crate::{DocState, LoroDocInner};
33
34#[derive(Clone, Debug, EnumAsInner)]
35pub enum TreeFractionalIndexConfigInner {
36    GenerateFractionalIndex {
37        jitter: u8,
38        rng: Box<rand::rngs::StdRng>,
39    },
40    MoveDisabled,
41}
42
43/// The state of movable tree.
44///
45/// using flat representation
46#[derive(Debug, Clone)]
47pub struct TreeState {
48    idx: ContainerIdx,
49    trees: FxHashMap<TreeID, TreeStateNode>,
50    children: TreeChildrenCache,
51    fractional_index_config: TreeFractionalIndexConfigInner,
52    peer_id: PeerID,
53}
54
55#[derive(Debug, Clone, PartialEq, Eq)]
56pub(crate) struct TreeStateNode {
57    pub parent: TreeParentId,
58    pub position: Option<FractionalIndex>,
59    pub last_move_op: IdFull,
60}
61
62#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
63pub(crate) struct NodePosition {
64    pub(crate) position: FractionalIndex,
65    // different nodes created by a peer may have the same position
66    // when we merge updates that cause cycles.
67    // for example [::fuzz::test::test_tree::same_peer_have_same_position()]
68    pub(crate) idlp: IdLp,
69}
70
71#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, EnumAsInner, Serialize)]
72pub enum TreeParentId {
73    Node(TreeID),
74    Root,
75    Deleted,
76    // We use `Unexist` as the old parent of a new node created
77    // so we can infer the retreat internal diff is `Uncreate`
78    Unexist,
79}
80
81impl From<Option<TreeID>> for TreeParentId {
82    fn from(id: Option<TreeID>) -> Self {
83        match id {
84            Some(id) => {
85                if TreeID::is_deleted_root(&id) {
86                    TreeParentId::Deleted
87                } else {
88                    TreeParentId::Node(id)
89                }
90            }
91            None => TreeParentId::Root,
92        }
93    }
94}
95
96impl From<TreeID> for TreeParentId {
97    fn from(id: TreeID) -> Self {
98        if TreeID::is_deleted_root(&id) {
99            TreeParentId::Deleted
100        } else {
101            TreeParentId::Node(id)
102        }
103    }
104}
105
106impl From<&TreeID> for TreeParentId {
107    fn from(id: &TreeID) -> Self {
108        if TreeID::is_deleted_root(id) {
109            TreeParentId::Deleted
110        } else {
111            TreeParentId::Node(*id)
112        }
113    }
114}
115
116impl TreeParentId {
117    pub fn tree_id(&self) -> Option<TreeID> {
118        match self {
119            TreeParentId::Node(id) => Some(*id),
120            TreeParentId::Root => None,
121            TreeParentId::Deleted => Some(DELETED_TREE_ROOT),
122            TreeParentId::Unexist => unreachable!(),
123        }
124    }
125}
126
127#[derive(Debug, Clone)]
128enum NodeChildren {
129    Vec(Vec<(NodePosition, TreeID)>),
130    BTree(btree::ChildTree),
131}
132
133impl Default for NodeChildren {
134    fn default() -> Self {
135        NodeChildren::Vec(vec![])
136    }
137}
138
139impl NodeChildren {
140    const MAX_SIZE_FOR_ARRAY: usize = 16;
141    fn get_index_by_child_id(&self, target: &TreeID) -> Option<usize> {
142        match self {
143            NodeChildren::Vec(v) => v.iter().position(|(_, id)| id == target),
144            NodeChildren::BTree(btree) => btree.id_to_index(target),
145        }
146    }
147
148    fn get_last_insert_index_by_position(
149        &self,
150        node_position: &NodePosition,
151    ) -> Result<usize, usize> {
152        match self {
153            NodeChildren::Vec(v) => v.binary_search_by_key(&node_position, |x| &x.0),
154            NodeChildren::BTree(btree) => btree.get_index_by_node_position(node_position),
155        }
156    }
157
158    fn get_node_position_at(&self, pos: usize) -> Option<&NodePosition> {
159        match self {
160            NodeChildren::Vec(v) => v.get(pos).map(|x| &x.0),
161            NodeChildren::BTree(btree) => btree.get_elem_at(pos).map(|x| x.pos.as_ref()),
162        }
163    }
164
165    fn get_elem_at(&self, pos: usize) -> Option<(&NodePosition, &TreeID)> {
166        match self {
167            NodeChildren::Vec(v) => v.get(pos).map(|x| (&x.0, &x.1)),
168            NodeChildren::BTree(btree) => btree.get_elem_at(pos).map(|x| (x.pos.as_ref(), &x.id)),
169        }
170    }
171
172    fn generate_fi_at(&self, pos: usize, target: &TreeID) -> FractionalIndexGenResult {
173        let mut reset_ids = vec![];
174        let mut left = None;
175        let mut next_right = None;
176        {
177            let mut right = None;
178            let children_num = self.len();
179            if children_num == 0 {
180                return FractionalIndexGenResult::Ok(FractionalIndex::default());
181            }
182
183            if pos > 0 {
184                left = self.get_node_position_at(pos - 1);
185            }
186            if pos < children_num {
187                right = self.get_elem_at(pos);
188            }
189
190            let left_fi = left.map(|x| &x.position);
191            // if left and right have the same fractional indexes, we need to scan further to
192            // find all the ids that need to be reset
193            if let Some(left_fi) = left_fi {
194                if Some(left_fi) == right.map(|x| &x.0.position) {
195                    // TODO: the min length between left and right
196                    reset_ids.push(*right.unwrap().1);
197                    for i in (pos + 1)..children_num {
198                        let this_position =
199                            self.get_node_position_at(i).map(|x| &x.position).unwrap();
200                        if this_position == left_fi {
201                            reset_ids.push(*self.get_elem_at(i).unwrap().1);
202                        } else {
203                            next_right = Some(this_position.clone());
204                            break;
205                        }
206                    }
207                }
208            }
209
210            if reset_ids.is_empty() {
211                return FractionalIndexGenResult::Ok(
212                    FractionalIndex::new(left.map(|x| &x.position), right.map(|x| &x.0.position))
213                        .unwrap(),
214                );
215            }
216        }
217        let positions = FractionalIndex::generate_n_evenly(
218            left.map(|x| &x.position),
219            next_right.as_ref(),
220            reset_ids.len() + 1,
221        )
222        .unwrap();
223        FractionalIndexGenResult::Rearrange(
224            Some(*target)
225                .into_iter()
226                .chain(reset_ids)
227                .zip(positions)
228                .collect(),
229        )
230    }
231
232    fn get_id_at(&self, pos: usize) -> Option<TreeID> {
233        match self {
234            NodeChildren::Vec(v) => v.get(pos).map(|x| x.1),
235            NodeChildren::BTree(btree) => btree.get_elem_at(pos).map(|x| x.id),
236        }
237    }
238
239    fn delete_child(&mut self, target: &TreeID) {
240        match self {
241            NodeChildren::Vec(v) => {
242                v.retain(|(_, id)| id != target);
243            }
244            NodeChildren::BTree(v) => {
245                v.delete_child(target);
246            }
247        }
248    }
249
250    fn upgrade(&mut self) {
251        match self {
252            NodeChildren::Vec(v) => {
253                let mut btree = btree::ChildTree::new();
254                for (pos, id) in v.drain(..) {
255                    btree.insert_child(pos, id);
256                }
257
258                *self = NodeChildren::BTree(btree);
259            }
260            NodeChildren::BTree(_) => unreachable!(),
261        }
262    }
263
264    fn insert_child(&mut self, pos: NodePosition, id: TreeID) {
265        match self {
266            NodeChildren::Vec(v) => {
267                if v.len() >= Self::MAX_SIZE_FOR_ARRAY {
268                    self.upgrade();
269                    return self.insert_child(pos, id);
270                }
271
272                let r = v.binary_search_by(|(target, _)| target.cmp(&pos));
273                match r {
274                    Ok(_) => unreachable!(),
275                    Err(i) => {
276                        v.insert(i, (pos, id));
277                    }
278                }
279            }
280            NodeChildren::BTree(v) => {
281                v.insert_child(pos, id);
282            }
283        }
284    }
285
286    fn push_child_in_order(&mut self, pos: NodePosition, id: TreeID) {
287        match self {
288            NodeChildren::Vec(v) => {
289                if v.len() >= Self::MAX_SIZE_FOR_ARRAY {
290                    self.upgrade();
291                    return self.push_child_in_order(pos, id);
292                }
293
294                if let Some(last) = v.last() {
295                    assert!(last.0 < pos);
296                }
297                v.push((pos, id));
298            }
299            NodeChildren::BTree(v) => {
300                v.push_child_in_order(pos, id);
301            }
302        }
303    }
304
305    fn len(&self) -> usize {
306        match self {
307            NodeChildren::Vec(v) => v.len(),
308            NodeChildren::BTree(v) => v.len(),
309        }
310    }
311
312    fn has_child(&self, node_position: &NodePosition) -> bool {
313        match self {
314            NodeChildren::Vec(v) => v
315                .binary_search_by(|(target, _)| target.cmp(node_position))
316                .is_ok(),
317            NodeChildren::BTree(v) => v.has_child(node_position),
318        }
319    }
320
321    fn iter(&self) -> impl Iterator<Item = (&NodePosition, &TreeID)> {
322        match self {
323            NodeChildren::Vec(v) => Either::Left(v.iter().map(|x| (&x.0, &x.1))),
324            NodeChildren::BTree(t) => Either::Right(t.iter()),
325        }
326    }
327}
328
329#[derive(Clone, Default)]
330struct TreeChildrenCache(FxHashMap<TreeParentId, NodeChildren>);
331
332mod btree {
333    use std::{cmp::Ordering, ops::Range, sync::Arc};
334
335    use fxhash::FxHashMap;
336    use generic_btree::{
337        rle::{CanRemove, HasLength, Mergeable, Sliceable, TryInsert},
338        BTree, BTreeTrait, Cursor, FindResult, LeafIndex, LengthFinder, Query, UseLengthFinder,
339    };
340    use loro_common::TreeID;
341
342    use super::NodePosition;
343
344    struct ChildTreeTrait;
345    #[derive(Debug, Clone)]
346    pub(super) struct ChildTree {
347        tree: BTree<ChildTreeTrait>,
348        id_to_leaf_index: FxHashMap<TreeID, LeafIndex>,
349    }
350
351    impl ChildTree {
352        pub(super) fn new() -> Self {
353            Self {
354                tree: BTree::new(),
355                id_to_leaf_index: FxHashMap::default(),
356            }
357        }
358
359        pub(super) fn insert_child(&mut self, pos: NodePosition, id: TreeID) {
360            let (c, _) = self.tree.insert::<KeyQuery>(
361                &pos,
362                Elem {
363                    pos: Arc::new(pos.clone()),
364                    id,
365                },
366            );
367
368            self.id_to_leaf_index.insert(id, c.leaf);
369        }
370
371        pub(super) fn push_child_in_order(&mut self, pos: NodePosition, id: TreeID) {
372            let c = self.tree.push(Elem {
373                pos: Arc::new(pos.clone()),
374                id,
375            });
376            self.id_to_leaf_index.insert(id, c.leaf);
377        }
378
379        pub(super) fn delete_child(&mut self, id: &TreeID) {
380            if let Some(leaf) = self.id_to_leaf_index.remove(id) {
381                self.tree.remove_leaf(Cursor { leaf, offset: 0 });
382            }
383        }
384
385        pub(super) fn has_child(&self, pos: &NodePosition) -> bool {
386            match self.tree.query::<KeyQuery>(pos) {
387                Some(r) => r.found,
388                None => false,
389            }
390        }
391
392        pub(super) fn iter(&self) -> impl Iterator<Item = (&NodePosition, &TreeID)> {
393            self.tree.iter().map(|x| (&*x.pos, &x.id))
394        }
395
396        pub(super) fn len(&self) -> usize {
397            self.tree.root_cache().len
398        }
399
400        pub(super) fn get_elem_at(&self, pos: usize) -> Option<&Elem> {
401            let result = self.tree.query::<LengthFinder>(&pos)?;
402            if !result.found {
403                return None;
404            }
405            self.tree.get_elem(result.leaf())
406        }
407
408        pub(super) fn id_to_index(&self, id: &TreeID) -> Option<usize> {
409            let leaf_index = self.id_to_leaf_index.get(id)?;
410            let mut ans = 0;
411            self.tree.visit_previous_caches(
412                Cursor {
413                    leaf: *leaf_index,
414                    offset: 0,
415                },
416                |prev| match prev {
417                    generic_btree::PreviousCache::NodeCache(c) => {
418                        ans += c.len;
419                    }
420                    generic_btree::PreviousCache::PrevSiblingElem(_) => {
421                        ans += 1;
422                    }
423                    generic_btree::PreviousCache::ThisElemAndOffset { .. } => {}
424                },
425            );
426
427            Some(ans)
428        }
429
430        pub(super) fn get_index_by_node_position(
431            &self,
432            node_position: &NodePosition,
433        ) -> Result<usize, usize> {
434            let Some(res) = self.tree.query::<KeyQuery>(node_position) else {
435                return Ok(0);
436            };
437            let mut ans = 0;
438            self.tree
439                .visit_previous_caches(res.cursor, |prev| match prev {
440                    generic_btree::PreviousCache::NodeCache(c) => {
441                        ans += c.len;
442                    }
443                    generic_btree::PreviousCache::PrevSiblingElem(_) => {
444                        ans += 1;
445                    }
446                    generic_btree::PreviousCache::ThisElemAndOffset { elem: _, offset } => {
447                        ans += offset;
448                    }
449                });
450            if res.found {
451                Ok(ans)
452            } else {
453                Err(ans)
454            }
455        }
456    }
457
458    #[derive(Clone, Debug)]
459    pub(super) struct Elem {
460        pub(super) pos: Arc<NodePosition>,
461        pub(super) id: TreeID,
462    }
463
464    impl Mergeable for Elem {
465        fn can_merge(&self, _rhs: &Self) -> bool {
466            false
467        }
468
469        fn merge_right(&mut self, _rhs: &Self) {
470            unreachable!()
471        }
472
473        fn merge_left(&mut self, _left: &Self) {
474            unreachable!()
475        }
476    }
477
478    impl HasLength for Elem {
479        fn rle_len(&self) -> usize {
480            1
481        }
482    }
483
484    impl Sliceable for Elem {
485        fn _slice(&self, range: std::ops::Range<usize>) -> Self {
486            assert!(range.len() == 1);
487            self.clone()
488        }
489    }
490
491    impl CanRemove for Elem {
492        fn can_remove(&self) -> bool {
493            false
494        }
495    }
496
497    impl TryInsert for Elem {
498        fn try_insert(&mut self, _pos: usize, elem: Self) -> Result<(), Self>
499        where
500            Self: Sized,
501        {
502            Err(elem)
503        }
504    }
505
506    #[derive(Clone, Debug, Default, PartialEq, Eq)]
507    struct Cache {
508        range: Option<Range<Arc<NodePosition>>>,
509        len: usize,
510    }
511
512    impl BTreeTrait for ChildTreeTrait {
513        type Elem = Elem;
514        type Cache = Cache;
515        type CacheDiff = ();
516        const USE_DIFF: bool = false;
517
518        fn calc_cache_internal(
519            cache: &mut Self::Cache,
520            caches: &[generic_btree::Child<Self>],
521        ) -> Self::CacheDiff {
522            if caches.is_empty() {
523                *cache = Default::default();
524                return;
525            }
526
527            *cache = Cache {
528                range: Some(
529                    caches[0].cache.range.as_ref().unwrap().start.clone()
530                        ..caches
531                            .last()
532                            .unwrap()
533                            .cache
534                            .range
535                            .as_ref()
536                            .unwrap()
537                            .end
538                            .clone(),
539                ),
540                len: caches.iter().map(|x| x.cache.len).sum(),
541            };
542        }
543
544        fn apply_cache_diff(_cache: &mut Self::Cache, _diff: &Self::CacheDiff) {
545            unreachable!()
546        }
547
548        fn merge_cache_diff(_diff1: &mut Self::CacheDiff, _diff2: &Self::CacheDiff) {}
549
550        fn get_elem_cache(elem: &Self::Elem) -> Self::Cache {
551            Cache {
552                range: Some(elem.pos.clone()..elem.pos.clone()),
553                len: 1,
554            }
555        }
556
557        fn new_cache_to_diff(_cache: &Self::Cache) -> Self::CacheDiff {}
558
559        fn sub_cache(_cache_lhs: &Self::Cache, _cache_rhs: &Self::Cache) -> Self::CacheDiff {}
560    }
561
562    struct KeyQuery;
563
564    impl Query<ChildTreeTrait> for KeyQuery {
565        type QueryArg = NodePosition;
566
567        #[inline(always)]
568        fn init(_target: &Self::QueryArg) -> Self {
569            KeyQuery
570        }
571
572        #[inline]
573        fn find_node(
574            &mut self,
575            target: &Self::QueryArg,
576            caches: &[generic_btree::Child<ChildTreeTrait>],
577        ) -> FindResult {
578            let result = caches.binary_search_by(|x| {
579                let range = x.cache.range.as_ref().unwrap();
580                if target < &range.start {
581                    core::cmp::Ordering::Greater
582                } else if target > &range.end {
583                    core::cmp::Ordering::Less
584                } else {
585                    core::cmp::Ordering::Equal
586                }
587            });
588
589            match result {
590                Ok(i) => FindResult::new_found(i, 0),
591                Err(i) => FindResult::new_missing(
592                    i.min(caches.len() - 1),
593                    if i == caches.len() { 1 } else { 0 },
594                ),
595            }
596        }
597
598        #[inline(always)]
599        fn confirm_elem(
600            &mut self,
601            q: &Self::QueryArg,
602            elem: &<ChildTreeTrait as BTreeTrait>::Elem,
603        ) -> (usize, bool) {
604            match q.cmp(&elem.pos) {
605                Ordering::Less => (0, false),
606                Ordering::Equal => (0, true),
607                Ordering::Greater => (1, false),
608            }
609        }
610    }
611
612    impl UseLengthFinder<ChildTreeTrait> for ChildTreeTrait {
613        fn get_len(cache: &<ChildTreeTrait as BTreeTrait>::Cache) -> usize {
614            cache.len
615        }
616    }
617}
618
619impl Debug for TreeChildrenCache {
620    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
621        writeln!(f, "TreeChildrenCache {{")?;
622        for (parent, children) in self.0.iter() {
623            writeln!(f, "  {:?}:{{", parent)?;
624            for (position, id) in children.iter() {
625                writeln!(f, "      {:?} -> {:?}", position, id)?;
626            }
627            writeln!(f, "  }}")?;
628        }
629        writeln!(f, "}}")
630    }
631}
632
633impl Deref for TreeChildrenCache {
634    type Target = FxHashMap<TreeParentId, NodeChildren>;
635
636    fn deref(&self) -> &Self::Target {
637        &self.0
638    }
639}
640
641impl DerefMut for TreeChildrenCache {
642    fn deref_mut(&mut self) -> &mut Self::Target {
643        &mut self.0
644    }
645}
646
647impl NodePosition {
648    fn new(position: FractionalIndex, idlp: IdLp) -> Self {
649        Self { position, idlp }
650    }
651}
652
653pub(crate) enum FiIfNotConfigured {
654    UseJitterZero,
655    #[allow(unused)]
656    Throw,
657    #[allow(unused)]
658    Zero,
659}
660
661impl TreeState {
662    pub fn new(idx: ContainerIdx, peer_id: PeerID) -> Self {
663        Self {
664            idx,
665            trees: FxHashMap::default(),
666            children: Default::default(),
667            fractional_index_config: TreeFractionalIndexConfigInner::GenerateFractionalIndex {
668                jitter: 0,
669                rng: Box::new(rand::rngs::StdRng::seed_from_u64(0)),
670            },
671            peer_id,
672        }
673    }
674
675    pub fn mov(
676        &mut self,
677        target: TreeID,
678        parent: TreeParentId,
679        id: IdFull,
680        position: Option<FractionalIndex>,
681        with_check: bool,
682    ) -> Result<(), LoroError> {
683        if with_check {
684            if let TreeParentId::Node(parent) = parent {
685                if !self.trees.contains_key(&parent) {
686                    return Err(LoroTreeError::TreeNodeParentNotFound(parent).into());
687                }
688            }
689            if self.is_ancestor_of(&target, &parent) {
690                return Err(LoroTreeError::CyclicMoveError.into());
691            }
692        }
693        if let Some(old_parent) = self.trees.get(&target).map(|x| x.parent) {
694            // remove old position
695            self.try_delete_position_cache(&old_parent, &target);
696        }
697
698        let entry = self.children.entry(parent).or_default();
699        let node_position = NodePosition::new(position.clone().unwrap_or_default(), id.idlp());
700        debug_assert!(!entry.has_child(&node_position));
701        entry.insert_child(node_position, target);
702
703        self.trees.insert(
704            target,
705            TreeStateNode {
706                parent,
707                position,
708                last_move_op: id,
709            },
710        );
711
712        Ok(())
713    }
714
715    fn _init_push_tree_node_in_order(
716        &mut self,
717        target: TreeID,
718        parent: TreeParentId,
719        last_move_op: IdFull,
720        position: Option<FractionalIndex>,
721    ) -> Result<(), LoroError> {
722        debug_assert!(!self.trees.contains_key(&target));
723        let entry = self.children.entry(parent).or_default();
724        let node_position =
725            NodePosition::new(position.clone().unwrap_or_default(), last_move_op.idlp());
726        debug_assert!(!entry.has_child(&node_position));
727        entry.push_child_in_order(node_position, target);
728        self.trees.insert(
729            target,
730            TreeStateNode {
731                parent,
732                position,
733                last_move_op,
734            },
735        );
736
737        Ok(())
738    }
739
740    #[inline(never)]
741    fn is_ancestor_of(&self, maybe_ancestor: &TreeID, node_id: &TreeParentId) -> bool {
742        if !self.trees.contains_key(maybe_ancestor) {
743            return false;
744        }
745        if let TreeParentId::Node(id) = node_id {
746            if id == maybe_ancestor {
747                return true;
748            }
749        }
750        match node_id {
751            TreeParentId::Node(id) => {
752                let parent = &self.trees.get(id).unwrap().parent;
753                if parent == node_id {
754                    panic!("is_ancestor_of loop")
755                }
756                self.is_ancestor_of(maybe_ancestor, parent)
757            }
758            TreeParentId::Deleted | TreeParentId::Root => false,
759            TreeParentId::Unexist => unreachable!(),
760        }
761    }
762
763    /// Get the parent of the node, if the node does not exist, return None
764    pub fn parent(&self, target: &TreeID) -> Option<TreeParentId> {
765        self.trees.get(target).map(|x| x.parent)
766    }
767
768    /// If the node is unexist, return None. If the node is deleted, return true.
769    pub(crate) fn is_node_deleted(&self, target: &TreeID) -> Option<bool> {
770        match self.trees.get(target).map(|x| x.parent)? {
771            TreeParentId::Deleted => Some(true),
772            TreeParentId::Root => Some(false),
773            TreeParentId::Node(p) => self.is_node_deleted(&p),
774            TreeParentId::Unexist => unreachable!(),
775        }
776    }
777
778    pub(crate) fn is_node_unexist(&self, target: &TreeID) -> bool {
779        !self.trees.contains_key(target)
780    }
781
782    // Get all flat tree nodes, excluding deleted nodes.
783    pub(crate) fn tree_nodes(&self) -> Vec<TreeNode> {
784        self.get_all_tree_nodes_under(TreeParentId::Root)
785    }
786
787    // Get all flat deleted nodes
788    #[allow(unused)]
789    pub(crate) fn deleted_tree_nodes(&self) -> Vec<TreeNode> {
790        self.get_all_tree_nodes_under(TreeParentId::Deleted)
791    }
792
793    // Get all flat tree nodes under the parent
794    pub(crate) fn get_all_tree_nodes_under(&self, root: TreeParentId) -> Vec<TreeNode> {
795        let mut ans = vec![];
796        let children = self.children.get(&root);
797        let mut q = children
798            .map(|x| VecDeque::from_iter(x.iter().enumerate().zip(std::iter::repeat(root))))
799            .unwrap_or_default();
800
801        while let Some(((index, (position, &target)), parent)) = q.pop_front() {
802            ans.push(TreeNode {
803                id: target,
804                parent,
805                fractional_index: position.position.clone(),
806                index,
807                last_move_op: self.trees.get(&target).map(|x| x.last_move_op).unwrap(),
808            });
809            if let Some(children) = self.children.get(&TreeParentId::Node(target)) {
810                q.extend(
811                    children
812                        .iter()
813                        .enumerate()
814                        .map(|(index, (position, this_target))| {
815                            ((index, (position, this_target)), TreeParentId::Node(target))
816                        }),
817                );
818            }
819        }
820        ans
821    }
822
823    pub(crate) fn get_all_hierarchy_nodes_under(
824        &self,
825        root: TreeParentId,
826    ) -> Vec<TreeNodeWithChildren> {
827        let mut ans = vec![];
828        let Some(children) = self.children.get(&root) else {
829            return ans;
830        };
831        for (index, (position, &target)) in children.iter().enumerate() {
832            ans.push(TreeNodeWithChildren {
833                id: target,
834                parent: root,
835                fractional_index: position.position.clone(),
836                index,
837                children: self.get_all_hierarchy_nodes_under(TreeParentId::Node(target)),
838            })
839        }
840        ans
841    }
842
843    fn bfs_all_alive_nodes_for_fast_snapshot(&self) -> Vec<TreeNode> {
844        let mut ans = vec![];
845        self._bfs_all_nodes(TreeParentId::Root, &mut ans);
846        ans
847    }
848
849    fn bfs_all_deleted_nodes_for_fast_snapshot(&self) -> Vec<TreeNode> {
850        let mut ans = vec![];
851        self._bfs_all_nodes(TreeParentId::Deleted, &mut ans);
852        ans
853    }
854
855    fn _bfs_all_nodes(&self, root: TreeParentId, ans: &mut Vec<TreeNode>) {
856        let children = self.children.get(&root);
857        if let Some(children) = children {
858            for (index, (position, target)) in children.iter().enumerate() {
859                ans.push(TreeNode {
860                    id: *target,
861                    parent: root,
862                    fractional_index: position.position.clone(),
863                    index,
864                    last_move_op: self.trees.get(target).map(|x| x.last_move_op).unwrap(),
865                });
866            }
867
868            for (_, id) in children.iter() {
869                self._bfs_all_nodes(TreeParentId::Node(*id), ans);
870            }
871        }
872    }
873
874    pub fn nodes(&self) -> Vec<TreeID> {
875        self.trees.keys().copied().collect::<Vec<_>>()
876    }
877
878    #[cfg(feature = "test_utils")]
879    pub fn max_counter(&self) -> i32 {
880        self.trees
881            .keys()
882            .filter(|&k| !self.is_node_deleted(k).unwrap())
883            .map(|k| k.counter)
884            .max()
885            .unwrap_or(0)
886    }
887
888    pub fn get_children<'a>(
889        &'a self,
890        parent: &TreeParentId,
891    ) -> Option<impl Iterator<Item = TreeID> + 'a> {
892        self.children.get(parent).map(|x| x.iter().map(|x| *x.1))
893    }
894
895    pub fn children_num(&self, parent: &TreeParentId) -> Option<usize> {
896        self.children.get(parent).map(|x| x.len())
897    }
898
899    /// Determine whether the target is the child of the node
900    ///
901    /// O(1)
902    pub fn is_parent(&self, target: &TreeID, parent: &TreeParentId) -> bool {
903        self.trees.get(target).is_some_and(|x| x.parent == *parent)
904    }
905
906    /// Delete the position cache of the node
907    pub(crate) fn try_delete_position_cache(&mut self, parent: &TreeParentId, target: &TreeID) {
908        if let Some(x) = self.children.get_mut(parent) {
909            x.delete_child(target);
910        }
911    }
912
913    pub(crate) fn generate_position_at(
914        &mut self,
915        target: &TreeID,
916        parent: &TreeParentId,
917        index: usize,
918        cfg: FiIfNotConfigured,
919    ) -> FractionalIndexGenResult {
920        match &mut self.fractional_index_config {
921            TreeFractionalIndexConfigInner::GenerateFractionalIndex { jitter, rng } => {
922                if *jitter == 0 {
923                    self.children
924                        .entry(*parent)
925                        .or_default()
926                        .generate_fi_at(index, target)
927                } else {
928                    self.children
929                        .entry(*parent)
930                        .or_default()
931                        .generate_fi_at_jitter(index, target, rng.as_mut(), *jitter)
932                }
933            }
934            TreeFractionalIndexConfigInner::MoveDisabled => match cfg {
935                FiIfNotConfigured::Throw => FractionalIndexGenResult::NotConfigured,
936                FiIfNotConfigured::UseJitterZero => self
937                    .children
938                    .entry(*parent)
939                    .or_default()
940                    .generate_fi_at(index, target),
941                FiIfNotConfigured::Zero => FractionalIndexGenResult::Ok(FractionalIndex::default()),
942            },
943        }
944    }
945
946    pub(crate) fn is_fractional_index_enabled(&self) -> bool {
947        !matches!(
948            self.fractional_index_config,
949            TreeFractionalIndexConfigInner::MoveDisabled
950        )
951    }
952
953    pub(crate) fn enable_generate_fractional_index(&mut self, jitter: u8) {
954        if let TreeFractionalIndexConfigInner::GenerateFractionalIndex {
955            jitter: old_jitter, ..
956        } = &mut self.fractional_index_config
957        {
958            *old_jitter = jitter;
959            return;
960        }
961        self.fractional_index_config = TreeFractionalIndexConfigInner::GenerateFractionalIndex {
962            jitter,
963            rng: Box::new(rand::rngs::StdRng::seed_from_u64(self.peer_id)),
964        };
965    }
966
967    pub(crate) fn disable_generate_fractional_index(&mut self) {
968        self.fractional_index_config = TreeFractionalIndexConfigInner::MoveDisabled;
969    }
970
971    pub(crate) fn get_position(&self, target: &TreeID) -> Option<FractionalIndex> {
972        self.trees.get(target).and_then(|x| x.position.clone())
973    }
974
975    pub(crate) fn get_index_by_tree_id(&self, target: &TreeID) -> Option<usize> {
976        let parent = self.parent(target)?;
977        (!parent.is_deleted())
978            .then(|| {
979                self.children
980                    .get(&parent)
981                    .and_then(|x| x.get_index_by_child_id(target))
982            })
983            .flatten()
984    }
985
986    pub(crate) fn get_index_by_position(
987        &self,
988        parent: &TreeParentId,
989        node_position: &NodePosition,
990    ) -> Option<usize> {
991        self.children.get(parent).map(|c| {
992            match c.get_last_insert_index_by_position(node_position) {
993                Ok(i) => i,
994                Err(i) => i,
995            }
996        })
997    }
998
999    pub(crate) fn get_id_by_index(&self, parent: &TreeParentId, index: usize) -> Option<TreeID> {
1000        (!parent.is_deleted())
1001            .then(|| self.children.get(parent).and_then(|x| x.get_id_at(index)))
1002            .flatten()
1003    }
1004
1005    /// Check the consistency between `self.trees` and `self.children`
1006    ///
1007    /// It's used for debug and test
1008    #[allow(unused)]
1009    pub(crate) fn check_tree_integrity(&self) {
1010        let mut parent_children_map: FxHashMap<TreeParentId, FxHashSet<TreeID>> =
1011            FxHashMap::default();
1012        for (id, node) in self.trees.iter() {
1013            let parent = node.parent;
1014            parent_children_map.entry(parent).or_default().insert(*id);
1015        }
1016
1017        for (parent, children) in parent_children_map.iter() {
1018            let cached_children = self.get_children(parent).expect("parent not found");
1019            let cached_children = cached_children.collect::<FxHashSet<_>>();
1020            if &cached_children != children {
1021                panic!(
1022                    "tree integrity broken: children set of node {:?} is not consistent",
1023                    parent
1024                );
1025            }
1026        }
1027    }
1028
1029    pub fn is_empty(&self) -> bool {
1030        match self.children.get(&TreeParentId::Root) {
1031            Some(c) => c.len() == 0,
1032            None => true,
1033        }
1034    }
1035
1036    pub fn get_last_move_id(&self, id: &TreeID) -> Option<ID> {
1037        self.trees.get(id).map(|x| x.last_move_op.id())
1038    }
1039}
1040
1041pub(crate) enum FractionalIndexGenResult {
1042    Ok(FractionalIndex),
1043    Rearrange(Vec<(TreeID, FractionalIndex)>),
1044    NotConfigured,
1045}
1046
1047impl ContainerState for TreeState {
1048    fn container_idx(&self) -> crate::container::idx::ContainerIdx {
1049        self.idx
1050    }
1051
1052    fn estimate_size(&self) -> usize {
1053        self.trees.len() * (std::mem::size_of::<(TreeID, TreeStateNode)>())
1054    }
1055
1056    fn is_state_empty(&self) -> bool {
1057        self.nodes().is_empty()
1058    }
1059
1060    // How we apply the diff is coupled with the [DiffMode] we used to calculate the diff.
1061    // So be careful when you modify this function.
1062    fn apply_diff_and_convert(
1063        &mut self,
1064        diff: crate::event::InternalDiff,
1065        ctx: DiffApplyContext,
1066    ) -> Diff {
1067        let need_check = !matches!(ctx.mode, DiffMode::Checkout | DiffMode::Linear);
1068        let mut ans = vec![];
1069        if let InternalDiff::Tree(tree) = &diff {
1070            // assert never cause cycle move
1071            for diff in tree.diff.iter() {
1072                let last_move_op = diff.last_effective_move_op_id;
1073                let target = diff.target;
1074                // create associated metadata container
1075                match &diff.action {
1076                    TreeInternalDiff::Create { parent, position } => {
1077                        self.mov(target, *parent, last_move_op, Some(position.clone()), false)
1078                            .unwrap();
1079
1080                        if let TreeParentId::Node(p) = parent {
1081                            // reuse diff cache, at this time,it's "move in deleted"
1082                            if self.is_node_deleted(p).unwrap() {
1083                                continue;
1084                            }
1085                        }
1086
1087                        let index = self.get_index_by_tree_id(&target).unwrap();
1088                        ans.push(TreeDiffItem {
1089                            target,
1090                            action: TreeExternalDiff::Create {
1091                                parent: *parent,
1092                                index,
1093                                position: position.clone(),
1094                            },
1095                        });
1096                    }
1097                    TreeInternalDiff::Move { parent, position } => {
1098                        let old_parent = self.trees.get(&target).unwrap().parent;
1099                        // If this is some, the node is still alive at the moment
1100                        let old_index = self.get_index_by_tree_id(&target);
1101                        let was_alive = !self.is_node_deleted(&target).unwrap();
1102                        if need_check {
1103                            if self
1104                                .mov(target, *parent, last_move_op, Some(position.clone()), true)
1105                                .is_ok()
1106                            {
1107                                if self.is_node_deleted(&target).unwrap() {
1108                                    if was_alive {
1109                                        // delete event
1110                                        ans.push(TreeDiffItem {
1111                                            target,
1112                                            action: TreeExternalDiff::Delete {
1113                                                old_parent,
1114                                                old_index: old_index.unwrap(),
1115                                            },
1116                                        });
1117                                    }
1118                                    // Otherwise, it's a normal move inside deleted nodes, no event is needed
1119                                } else if was_alive {
1120                                    // normal move
1121                                    ans.push(TreeDiffItem {
1122                                        target,
1123                                        action: TreeExternalDiff::Move {
1124                                            parent: *parent,
1125                                            index: self.get_index_by_tree_id(&target).unwrap(),
1126                                            position: position.clone(),
1127                                            old_parent,
1128                                            old_index: old_index.unwrap(),
1129                                        },
1130                                    });
1131                                } else {
1132                                    // create event
1133                                    ans.push(TreeDiffItem {
1134                                        target,
1135                                        action: TreeExternalDiff::Create {
1136                                            parent: *parent,
1137                                            index: self.get_index_by_tree_id(&target).unwrap(),
1138                                            position: position.clone(),
1139                                        },
1140                                    });
1141                                }
1142                            }
1143                        } else {
1144                            self.mov(target, *parent, last_move_op, Some(position.clone()), false)
1145                                .unwrap();
1146
1147                            if let TreeParentId::Node(p) = parent {
1148                                // reuse diff cache, at this time,it's "move in deleted"
1149                                if self.is_node_deleted(p).unwrap() {
1150                                    continue;
1151                                }
1152                            }
1153
1154                            let index = self.get_index_by_tree_id(&target).unwrap();
1155                            match was_alive {
1156                                true => {
1157                                    ans.push(TreeDiffItem {
1158                                        target,
1159                                        action: TreeExternalDiff::Move {
1160                                            parent: *parent,
1161                                            index,
1162                                            position: position.clone(),
1163                                            old_parent,
1164                                            old_index: old_index.unwrap(),
1165                                        },
1166                                    });
1167                                }
1168                                false => {
1169                                    ans.push(TreeDiffItem {
1170                                        target,
1171                                        action: TreeExternalDiff::Create {
1172                                            parent: *parent,
1173                                            index,
1174                                            position: position.clone(),
1175                                        },
1176                                    });
1177                                }
1178                            }
1179                        };
1180                    }
1181                    TreeInternalDiff::Delete { parent, position } => {
1182                        let mut send_event = true;
1183                        if self.is_node_deleted(&target).unwrap() {
1184                            send_event = false;
1185                        }
1186                        if send_event {
1187                            ans.push(TreeDiffItem {
1188                                target,
1189                                action: TreeExternalDiff::Delete {
1190                                    old_parent: self.trees.get(&target).unwrap().parent,
1191                                    old_index: self.get_index_by_tree_id(&target).unwrap(),
1192                                },
1193                            });
1194                        }
1195                        self.mov(target, *parent, last_move_op, position.clone(), false)
1196                            .unwrap();
1197                    }
1198                    TreeInternalDiff::MoveInDelete { parent, position } => {
1199                        self.mov(target, *parent, last_move_op, position.clone(), false)
1200                            .unwrap();
1201                    }
1202                    TreeInternalDiff::UnCreate => {
1203                        // maybe the node created and moved to the parent deleted
1204                        if !self.is_node_deleted(&target).unwrap() {
1205                            ans.push(TreeDiffItem {
1206                                target,
1207                                action: TreeExternalDiff::Delete {
1208                                    old_parent: self.trees.get(&target).unwrap().parent,
1209                                    old_index: self.get_index_by_tree_id(&target).unwrap(),
1210                                },
1211                            });
1212                        }
1213                        // delete it from state
1214                        let node = self.trees.remove(&target);
1215                        if let Some(node) = node {
1216                            if !node.parent.is_deleted() {
1217                                self.children
1218                                    .get_mut(&node.parent)
1219                                    .unwrap()
1220                                    .delete_child(&target);
1221                            }
1222                        }
1223                        continue;
1224                    }
1225                };
1226            }
1227        }
1228
1229        // self.check_tree_integrity();
1230        Diff::Tree(TreeDiff { diff: ans })
1231    }
1232
1233    // How we apply the diff is coupled with the [DiffMode] we used to calculate the diff.
1234    // So be careful when you modify this function.
1235    fn apply_diff(&mut self, diff: InternalDiff, ctx: DiffApplyContext) {
1236        if let InternalDiff::Tree(tree) = &diff {
1237            let need_check = !matches!(ctx.mode, DiffMode::Checkout | DiffMode::Linear);
1238            // assert never cause cycle move
1239            for diff in tree.diff.iter() {
1240                let last_move_op = diff.last_effective_move_op_id;
1241                let target = diff.target;
1242                // create associated metadata container
1243                match &diff.action {
1244                    TreeInternalDiff::Create { parent, position }
1245                    | TreeInternalDiff::Move {
1246                        parent, position, ..
1247                    } => {
1248                        if need_check {
1249                            self.mov(target, *parent, last_move_op, Some(position.clone()), true)
1250                                .unwrap_or_default();
1251                        } else {
1252                            self.mov(target, *parent, last_move_op, Some(position.clone()), false)
1253                                .unwrap();
1254                        }
1255                    }
1256                    TreeInternalDiff::Delete { parent, position } => {
1257                        self.mov(target, *parent, last_move_op, position.clone(), false)
1258                            .unwrap();
1259                    }
1260                    TreeInternalDiff::MoveInDelete { parent, position } => {
1261                        self.mov(target, *parent, last_move_op, position.clone(), false)
1262                            .unwrap();
1263                    }
1264                    TreeInternalDiff::UnCreate => {
1265                        // delete it from state
1266                        let parent = self.trees.remove(&target);
1267                        if let Some(parent) = parent {
1268                            if !parent.parent.is_deleted() {
1269                                self.children
1270                                    .get_mut(&parent.parent)
1271                                    .unwrap()
1272                                    .delete_child(&target);
1273                            }
1274                        }
1275                        continue;
1276                    }
1277                };
1278            }
1279        }
1280        // self.check_tree_integrity();
1281    }
1282
1283    fn apply_local_op(&mut self, raw_op: &RawOp, _op: &Op) -> LoroResult<ApplyLocalOpReturn> {
1284        let mut deleted_containers = vec![];
1285        match &raw_op.content {
1286            crate::op::RawOpContent::Tree(tree) => match &**tree {
1287                TreeOp::Create {
1288                    target,
1289                    parent,
1290                    position,
1291                }
1292                | TreeOp::Move {
1293                    target,
1294                    parent,
1295                    position,
1296                } => {
1297                    let parent = TreeParentId::from(*parent);
1298                    self.mov(
1299                        *target,
1300                        parent,
1301                        raw_op.id_full(),
1302                        Some(position.clone()),
1303                        true,
1304                    )?;
1305                }
1306                TreeOp::Delete { target } => {
1307                    let parent = TreeParentId::Deleted;
1308                    deleted_containers.push(ContainerID::new_normal(
1309                        target.id(),
1310                        loro_common::ContainerType::Map,
1311                    ));
1312                    self.mov(*target, parent, raw_op.id_full(), None, true)?;
1313                }
1314            },
1315            _ => unreachable!(),
1316        }
1317        // self.check_tree_integrity();
1318        Ok(ApplyLocalOpReturn { deleted_containers })
1319    }
1320
1321    fn to_diff(&mut self, _doc: &Weak<LoroDocInner>) -> Diff {
1322        let mut diffs = vec![];
1323        let Some(roots) = self.children.get(&TreeParentId::Root) else {
1324            return Diff::Tree(TreeDiff { diff: vec![] });
1325        };
1326
1327        let mut q = VecDeque::from_iter(roots.iter());
1328        let mut index = 0;
1329        let mut parent = TreeParentId::Root;
1330        while let Some((position, node)) = q.pop_front() {
1331            let node_parent = self.trees.get(node).unwrap().parent;
1332            if node_parent != parent {
1333                index = 0;
1334                parent = node_parent;
1335            }
1336            let diff = TreeDiffItem {
1337                target: *node,
1338                action: TreeExternalDiff::Create {
1339                    parent: node_parent,
1340                    index,
1341                    position: position.position.clone(),
1342                },
1343            };
1344            index += 1;
1345            diffs.push(diff);
1346            if let Some(children) = self.children.get(&TreeParentId::Node(*node)) {
1347                // TODO: Refactor: you can include the index and parent in the q
1348                // The code will be more robust and easy to understand
1349                q.extend(children.iter());
1350            }
1351        }
1352
1353        Diff::Tree(TreeDiff { diff: diffs })
1354    }
1355
1356    fn get_value(&mut self) -> LoroValue {
1357        self.get_all_hierarchy_nodes_under(TreeParentId::Root)
1358            .into_iter()
1359            .map(|x| x.into_value())
1360            .collect::<Vec<_>>()
1361            .into()
1362    }
1363
1364    /// Get the index of the child container
1365    fn get_child_index(&self, id: &ContainerID) -> Option<Index> {
1366        let id = id.as_normal().unwrap();
1367        let tree_id = TreeID {
1368            peer: *id.0,
1369            counter: *id.1,
1370        };
1371        if !self.trees.contains_key(&tree_id) || self.is_node_deleted(&tree_id).unwrap() {
1372            None
1373        } else {
1374            Some(Index::Node(tree_id))
1375        }
1376    }
1377
1378    fn contains_child(&self, id: &ContainerID) -> bool {
1379        let id = id.as_normal().unwrap();
1380        let tree_id = TreeID {
1381            peer: *id.0,
1382            counter: *id.1,
1383        };
1384        self.trees.contains_key(&tree_id) && !self.is_node_deleted(&tree_id).unwrap()
1385    }
1386
1387    fn get_child_containers(&self) -> Vec<ContainerID> {
1388        self.trees
1389            .keys()
1390            .map(|n| n.associated_meta_container())
1391            .collect_vec()
1392    }
1393
1394    #[doc = " Get a list of ops that can be used to restore the state to the current state"]
1395    fn encode_snapshot(&self, mut encoder: StateSnapshotEncoder) -> Vec<u8> {
1396        for node in self.trees.values() {
1397            if node.last_move_op == IdFull::NONE_ID {
1398                continue;
1399            }
1400            encoder.encode_op(node.last_move_op.idlp().into(), || unimplemented!());
1401        }
1402        Vec::new()
1403    }
1404
1405    #[doc = " Restore the state to the state represented by the ops that exported by `get_snapshot_ops`"]
1406    fn import_from_snapshot_ops(&mut self, ctx: StateSnapshotDecodeContext) -> LoroResult<()> {
1407        assert_eq!(ctx.mode, EncodeMode::OutdatedSnapshot);
1408        for op in ctx.ops {
1409            assert_eq!(op.op.atom_len(), 1);
1410            let content = op.op.content.as_tree().unwrap();
1411            match &**content {
1412                TreeOp::Create {
1413                    target,
1414                    parent,
1415                    position,
1416                }
1417                | TreeOp::Move {
1418                    target,
1419                    parent,
1420                    position,
1421                } => {
1422                    let parent = TreeParentId::from(*parent);
1423                    self.mov(*target, parent, op.id_full(), Some(position.clone()), false)
1424                        .unwrap()
1425                }
1426                TreeOp::Delete { target } => {
1427                    let parent = TreeParentId::Deleted;
1428                    self.mov(*target, parent, op.id_full(), None, false)
1429                        .unwrap()
1430                }
1431            };
1432        }
1433        Ok(())
1434    }
1435
1436    fn fork(&self, _config: &Configure) -> Self {
1437        self.clone()
1438    }
1439}
1440
1441// convert map container to LoroValue
1442#[allow(clippy::ptr_arg)]
1443pub(crate) fn get_meta_value(nodes: &mut Vec<LoroValue>, state: &mut DocState) {
1444    for node in nodes.iter_mut() {
1445        let map = node.as_map_mut().unwrap().make_mut();
1446        let meta = map.get_mut("meta").unwrap();
1447        let id = meta.as_container().unwrap();
1448        *meta = state.get_container_deep_value(state.arena.register_container(id));
1449        let children = map.get_mut("children").unwrap().as_list_mut().unwrap();
1450        get_meta_value(children.make_mut(), state);
1451    }
1452}
1453
1454#[derive(Debug, Clone)]
1455pub struct TreeNode {
1456    pub id: TreeID,
1457    pub parent: TreeParentId,
1458    pub fractional_index: FractionalIndex,
1459    pub index: usize,
1460    pub last_move_op: IdFull,
1461}
1462
1463#[derive(Debug, Clone)]
1464pub struct TreeNodeWithChildren {
1465    pub id: TreeID,
1466    pub parent: TreeParentId,
1467    pub fractional_index: FractionalIndex,
1468    pub index: usize,
1469    pub children: Vec<TreeNodeWithChildren>,
1470}
1471
1472impl TreeNodeWithChildren {
1473    fn into_value(self) -> LoroValue {
1474        let mut t = FxHashMap::default();
1475        t.insert("id".to_string(), self.id.to_string().into());
1476        let p = self
1477            .parent
1478            .tree_id()
1479            .map(|p| p.to_string().into())
1480            .unwrap_or(LoroValue::Null);
1481        t.insert("parent".to_string(), p);
1482        t.insert(
1483            "meta".to_string(),
1484            self.id.associated_meta_container().into(),
1485        );
1486        t.insert("index".to_string(), (self.index as i64).into());
1487        t.insert(
1488            "fractional_index".to_string(),
1489            self.fractional_index.to_string().into(),
1490        );
1491        t.insert(
1492            "children".to_string(),
1493            self.children
1494                .into_iter()
1495                .map(|x| x.into_value())
1496                .collect::<Vec<_>>()
1497                .into(),
1498        );
1499        t.into()
1500    }
1501}
1502
1503mod jitter {
1504    use super::{FractionalIndexGenResult, NodeChildren};
1505    use fractional_index::FractionalIndex;
1506    use loro_common::TreeID;
1507    use rand::Rng;
1508
1509    impl NodeChildren {
1510        pub(super) fn generate_fi_at_jitter(
1511            &self,
1512            pos: usize,
1513            target: &TreeID,
1514            rng: &mut impl Rng,
1515            jitter: u8,
1516        ) -> FractionalIndexGenResult {
1517            let mut reset_ids = vec![];
1518            let mut left = None;
1519            let mut next_right = None;
1520            {
1521                let mut right = None;
1522                let children_num = self.len();
1523                if children_num == 0 {
1524                    return FractionalIndexGenResult::Ok(FractionalIndex::jitter_default(
1525                        rng, jitter,
1526                    ));
1527                }
1528
1529                if pos > 0 {
1530                    left = self.get_node_position_at(pos - 1);
1531                }
1532                if pos < children_num {
1533                    right = self.get_elem_at(pos);
1534                }
1535
1536                let left_fi = left.map(|x| &x.position);
1537                // if left and right have the same fractional indexes, we need to scan further to
1538                // find all the ids that need to be reset
1539                if let Some(left_fi) = left_fi {
1540                    if Some(left_fi) == right.map(|x| &x.0.position) {
1541                        // TODO: the min length between left and right
1542                        reset_ids.push(*right.unwrap().1);
1543                        for i in (pos + 1)..children_num {
1544                            let this_position = &self.get_node_position_at(i).unwrap().position;
1545                            if this_position == left_fi {
1546                                reset_ids.push(*self.get_elem_at(i).unwrap().1);
1547                            } else {
1548                                next_right = Some(this_position.clone());
1549                                break;
1550                            }
1551                        }
1552                    }
1553                }
1554
1555                if reset_ids.is_empty() {
1556                    return FractionalIndexGenResult::Ok(
1557                        FractionalIndex::new_jitter(
1558                            left.map(|x| &x.position),
1559                            right.map(|x| &x.0.position),
1560                            rng,
1561                            jitter,
1562                        )
1563                        .unwrap(),
1564                    );
1565                }
1566            }
1567            let positions = FractionalIndex::generate_n_evenly_jitter(
1568                left.map(|x| &x.position),
1569                next_right.as_ref(),
1570                reset_ids.len() + 1,
1571                rng,
1572                jitter,
1573            )
1574            .unwrap();
1575            FractionalIndexGenResult::Rearrange(
1576                Some(*target)
1577                    .into_iter()
1578                    .chain(reset_ids)
1579                    .zip(positions)
1580                    .collect(),
1581            )
1582        }
1583    }
1584}
1585
1586mod snapshot {
1587    use std::{borrow::Cow, collections::BTreeSet, io::Read};
1588
1589    use fractional_index::FractionalIndex;
1590    use fxhash::FxHashMap;
1591    use itertools::Itertools;
1592    use loro_common::{IdFull, Lamport, PeerID, TreeID};
1593
1594    use serde_columnar::columnar;
1595
1596    use crate::{
1597        encoding::{arena::PositionArena, value_register::ValueRegister},
1598        state::FastStateSnapshot,
1599    };
1600
1601    use super::{TreeNode, TreeParentId, TreeState};
1602    #[columnar(vec, ser, de, iterable)]
1603    #[derive(Debug, Clone)]
1604    struct EncodedTreeNodeId {
1605        #[columnar(strategy = "DeltaRle")]
1606        peer_idx: usize,
1607        #[columnar(strategy = "DeltaRle")]
1608        counter: i32,
1609    }
1610
1611    #[columnar(vec, ser, de, iterable)]
1612    #[derive(Debug, Clone)]
1613    struct EncodedTreeNode {
1614        /// If this field is 0, it means none, its parent is root
1615        /// If this field is 1, its parent is the deleted root
1616        #[columnar(strategy = "DeltaRle")]
1617        parent_idx_plus_two: usize,
1618        #[columnar(strategy = "DeltaRle")]
1619        last_set_peer_idx: usize,
1620        #[columnar(strategy = "DeltaRle")]
1621        last_set_counter: i32,
1622        #[columnar(strategy = "DeltaRle")]
1623        last_set_lamport_sub_counter: i32,
1624        fractional_index_idx: usize,
1625    }
1626
1627    #[columnar(ser, de)]
1628    struct EncodedTree<'a> {
1629        #[columnar(class = "vec", iter = "EncodedTreeNodeId")]
1630        node_ids: Vec<EncodedTreeNodeId>,
1631        #[columnar(class = "vec", iter = "EncodedTreeNode")]
1632        nodes: Vec<EncodedTreeNode>,
1633        #[columnar(borrow)]
1634        fractional_indexes: Cow<'a, [u8]>,
1635        #[columnar(borrow)]
1636        reserved_has_effect_bool_rle: Cow<'a, [u8]>,
1637    }
1638
1639    fn encode(
1640        state: &TreeState,
1641        input: Vec<TreeNode>,
1642        deleted_nodes: Vec<TreeNode>,
1643    ) -> (ValueRegister<PeerID>, EncodedTree) {
1644        let mut peers: ValueRegister<PeerID> = ValueRegister::new();
1645        let mut position_set = BTreeSet::default();
1646        let mut nodes = Vec::with_capacity(input.len());
1647        let mut node_ids = Vec::with_capacity(input.len());
1648        let mut position_register = ValueRegister::new();
1649        let mut id_to_idx = FxHashMap::default();
1650        for node in input.iter().chain(deleted_nodes.iter()) {
1651            position_set.insert(node.fractional_index.clone());
1652            let idx = node_ids.len();
1653            node_ids.push(EncodedTreeNodeId {
1654                peer_idx: peers.register(&node.id.peer),
1655                counter: node.id.counter,
1656            });
1657            id_to_idx.insert(node.id, idx);
1658        }
1659
1660        for p in position_set {
1661            position_register.register(&p);
1662        }
1663
1664        for node in input {
1665            let n = state.trees.get(&node.id).unwrap();
1666            let last_set_id = n.last_move_op;
1667            nodes.push(EncodedTreeNode {
1668                parent_idx_plus_two: match node.parent {
1669                    TreeParentId::Deleted => 1,
1670                    TreeParentId::Root => 0,
1671                    TreeParentId::Node(id) => id_to_idx.get(&id).unwrap() + 2,
1672                    TreeParentId::Unexist => unreachable!(),
1673                },
1674                last_set_peer_idx: peers.register(&last_set_id.peer),
1675                last_set_counter: last_set_id.counter,
1676                last_set_lamport_sub_counter: last_set_id.lamport as i32 - last_set_id.counter,
1677                fractional_index_idx: position_register.register(&node.fractional_index),
1678            })
1679        }
1680
1681        for node in deleted_nodes {
1682            let n = state.trees.get(&node.id).unwrap();
1683            let last_set_id = n.last_move_op;
1684            nodes.push(EncodedTreeNode {
1685                parent_idx_plus_two: match node.parent {
1686                    TreeParentId::Deleted => 1,
1687                    TreeParentId::Root => 0,
1688                    TreeParentId::Node(id) => id_to_idx.get(&id).unwrap() + 2,
1689                    TreeParentId::Unexist => unreachable!(),
1690                },
1691                last_set_peer_idx: peers.register(&last_set_id.peer),
1692                last_set_counter: last_set_id.counter,
1693                last_set_lamport_sub_counter: last_set_id.lamport as i32 - last_set_id.counter,
1694                fractional_index_idx: position_register.register(&node.fractional_index),
1695            })
1696        }
1697
1698        let position_vec = position_register.unwrap_vec();
1699        let positions = PositionArena::from_positions(position_vec.iter().map(|p| p.as_bytes()));
1700        (
1701            peers,
1702            EncodedTree {
1703                node_ids,
1704                nodes,
1705                fractional_indexes: positions.encode().into(),
1706                reserved_has_effect_bool_rle: vec![].into(),
1707            },
1708        )
1709    }
1710
1711    impl FastStateSnapshot for TreeState {
1712        /// Encodes the TreeState into a compact binary format for efficient serialization.
1713        ///
1714        /// The encoding schema:
1715        /// 1. Encodes all nodes using a breadth-first search traversal, ensuring a consistent order.
1716        /// 2. Uses a ValueRegister to deduplicate and index PeerIDs and TreeIDs, reducing redundancy.
1717        ///    - PeerIDs are stored once and referenced by index.
1718        ///    - TreeIDs are decomposed into peer index and counter for compact representation.
1719        /// 3. Encodes fractional indexes using a PositionArena for space efficiency
1720        /// 4. Utilizes delta encoding and run-length encoding for further size reduction:
1721        ///    - Delta encoding stores differences between consecutive values.
1722        ///    - Run-length encoding compresses sequences of repeated values.
1723        /// 5. Stores parent relationships using indices, with special values for root and deleted nodes.
1724        /// 6. Encodes last move operation details (peer_idx, counter[Delta], lamport clock[Delta]) for each node.
1725        fn encode_snapshot_fast<W: std::io::prelude::Write>(&mut self, mut w: W) {
1726            let all_alive_nodes = self.bfs_all_alive_nodes_for_fast_snapshot();
1727            let all_deleted_nodes = self.bfs_all_deleted_nodes_for_fast_snapshot();
1728            let (peers, encoded) = encode(self, all_alive_nodes, all_deleted_nodes);
1729            let peers = peers.unwrap_vec();
1730            leb128::write::unsigned(&mut w, peers.len() as u64).unwrap();
1731            for peer in peers {
1732                w.write_all(&peer.to_le_bytes()).unwrap();
1733            }
1734
1735            let vec = serde_columnar::to_vec(&encoded).unwrap();
1736            w.write_all(&vec).unwrap();
1737        }
1738
1739        fn decode_value(_: &[u8]) -> loro_common::LoroResult<(loro_common::LoroValue, &[u8])> {
1740            unreachable!()
1741        }
1742
1743        fn decode_snapshot_fast(
1744            idx: crate::container::idx::ContainerIdx,
1745            (_, mut bytes): (loro_common::LoroValue, &[u8]),
1746            ctx: crate::state::ContainerCreationContext,
1747        ) -> loro_common::LoroResult<Self>
1748        where
1749            Self: Sized,
1750        {
1751            let peer_num = leb128::read::unsigned(&mut bytes).unwrap() as usize;
1752            let mut peers = Vec::with_capacity(peer_num);
1753            for _ in 0..peer_num {
1754                let mut buf = [0u8; 8];
1755                bytes.read_exact(&mut buf).unwrap();
1756                peers.push(PeerID::from_le_bytes(buf));
1757            }
1758
1759            let mut tree = TreeState::new(idx, ctx.peer);
1760            let encoded: EncodedTree = serde_columnar::from_bytes(bytes)?;
1761            let fractional_indexes = PositionArena::decode(&encoded.fractional_indexes).unwrap();
1762            let fractional_indexes = fractional_indexes.parse_to_positions();
1763            let node_ids = encoded
1764                .node_ids
1765                .iter()
1766                .map(|x| TreeID::new(peers[x.peer_idx], x.counter))
1767                .collect_vec();
1768            for (node_id, node) in node_ids.iter().zip(encoded.nodes.into_iter()) {
1769                // PERF: we don't need to mov the deleted node, instead we can cache them
1770                // If the parent is TreeParentId::Deleted, then all the nodes afterwards are deleted
1771                tree._init_push_tree_node_in_order(
1772                    *node_id,
1773                    match node.parent_idx_plus_two {
1774                        0 => TreeParentId::Root,
1775                        1 => TreeParentId::Deleted,
1776                        n => {
1777                            let id = node_ids[n - 2];
1778                            TreeParentId::from(Some(id))
1779                        }
1780                    },
1781                    IdFull::new(
1782                        peers[node.last_set_peer_idx],
1783                        node.last_set_counter,
1784                        (node.last_set_lamport_sub_counter + node.last_set_counter) as Lamport,
1785                    ),
1786                    Some(FractionalIndex::from_bytes(
1787                        fractional_indexes[node.fractional_index_idx].clone(),
1788                    )),
1789                )
1790                .unwrap();
1791            }
1792
1793            Ok(tree)
1794        }
1795    }
1796
1797    #[cfg(test)]
1798    mod test {
1799        use loro_common::LoroValue;
1800
1801        use crate::{
1802            container::idx::ContainerIdx,
1803            state::{ContainerCreationContext, ContainerState},
1804            LoroDoc,
1805        };
1806
1807        use super::*;
1808
1809        #[test]
1810        fn test_tree_state_snapshot() {
1811            let doc = LoroDoc::new();
1812            doc.set_peer_id(0).unwrap();
1813            doc.start_auto_commit();
1814            let tree = doc.get_tree("tree");
1815            tree.enable_fractional_index(0);
1816            let a = tree.create(TreeParentId::Root).unwrap();
1817            let b = tree.create(TreeParentId::Root).unwrap();
1818            let _c = tree.create(TreeParentId::Root).unwrap();
1819            tree.mov(b, TreeParentId::Node(a)).unwrap();
1820            let (bytes, value) = {
1821                let mut doc_state = doc.app_state().try_lock().unwrap();
1822                let tree_state = doc_state.get_tree("tree").unwrap();
1823                let value = tree_state.get_value();
1824                let mut bytes = Vec::new();
1825                tree_state.encode_snapshot_fast(&mut bytes);
1826                (bytes, value)
1827            };
1828
1829            assert!(bytes.len() == 55, "{}", bytes.len());
1830            let mut new_tree_state = TreeState::decode_snapshot_fast(
1831                ContainerIdx::from_index_and_type(0, loro_common::ContainerType::Tree),
1832                (LoroValue::Null, &bytes),
1833                ContainerCreationContext {
1834                    configure: &Default::default(),
1835                    peer: 0,
1836                },
1837            )
1838            .unwrap();
1839
1840            let mut doc_state = doc.app_state().try_lock().unwrap();
1841            let tree_state = doc_state.get_tree("tree").unwrap();
1842            assert_eq!(&tree_state.trees, &new_tree_state.trees);
1843            let new_v = new_tree_state.get_value();
1844            assert_eq!(value, new_v);
1845        }
1846    }
1847}