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