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#[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 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 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 let Some(left_fi) = left_fi {
194 if Some(left_fi) == right.map(|x| &x.0.position) {
195 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 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 pub fn parent(&self, target: &TreeID) -> Option<TreeParentId> {
765 self.trees.get(target).map(|x| x.parent)
766 }
767
768 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 pub(crate) fn tree_nodes(&self) -> Vec<TreeNode> {
784 self.get_all_tree_nodes_under(TreeParentId::Root)
785 }
786
787 #[allow(unused)]
789 pub(crate) fn deleted_tree_nodes(&self) -> Vec<TreeNode> {
790 self.get_all_tree_nodes_under(TreeParentId::Deleted)
791 }
792
793 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 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 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 #[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 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 for diff in tree.diff.iter() {
1072 let last_move_op = diff.last_effective_move_op_id;
1073 let target = diff.target;
1074 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 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 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 ans.push(TreeDiffItem {
1111 target,
1112 action: TreeExternalDiff::Delete {
1113 old_parent,
1114 old_index: old_index.unwrap(),
1115 },
1116 });
1117 }
1118 } else if was_alive {
1120 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 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 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 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 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 Diff::Tree(TreeDiff { diff: ans })
1231 }
1232
1233 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 for diff in tree.diff.iter() {
1240 let last_move_op = diff.last_effective_move_op_id;
1241 let target = diff.target;
1242 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 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 }
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 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 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 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#[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 let Some(left_fi) = left_fi {
1540 if Some(left_fi) == right.map(|x| &x.0.position) {
1541 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 #[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 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 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}