1use std::{collections::VecDeque, sync::Arc};
2
3use fractional_index::FractionalIndex;
4use loro_common::{
5 ContainerID, ContainerType, Counter, IdFull, IdLp, LoroError, LoroResult, LoroTreeError,
6 LoroValue, PeerID, TreeID, ID,
7};
8use rustc_hash::FxHashMap;
9use smallvec::smallvec;
10
11use crate::{
12 container::tree::tree_op::TreeOp,
13 delta::{TreeDiffItem, TreeExternalDiff},
14 state::{
15 FiIfNotConfigured, FractionalIndexGenResult, NodePosition, TreeNode, TreeNodeWithChildren,
16 TreeParentId,
17 },
18 txn::{EventHint, Transaction},
19 BasicHandler, HandlerTrait, MapHandler,
20};
21
22use super::{create_handler, Handler, MaybeDetached};
23
24#[derive(Clone)]
25pub struct TreeHandler {
26 pub(super) inner: MaybeDetached<TreeInner>,
27}
28
29#[derive(Clone)]
30pub(super) struct TreeInner {
31 next_counter: Counter,
32 map: FxHashMap<TreeID, MapHandler>,
33 parent_links: FxHashMap<TreeID, Option<TreeID>>,
34 children_links: FxHashMap<Option<TreeID>, Vec<TreeID>>,
35}
36
37impl TreeInner {
38 fn new() -> Self {
39 TreeInner {
40 next_counter: 0,
41 map: FxHashMap::default(),
42 parent_links: FxHashMap::default(),
43 children_links: FxHashMap::default(),
44 }
45 }
46
47 fn create(&mut self, parent: Option<TreeID>, index: usize) -> TreeID {
48 let id = TreeID::new(PeerID::MAX, self.next_counter);
49 self.next_counter += 1;
50 self.map.insert(id, MapHandler::new_detached());
51 self.parent_links.insert(id, parent);
52 let children = self.children_links.entry(parent).or_default();
53 children.insert(index, id);
54 id
55 }
56
57 fn mov(&mut self, target: TreeID, new_parent: Option<TreeID>, index: usize) -> LoroResult<()> {
58 let old_parent = self
59 .parent_links
60 .get_mut(&target)
61 .ok_or(LoroTreeError::TreeNodeNotExist(target))?;
62 let children = self.children_links.get_mut(old_parent).unwrap();
63 children.retain(|x| x != &target);
64 self.parent_links.insert(target, new_parent);
65 let children = self.children_links.entry(new_parent).or_default();
66 children.insert(index, target);
67 Ok(())
68 }
69
70 fn delete(&mut self, id: TreeID) -> LoroResult<()> {
71 self.map.remove(&id);
72 let parent = self
73 .parent_links
74 .remove(&id)
75 .ok_or(LoroTreeError::TreeNodeNotExist(id))?;
76 let children = self.children_links.get_mut(&parent).unwrap();
77 children.retain(|x| x != &id);
78 self.children_links.remove(&Some(id));
79 Ok(())
80 }
81
82 fn get_id_by_index(&self, parent: &Option<TreeID>, index: usize) -> Option<TreeID> {
83 self.children_links
84 .get(parent)
85 .and_then(|x| x.get(index).cloned())
86 }
87
88 fn get_parent(&self, id: &TreeID) -> Option<Option<TreeID>> {
89 self.parent_links.get(id).cloned()
90 }
91
92 fn get_children(&self, parent: Option<TreeID>) -> Option<Vec<TreeID>> {
93 self.children_links.get(&parent).cloned()
94 }
95
96 fn children_num(&self, parent: Option<TreeID>) -> Option<usize> {
97 self.children_links.get(&parent).map(|x| x.len())
98 }
99
100 fn is_parent(&self, target: &TreeID, parent: &Option<TreeID>) -> bool {
101 self.parent_links.get(target) == Some(parent)
102 }
103
104 fn get_index_by_tree_id(&self, target: &TreeID) -> Option<usize> {
105 self.parent_links
106 .get(target)
107 .and_then(|parent| self.children_links.get(parent))
108 .and_then(|children| children.iter().position(|x| x == target))
109 }
110
111 fn get_value(&self, deep: bool) -> LoroValue {
112 let mut ans = vec![];
113
114 let empty_vec = vec![];
115 let mut q = VecDeque::from_iter(
116 self.children_links
117 .get(&None)
118 .unwrap_or(&empty_vec)
119 .iter()
120 .enumerate()
121 .zip(std::iter::repeat(None::<TreeID>)),
122 );
123
124 while let Some(((idx, target), parent)) = q.pop_front() {
125 let map = self.map.get(target).unwrap();
126 let mut loro_map_value = FxHashMap::default();
127 loro_map_value.insert("id".to_string(), target.to_string().into());
128 let parent = parent
129 .map(|p| p.to_string().into())
130 .unwrap_or(LoroValue::Null);
131 loro_map_value.insert("parent".to_string(), parent);
132 loro_map_value.insert(
133 "meta".to_string(),
134 if deep {
135 map.get_deep_value()
136 } else {
137 String::from("UnResolved").into()
138 },
139 );
140 loro_map_value.insert("index".to_string(), (idx as i64).into());
141 ans.push(loro_map_value);
142 if let Some(children) = self.children_links.get(&Some(*target)) {
143 for (idx, child) in children.iter().enumerate() {
144 q.push_back(((idx, child), Some(*target)));
145 }
146 }
147 }
148 ans.into()
149 }
150
151 fn get_nodes_under(&self, root: TreeParentId) -> Vec<TreeNode> {
152 let root_id = root.tree_id();
153 let mut ans = vec![];
154 let empty_vec = vec![];
155 let mut q = VecDeque::from_iter(
156 self.children_links
157 .get(&root_id)
158 .unwrap_or(&empty_vec)
159 .iter()
160 .enumerate()
161 .zip(std::iter::repeat(root)),
162 );
163
164 while let Some(((index, target), parent)) = q.pop_front() {
165 ans.push(TreeNode {
166 id: *target,
167 parent,
168 fractional_index: FractionalIndex::default(),
169 index,
170 last_move_op: IdFull {
171 peer: target.peer,
172 lamport: 0,
173 counter: target.counter,
174 },
175 });
176 if let Some(children) = self.children_links.get(&Some(*target)) {
177 let parent = TreeParentId::Node(*target);
178 q.extend(
179 children
180 .iter()
181 .enumerate()
182 .map(|(index, target)| ((index, target), parent)),
183 );
184 }
185 }
186
187 ans
188 }
189}
190
191impl HandlerTrait for TreeHandler {
192 fn to_handler(&self) -> Handler {
193 Handler::Tree(self.clone())
194 }
195
196 fn attach(
197 &self,
198 txn: &mut Transaction,
199 parent: &BasicHandler,
200 self_id: ContainerID,
201 ) -> LoroResult<Self> {
202 match &self.inner {
203 MaybeDetached::Detached(t) => {
204 let mut t = t.lock();
205 let inner = create_handler(parent, self_id);
206 let tree = inner.into_tree().unwrap();
207
208 let children = t.value.children_links.get(&None);
209 let mut q = children
210 .map(|c| {
211 VecDeque::from_iter(
212 c.iter()
213 .enumerate()
214 .zip(std::iter::repeat(TreeParentId::Root)),
215 )
216 })
217 .unwrap_or_default();
218 while let Some(((idx, target), parent)) = q.pop_front() {
219 let real_id =
220 tree.create_with_txn(txn, parent, idx, FiIfNotConfigured::UseJitterZero)?;
221 let map = t.value.map.get(target).unwrap();
222 map.attach(
223 txn,
224 tree.inner.try_attached_state()?,
225 real_id.associated_meta_container(),
226 )?;
227
228 if let Some(children) = t.value.children_links.get(&Some(*target)) {
229 for (idx, child) in children.iter().enumerate() {
230 q.push_back(((idx, child), TreeParentId::Node(real_id)));
231 }
232 }
233 }
234 t.attached = tree.attached_handler().cloned();
235 Ok(tree)
236 }
237 MaybeDetached::Attached(a) => {
238 let new_inner = create_handler(a, self_id);
239 let ans = new_inner.into_tree().unwrap();
240
241 fn attach_nodes(
242 source: &TreeHandler,
243 target: &TreeHandler,
244 txn: &mut Transaction,
245 parent: TreeParentId,
246 nodes: Vec<TreeNodeWithChildren>,
247 ) -> LoroResult<()> {
248 for node in nodes {
249 let real_id = target.create_with_txn(
250 txn,
251 parent,
252 node.index,
253 FiIfNotConfigured::UseJitterZero,
254 )?;
255 source.get_meta(node.id)?.attach(
256 txn,
257 target.inner.try_attached_state()?,
258 real_id.associated_meta_container(),
259 )?;
260 attach_nodes(
261 source,
262 target,
263 txn,
264 TreeParentId::Node(real_id),
265 node.children,
266 )?;
267 }
268
269 Ok(())
270 }
271
272 let tree_nodes = self.get_all_hierarchy_nodes_under(TreeParentId::Root);
273 attach_nodes(self, &ans, txn, TreeParentId::Root, tree_nodes)?;
274 Ok(ans)
275 }
276 }
277 }
278
279 fn is_attached(&self) -> bool {
280 self.inner.is_attached()
281 }
282
283 fn attached_handler(&self) -> Option<&BasicHandler> {
284 self.inner.attached_handler()
285 }
286
287 fn get_value(&self) -> LoroValue {
288 match &self.inner {
289 MaybeDetached::Detached(t) => {
290 let t = t.lock();
291 t.value.get_value(false)
292 }
293 MaybeDetached::Attached(a) => a.get_value(),
294 }
295 }
296
297 fn get_deep_value(&self) -> LoroValue {
298 match &self.inner {
299 MaybeDetached::Detached(t) => {
300 let t = t.lock();
301 t.value.get_value(true)
302 }
303 MaybeDetached::Attached(a) => a.get_deep_value(),
304 }
305 }
306
307 fn kind(&self) -> ContainerType {
308 ContainerType::Tree
309 }
310
311 fn get_attached(&self) -> Option<Self> {
312 match &self.inner {
313 MaybeDetached::Detached(d) => d.lock().attached.clone().map(|x| Self {
314 inner: MaybeDetached::Attached(x),
315 }),
316 MaybeDetached::Attached(_a) => Some(self.clone()),
317 }
318 }
319
320 fn from_handler(h: Handler) -> Option<Self> {
321 match h {
322 Handler::Tree(x) => Some(x),
323 _ => None,
324 }
325 }
326
327 fn doc(&self) -> Option<crate::LoroDoc> {
328 match &self.inner {
329 MaybeDetached::Detached(_) => None,
330 MaybeDetached::Attached(a) => Some(a.doc()),
331 }
332 }
333}
334
335impl std::fmt::Debug for TreeHandler {
336 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
337 match &self.inner {
338 MaybeDetached::Detached(_) => write!(f, "TreeHandler Detached"),
339 MaybeDetached::Attached(a) => write!(f, "TreeHandler {}", a.id),
340 }
341 }
342}
343
344impl TreeHandler {
345 pub fn new_detached() -> Self {
351 Self {
352 inner: MaybeDetached::new_detached(TreeInner::new()),
353 }
354 }
355
356 pub fn get_deep_value_with_id(&self) -> LoroResult<LoroValue> {
360 let inner = self.inner.try_attached_state()?;
361 Ok(inner.with_doc_state(|state| {
362 state.get_container_deep_value_with_id(inner.container_idx, None)
363 }))
364 }
365
366 pub fn delete(&self, target: TreeID) -> LoroResult<()> {
367 match &self.inner {
368 MaybeDetached::Detached(t) => {
369 let mut t = t.lock();
370 t.value.delete(target)?;
371 Ok(())
372 }
373 MaybeDetached::Attached(a) => a.with_txn(|txn| self.delete_with_txn(txn, target)),
374 }
375 }
376
377 pub(crate) fn delete_with_txn(&self, txn: &mut Transaction, target: TreeID) -> LoroResult<()> {
378 let inner = self.inner.try_attached_state()?;
379 let index = match self.get_index_by_tree_id(&target) {
380 Some(i) => i,
381 None => {
382 return Err(LoroTreeError::TreeNodeDeletedOrNotExist(target).into());
383 }
384 };
385 txn.apply_local_op(
386 inner.container_idx,
387 crate::op::RawOpContent::Tree(Arc::new(TreeOp::Delete { target })),
388 EventHint::Tree(smallvec![TreeDiffItem {
389 target,
390 action: TreeExternalDiff::Delete {
391 old_parent: self
392 .get_node_parent(&target)
393 .ok_or(LoroTreeError::TreeNodeDeletedOrNotExist(target))?,
394 old_index: index
395 },
396 }]),
397 &inner.doc,
398 )
399 }
400
401 pub fn create(&self, parent: TreeParentId) -> LoroResult<TreeID> {
402 match parent {
403 TreeParentId::Deleted | TreeParentId::Unexist => {
404 return Err(LoroTreeError::InvalidParent.into());
405 }
406 _ => {}
407 }
408 let index: usize = self.children_num(&parent).unwrap_or(0);
409 match &self.inner {
410 MaybeDetached::Detached(t) => {
411 let t = &mut t.lock().value;
412 Ok(t.create(parent.tree_id(), index))
413 }
414 MaybeDetached::Attached(a) => {
415 a.with_txn(|txn| self.create_with_txn(txn, parent, index, FiIfNotConfigured::Zero))
416 }
417 }
418 }
419
420 pub fn create_at(&self, parent: TreeParentId, index: usize) -> LoroResult<TreeID> {
421 match parent {
422 TreeParentId::Deleted | TreeParentId::Unexist => {
423 return Err(LoroTreeError::InvalidParent.into());
424 }
425 _ => {}
426 }
427 let children_len = self.children_num(&parent).unwrap_or(0);
428 if index > children_len {
429 return Err(LoroTreeError::IndexOutOfBound {
430 len: children_len,
431 index,
432 }
433 .into());
434 }
435 match &self.inner {
436 MaybeDetached::Detached(t) => {
437 let t = &mut t.lock().value;
438 Ok(t.create(parent.tree_id(), index))
439 }
440 MaybeDetached::Attached(a) => {
441 a.with_txn(|txn| self.create_with_txn(txn, parent, index, FiIfNotConfigured::Throw))
442 }
443 }
444 }
445
446 pub(crate) fn create_at_with_target_for_apply_diff(
448 &self,
449 parent: TreeParentId,
450 position: FractionalIndex,
451 target: TreeID,
452 ) -> LoroResult<bool> {
453 let MaybeDetached::Attached(a) = &self.inner else {
454 unreachable!();
455 };
456
457 if let Some(p) = self.get_node_parent(&target) {
458 if p == parent {
459 return Ok(false);
460 }
462 match p {
463 TreeParentId::Node(p) => {
464 if !self.is_node_unexist(&target) && !self.is_node_deleted(&p)? {
465 return self.move_at_with_target_for_apply_diff(parent, position, target);
466 }
467 }
468 TreeParentId::Root => {
469 return self.move_at_with_target_for_apply_diff(parent, position, target);
470 }
471 TreeParentId::Deleted | TreeParentId::Unexist => {}
472 }
473 }
474
475 let with_event = !parent
476 .tree_id()
477 .is_some_and(|p| self.is_node_deleted(&p).unwrap());
478 if !with_event {
479 return Ok(false);
480 }
481
482 let index = self
488 .get_index_by_fractional_index(
489 &parent,
490 &NodePosition {
491 position: position.clone(),
492 idlp: self.next_idlp(),
493 },
494 )
495 .unwrap_or(0);
497
498 let children = a.with_txn(|txn| {
499 let inner = self.inner.try_attached_state()?;
500
501 txn.apply_local_op(
502 inner.container_idx,
503 crate::op::RawOpContent::Tree(Arc::new(TreeOp::Create {
504 target,
505 parent: parent.tree_id(),
506 position: position.clone(),
507 })),
508 EventHint::Tree(smallvec![TreeDiffItem {
509 target,
510 action: TreeExternalDiff::Create {
511 parent,
512 index,
513 position: position.clone(),
514 },
515 }]),
516 &inner.doc,
517 )?;
518
519 Ok(self
520 .children(&TreeParentId::Node(target))
521 .unwrap_or_default())
522 })?;
523 for child in children {
524 let position = self.get_position_by_tree_id(&child).unwrap();
525 self.create_at_with_target_for_apply_diff(TreeParentId::Node(target), position, child)?;
526 }
527 Ok(true)
528 }
529
530 pub(crate) fn move_at_with_target_for_apply_diff(
532 &self,
533 parent: TreeParentId,
534 position: FractionalIndex,
535 target: TreeID,
536 ) -> LoroResult<bool> {
537 let MaybeDetached::Attached(a) = &self.inner else {
538 unreachable!();
539 };
540
541 if let (Some(p), Some(fi)) = (
547 self.get_node_parent(&target),
548 self.get_position_by_tree_id(&target),
549 ) {
550 if p == parent && position == fi {
551 return Ok(false);
552 }
553 }
554
555 let old_parent = self.get_node_parent(&target).unwrap();
556 let old_index = self.get_index_by_tree_id(&target).unwrap();
557 let mut index = self
558 .get_index_by_fractional_index(
559 &parent,
560 &NodePosition {
561 position: position.clone(),
562 idlp: self.next_idlp(),
563 },
564 )
565 .unwrap_or(0);
566 if old_parent == parent && old_index < index {
567 index -= 1;
568 }
569 let with_event = match parent.tree_id() {
570 Some(p) => !self.is_node_deleted(&p)?,
571 None => true,
572 };
573
574 if !with_event {
575 return Ok(false);
576 }
577
578 a.with_txn(|txn| {
584 let inner = self.inner.try_attached_state()?;
585 txn.apply_local_op(
586 inner.container_idx,
587 crate::op::RawOpContent::Tree(Arc::new(TreeOp::Move {
588 target,
589 parent: parent.tree_id(),
590 position: position.clone(),
591 })),
592 EventHint::Tree(smallvec![TreeDiffItem {
593 target,
594 action: TreeExternalDiff::Move {
595 parent,
596 index,
597 position: position.clone(),
598 old_parent,
600 old_index,
601 },
602 }]),
603 &inner.doc,
604 )
605 })?;
606 Ok(true)
607 }
608
609 pub(crate) fn create_with_txn(
610 &self,
611 txn: &mut Transaction,
612 parent: TreeParentId,
613 index: usize,
614 cfg: FiIfNotConfigured,
615 ) -> LoroResult<TreeID> {
616 let inner = self.inner.try_attached_state()?;
617 let target = TreeID::from_id(txn.next_id());
618
619 match self.generate_position_at(&target, &parent, index, cfg) {
620 FractionalIndexGenResult::Ok(position) => {
621 self.create_with_position(inner, txn, target, parent, index, position)
622 }
623 FractionalIndexGenResult::Rearrange(ids) => {
624 for (i, (id, position)) in ids.into_iter().enumerate() {
625 if i == 0 {
626 self.create_with_position(inner, txn, id, parent, index, position)?;
627 continue;
628 }
629 self.mov_with_position(inner, txn, id, parent, index + i, position, index + i)?;
630 }
631 Ok(target)
632 }
633 FractionalIndexGenResult::NotConfigured => {
634 Err(LoroTreeError::FractionalIndexNotEnabled.into())
635 }
636 }
637 }
638
639 pub fn mov(&self, target: TreeID, parent: TreeParentId) -> LoroResult<()> {
640 match &self.inner {
641 MaybeDetached::Detached(_) => {
642 let mut index: usize = self.children_num(&parent).unwrap_or(0);
643 if self.is_parent(&target, &parent) {
644 index -= 1;
645 }
646 self.move_to(target, parent, index)
647 }
648 MaybeDetached::Attached(a) => {
649 let mut index: usize = self.children_num(&parent).unwrap_or(0);
650 if self.is_parent(&target, &parent) {
651 index -= 1;
652 }
653 a.with_txn(|txn| {
654 self.mov_with_txn(txn, target, parent, index, FiIfNotConfigured::Zero)
655 })
656 }
657 }
658 }
659
660 pub fn mov_after(&self, target: TreeID, other: TreeID) -> LoroResult<()> {
661 let parent = self
662 .get_node_parent(&other)
663 .ok_or(LoroTreeError::TreeNodeNotExist(other))?;
664 let mut index = self
665 .get_index_by_tree_id(&other)
666 .ok_or(LoroTreeError::TreeNodeDeletedOrNotExist(other))?
667 + 1;
668 if self.is_parent(&target, &parent) {
669 if let Some(target_index) = self.get_index_by_tree_id(&target) {
670 if target_index < index {
671 index -= 1;
672 }
673 }
674 }
675 self.move_to(target, parent, index)
676 }
677
678 pub fn mov_before(&self, target: TreeID, other: TreeID) -> LoroResult<()> {
679 let parent = self
680 .get_node_parent(&other)
681 .ok_or(LoroTreeError::TreeNodeNotExist(other))?;
682 let mut index = self
683 .get_index_by_tree_id(&other)
684 .ok_or(LoroTreeError::TreeNodeDeletedOrNotExist(other))?;
685 if self.is_parent(&target, &parent) && index >= 1 {
686 if let Some(target_index) = self.get_index_by_tree_id(&target) {
687 if target_index < index {
688 index -= 1;
689 }
690 }
691 }
692 self.move_to(target, parent, index)
693 }
694
695 pub fn move_to(&self, target: TreeID, parent: TreeParentId, index: usize) -> LoroResult<()> {
696 match &self.inner {
697 MaybeDetached::Detached(t) => {
698 let mut t = t.lock();
699 t.value.mov(target, parent.tree_id(), index)
700 }
701 MaybeDetached::Attached(a) => a.with_txn(|txn| {
702 self.mov_with_txn(txn, target, parent, index, FiIfNotConfigured::Throw)
703 }),
704 }
705 }
706
707 pub(crate) fn mov_with_txn(
708 &self,
709 txn: &mut Transaction,
710 target: TreeID,
711 parent: TreeParentId,
712 index: usize,
713 cfg: FiIfNotConfigured,
714 ) -> LoroResult<()> {
715 let inner = self.inner.try_attached_state()?;
716 let mut children_len = self.children_num(&parent).unwrap_or(0);
717 let mut already_in_parent = false;
718 if self.is_parent(&target, &parent) {
720 if let Some(current_index) = self.get_index_by_tree_id(&target) {
722 if current_index == index {
723 return Ok(());
724 }
725 children_len -= 1;
728 already_in_parent = true;
729 }
730 };
731 if index > children_len {
732 return Err(LoroTreeError::IndexOutOfBound {
733 len: children_len,
734 index,
735 }
736 .into());
737 }
738 let Some(old_index) = self.get_index_by_tree_id(&target) else {
739 return Err(LoroError::TreeError(
740 LoroTreeError::TreeNodeDeletedOrNotExist(target),
741 ));
742 };
743
744 if already_in_parent {
745 self.delete_position(&parent, &target);
746 }
747
748 match self.generate_position_at(&target, &parent, index, cfg) {
749 FractionalIndexGenResult::Ok(position) => {
750 self.mov_with_position(inner, txn, target, parent, index, position, old_index)
751 }
752 FractionalIndexGenResult::Rearrange(ids) => {
753 for (i, (id, position)) in ids.into_iter().enumerate() {
754 self.mov_with_position(inner, txn, id, parent, index + i, position, old_index)?;
755 }
756 Ok(())
757 }
758 FractionalIndexGenResult::NotConfigured => {
759 Err(LoroTreeError::FractionalIndexNotEnabled.into())
760 }
761 }
762 }
763
764 #[allow(clippy::too_many_arguments)]
765 fn create_with_position(
766 &self,
767 inner: &BasicHandler,
768 txn: &mut Transaction,
769 tree_id: TreeID,
770 parent: TreeParentId,
771 index: usize,
772 position: FractionalIndex,
773 ) -> LoroResult<TreeID> {
774 txn.apply_local_op(
775 inner.container_idx,
776 crate::op::RawOpContent::Tree(Arc::new(TreeOp::Create {
777 target: tree_id,
778 parent: parent.tree_id(),
779 position: position.clone(),
780 })),
781 EventHint::Tree(smallvec![TreeDiffItem {
782 target: tree_id,
783 action: TreeExternalDiff::Create {
784 parent,
785 index,
786 position,
787 },
788 }]),
789 &inner.doc,
790 )?;
791 Ok(tree_id)
792 }
793
794 #[allow(clippy::too_many_arguments)]
795 fn mov_with_position(
796 &self,
797 inner: &BasicHandler,
798 txn: &mut Transaction,
799 target: TreeID,
800 parent: TreeParentId,
801 index: usize,
802 position: FractionalIndex,
803 old_index: usize,
804 ) -> LoroResult<()> {
805 txn.apply_local_op(
806 inner.container_idx,
807 crate::op::RawOpContent::Tree(Arc::new(TreeOp::Move {
808 target,
809 parent: parent.tree_id(),
810 position: position.clone(),
811 })),
812 EventHint::Tree(smallvec![TreeDiffItem {
813 target,
814 action: TreeExternalDiff::Move {
815 parent,
816 index,
817 position,
818 old_parent: self
819 .get_node_parent(&target)
820 .ok_or(LoroTreeError::TreeNodeDeletedOrNotExist(target))?,
821 old_index,
822 },
823 }]),
824 &inner.doc,
825 )
826 }
827
828 pub fn get_meta(&self, target: TreeID) -> LoroResult<MapHandler> {
829 match &self.inner {
830 MaybeDetached::Detached(d) => {
831 let d = d.lock();
832 d.value
833 .map
834 .get(&target)
835 .cloned()
836 .ok_or(LoroTreeError::TreeNodeNotExist(target).into())
837 }
838 MaybeDetached::Attached(a) => {
839 if self.is_node_unexist(&target) {
840 return Err(LoroTreeError::TreeNodeNotExist(target).into());
841 }
842 let map_container_id = target.associated_meta_container();
843 let handler = create_handler(a, map_container_id);
844 handler.into_map().map_err(|_| {
845 LoroError::DecodeError(
846 "Tree node's associated meta container is not a map".into(),
847 )
848 })
849 }
850 }
851 }
852
853 pub fn is_node_unexist(&self, target: &TreeID) -> bool {
854 match &self.inner {
855 MaybeDetached::Detached(d) => {
856 let d = d.lock();
857 !d.value.map.contains_key(target)
858 }
859 MaybeDetached::Attached(a) => a.with_state(|state| {
860 let a = state.as_tree_state().unwrap();
861 a.is_node_unexist(target)
862 }),
863 }
864 }
865
866 pub fn is_node_deleted(&self, target: &TreeID) -> LoroResult<bool> {
867 match &self.inner {
868 MaybeDetached::Detached(t) => {
869 let t = t.lock();
870 t.value
871 .map
872 .get(target)
873 .and(Some(true))
874 .ok_or(LoroTreeError::TreeNodeNotExist(*target).into())
875 }
876 MaybeDetached::Attached(a) => a.with_state(|state| {
877 let a = state.as_tree_state().unwrap();
878 a.is_node_deleted(target)
879 .ok_or(LoroTreeError::TreeNodeNotExist(*target).into())
880 }),
881 }
882 }
883
884 pub fn get_node_parent(&self, target: &TreeID) -> Option<TreeParentId> {
886 match &self.inner {
887 MaybeDetached::Detached(t) => {
888 let t = t.lock();
889 t.value.get_parent(target).map(TreeParentId::from)
890 }
891 MaybeDetached::Attached(a) => a.with_state(|state| {
892 let a = state.as_tree_state().unwrap();
893 a.parent(target)
894 }),
895 }
896 }
897
898 pub fn children(&self, parent: &TreeParentId) -> Option<Vec<TreeID>> {
900 match &self.inner {
901 MaybeDetached::Detached(t) => {
902 let t = t.lock();
903 t.value.get_children(parent.tree_id())
904 }
905 MaybeDetached::Attached(a) => a.with_state(|state| {
906 let a = state.as_tree_state().unwrap();
907 a.get_children(parent).map(|x| x.collect())
908 }),
909 }
910 }
911
912 pub fn children_num(&self, parent: &TreeParentId) -> Option<usize> {
913 match &self.inner {
914 MaybeDetached::Detached(t) => {
915 let t = t.lock();
916 t.value.children_num(parent.tree_id())
917 }
918 MaybeDetached::Attached(a) => a.with_state(|state| {
919 let a = state.as_tree_state().unwrap();
920 a.children_num(parent)
921 }),
922 }
923 }
924
925 pub fn contains(&self, target: TreeID) -> bool {
927 match &self.inner {
928 MaybeDetached::Detached(t) => {
929 let t = t.lock();
930 t.value.map.contains_key(&target)
931 }
932 MaybeDetached::Attached(a) => a.with_state(|state| {
933 let a = state.as_tree_state().unwrap();
934 !a.is_node_unexist(&target)
935 }),
936 }
937 }
938
939 pub fn get_child_at(&self, parent: &TreeParentId, index: usize) -> Option<TreeID> {
940 match &self.inner {
941 MaybeDetached::Detached(t) => {
942 let t = t.lock();
943 t.value.get_id_by_index(&parent.tree_id(), index)
944 }
945 MaybeDetached::Attached(a) => a.with_state(|state| {
946 let a = state.as_tree_state().unwrap();
947 a.get_id_by_index(parent, index)
948 }),
949 }
950 }
951
952 pub fn is_parent(&self, target: &TreeID, parent: &TreeParentId) -> bool {
953 match &self.inner {
954 MaybeDetached::Detached(t) => {
955 let t = t.lock();
956 t.value.is_parent(target, &parent.tree_id())
957 }
958 MaybeDetached::Attached(a) => a.with_state(|state| {
959 let a = state.as_tree_state().unwrap();
960 a.is_parent(target, parent)
961 }),
962 }
963 }
964
965 pub fn nodes(&self) -> Vec<TreeID> {
967 match &self.inner {
968 MaybeDetached::Detached(t) => {
969 let t = t.lock();
970 t.value.map.keys().cloned().collect()
971 }
972 MaybeDetached::Attached(a) => a.with_state(|state| {
973 let a = state.as_tree_state().unwrap();
974 a.nodes()
975 }),
976 }
977 }
978
979 pub fn get_nodes_under(&self, parent: TreeParentId) -> Vec<TreeNode> {
980 match &self.inner {
981 MaybeDetached::Detached(t) => t.lock().value.get_nodes_under(parent),
982 MaybeDetached::Attached(a) => a.with_state(|state| {
983 let a = state.as_tree_state().unwrap();
984 a.get_all_tree_nodes_under(parent)
985 }),
986 }
987 }
988 pub fn roots(&self) -> Vec<TreeID> {
989 self.children(&TreeParentId::Root).unwrap_or_default()
990 }
991
992 pub fn get_all_hierarchy_nodes_under(&self, parent: TreeParentId) -> Vec<TreeNodeWithChildren> {
993 match &self.inner {
994 MaybeDetached::Detached(_t) => {
995 unreachable!()
996 }
997 MaybeDetached::Attached(a) => a.with_state(|state| {
998 let a = state.as_tree_state().unwrap();
999 a.get_all_hierarchy_nodes_under(parent)
1000 }),
1001 }
1002 }
1003
1004 #[allow(non_snake_case)]
1005 pub fn __internal__next_tree_id(&self) -> TreeID {
1006 match &self.inner {
1007 MaybeDetached::Detached(d) => {
1008 let d = d.lock();
1009 TreeID::new(PeerID::MAX, d.value.next_counter)
1010 }
1011 MaybeDetached::Attached(a) => a
1012 .with_txn(|txn| Ok(TreeID::from_id(txn.next_id())))
1013 .unwrap(),
1014 }
1015 }
1016
1017 fn generate_position_at(
1018 &self,
1019 target: &TreeID,
1020 parent: &TreeParentId,
1021 index: usize,
1022 cfg: FiIfNotConfigured,
1023 ) -> FractionalIndexGenResult {
1024 let MaybeDetached::Attached(a) = &self.inner else {
1025 unreachable!()
1026 };
1027 a.with_state(|state| {
1028 let a = state.as_tree_state_mut().unwrap();
1029 a.generate_position_at(target, parent, index, cfg)
1030 })
1031 }
1032
1033 pub fn get_index_by_tree_id(&self, target: &TreeID) -> Option<usize> {
1037 match &self.inner {
1038 MaybeDetached::Detached(t) => {
1039 let t = t.lock();
1040 t.value.get_index_by_tree_id(target)
1041 }
1042 MaybeDetached::Attached(a) => a.with_state(|state| {
1043 let a = state.as_tree_state().unwrap();
1044 a.get_index_by_tree_id(target)
1045 }),
1046 }
1047 }
1048
1049 pub fn get_position_by_tree_id(&self, target: &TreeID) -> Option<FractionalIndex> {
1050 match &self.inner {
1051 MaybeDetached::Detached(t) => t
1052 .lock()
1053 .value
1054 .parent_links
1055 .contains_key(target)
1056 .then(FractionalIndex::default),
1057 MaybeDetached::Attached(a) => a.with_state(|state| {
1058 let a = state.as_tree_state().unwrap();
1059 a.get_position(target)
1060 }),
1061 }
1062 }
1063
1064 fn delete_position(&self, parent: &TreeParentId, target: &TreeID) {
1065 let MaybeDetached::Attached(a) = &self.inner else {
1066 unreachable!()
1067 };
1068 a.with_state(|state| {
1069 let a = state.as_tree_state_mut().unwrap();
1070 a.try_delete_position_cache(parent, target)
1071 })
1072 }
1073
1074 pub(crate) fn get_index_by_fractional_index(
1076 &self,
1077 parent: &TreeParentId,
1078 node_position: &NodePosition,
1079 ) -> Option<usize> {
1080 match &self.inner {
1081 MaybeDetached::Detached(_) => {
1082 unreachable!();
1083 }
1084 MaybeDetached::Attached(a) => a.with_state(|state| {
1085 let a = state.as_tree_state().unwrap();
1086 a.get_index_by_position(parent, node_position)
1087 }),
1088 }
1089 }
1090
1091 pub(crate) fn next_idlp(&self) -> IdLp {
1092 match &self.inner {
1093 MaybeDetached::Detached(_) => {
1094 unreachable!()
1095 }
1096 MaybeDetached::Attached(a) => a.with_txn(|txn| Ok(txn.next_idlp())).unwrap(),
1097 }
1098 }
1099
1100 pub fn is_fractional_index_enabled(&self) -> bool {
1101 match &self.inner {
1102 MaybeDetached::Detached(_) => true,
1103 MaybeDetached::Attached(a) => a.with_state(|state| {
1104 let a = state.as_tree_state().unwrap();
1105 a.is_fractional_index_enabled()
1106 }),
1107 }
1108 }
1109
1110 pub fn enable_fractional_index(&self, jitter: u8) {
1118 match &self.inner {
1119 MaybeDetached::Detached(_) => {
1120 let _ = jitter;
1122 }
1123 MaybeDetached::Attached(a) => a.with_state(|state| {
1124 let a = state.as_tree_state_mut().unwrap();
1125 a.enable_generate_fractional_index(jitter);
1126 }),
1127 }
1128 }
1129
1130 pub fn disable_fractional_index(&self) {
1135 match &self.inner {
1136 MaybeDetached::Detached(_) => {
1137 }
1139 MaybeDetached::Attached(a) => a.with_state(|state| {
1140 let a = state.as_tree_state_mut().unwrap();
1141 a.disable_generate_fractional_index();
1142 }),
1143 }
1144 }
1145
1146 pub fn is_deleted(&self) -> bool {
1147 match &self.inner {
1148 MaybeDetached::Detached(_) => false,
1149 MaybeDetached::Attached(a) => a.is_deleted(),
1150 }
1151 }
1152
1153 pub fn is_empty(&self) -> bool {
1154 match &self.inner {
1155 MaybeDetached::Detached(t) => {
1156 let t = t.lock();
1157 t.value.map.is_empty()
1158 }
1159 MaybeDetached::Attached(a) => a.with_state(|state| {
1160 let a = state.as_tree_state().unwrap();
1161 a.is_empty()
1162 }),
1163 }
1164 }
1165
1166 pub fn get_last_move_id(&self, target: &TreeID) -> Option<ID> {
1167 match &self.inner {
1168 MaybeDetached::Detached(_) => None,
1169 MaybeDetached::Attached(a) => a.with_state(|state| {
1170 let a = state.as_tree_state().unwrap();
1171 a.get_last_move_id(target)
1172 }),
1173 }
1174 }
1175
1176 pub fn clear(&self) -> LoroResult<()> {
1177 match &self.inner {
1178 MaybeDetached::Detached(t) => {
1179 let mut t = t.lock();
1180 t.value.map.clear();
1181 t.value.children_links.clear();
1182 t.value.parent_links.clear();
1183 Ok(())
1184 }
1185 MaybeDetached::Attached(_) => {
1186 let nodes = self.get_nodes_under(TreeParentId::Root);
1187 for node in nodes {
1188 self.delete(node.id)?;
1189 }
1190 Ok(())
1191 }
1192 }
1193 }
1194}