1use std::cell::RefCell;
40use std::rc::Rc;
41
42use slotmap::SlotMap;
43
44use teksilo_core::ObserverHandle;
45
46use crate::tree_change::{NodeId, TreeChange};
47
48struct TreeNode<T> {
49 data: T,
50 parent: Option<NodeId>,
51 children: Vec<NodeId>,
52}
53
54struct TreeObserverEntry {
55 id: u64,
56 callback: Rc<dyn Fn(&TreeChange)>,
57}
58
59struct TreeModelInner<T> {
60 arena: SlotMap<slotmap::DefaultKey, TreeNode<T>>,
61 roots: Vec<NodeId>,
62 observers: Vec<TreeObserverEntry>,
63 next_observer_id: u64,
64 #[cfg(debug_assertions)]
70 debug_adapter: Option<Rc<dyn crate::debug_registry::ModelDebug>>,
71}
72
73pub struct TreeModel<T: 'static> {
81 inner: Rc<RefCell<TreeModelInner<T>>>,
82}
83
84impl<T: 'static> TreeModel<T> {
85 pub fn new() -> Self {
87 Self {
88 inner: Rc::new(RefCell::new(TreeModelInner {
89 arena: SlotMap::new(),
90 roots: Vec::new(),
91 observers: Vec::new(),
92 next_observer_id: 1,
93 #[cfg(debug_assertions)]
94 debug_adapter: None,
95 })),
96 }
97 }
98
99 pub fn root_count(&self) -> usize {
103 self.inner.borrow().roots.len()
104 }
105
106 pub fn root(&self, index: usize) -> NodeId {
111 self.inner.borrow().roots[index]
112 }
113
114 pub fn child_count(&self, parent: NodeId) -> usize {
116 let guard = self.inner.borrow();
117 guard
118 .arena
119 .get(parent.key())
120 .map(|n| n.children.len())
121 .unwrap_or(0)
122 }
123
124 pub fn child(&self, parent: NodeId, index: usize) -> NodeId {
129 let guard = self.inner.borrow();
130 guard.arena[parent.key()].children[index]
131 }
132
133 pub fn parent(&self, node: NodeId) -> Option<NodeId> {
135 let guard = self.inner.borrow();
136 guard.arena.get(node.key()).and_then(|n| n.parent)
137 }
138
139 pub fn depth(&self, node: NodeId) -> usize {
141 let guard = self.inner.borrow();
142 let mut depth = 0;
143 let mut current = guard.arena.get(node.key()).and_then(|n| n.parent);
144 while let Some(pid) = current {
145 depth += 1;
146 current = guard.arena.get(pid.key()).and_then(|n| n.parent);
147 }
148 depth
149 }
150
151 pub fn has_children(&self, node: NodeId) -> bool {
153 self.child_count(node) > 0
154 }
155
156 pub fn children(&self, node: NodeId) -> Vec<NodeId> {
158 let guard = self.inner.borrow();
159 guard
160 .arena
161 .get(node.key())
162 .map(|n| n.children.clone())
163 .unwrap_or_default()
164 }
165
166 pub fn with_item<R>(&self, node: NodeId, f: impl FnOnce(&T) -> R) -> Option<R> {
168 let guard = self.inner.borrow();
169 guard.arena.get(node.key()).map(|n| f(&n.data))
170 }
171
172 pub fn find_by(&self, predicate: impl Fn(&T) -> bool) -> Option<NodeId> {
174 let guard = self.inner.borrow();
175 let mut stack: Vec<NodeId> = guard.roots.iter().rev().copied().collect();
176 while let Some(nid) = stack.pop() {
177 if let Some(node) = guard.arena.get(nid.key()) {
178 if predicate(&node.data) {
179 return Some(nid);
180 }
181 for &child_id in node.children.iter().rev() {
182 stack.push(child_id);
183 }
184 }
185 }
186 None
187 }
188
189 pub fn insert_root(&self, index: usize, item: T) -> NodeId {
196 let node_id = {
197 let mut guard = self.inner.borrow_mut();
198 let key = guard.arena.insert(TreeNode {
199 data: item,
200 parent: None,
201 children: Vec::new(),
202 });
203 let node_id = NodeId::from_key(key);
204 guard.roots.insert(index, node_id);
205 node_id
206 };
207 self.notify(TreeChange::NodeInserted {
208 parent: None,
209 index,
210 node: node_id,
211 });
212 node_id
213 }
214
215 pub fn insert_child(&self, parent: NodeId, index: usize, item: T) -> NodeId {
220 let node_id = {
221 let mut guard = self.inner.borrow_mut();
222 let key = guard.arena.insert(TreeNode {
223 data: item,
224 parent: Some(parent),
225 children: Vec::new(),
226 });
227 let node_id = NodeId::from_key(key);
228 guard.arena[parent.key()].children.insert(index, node_id);
229 node_id
230 };
231 self.notify(TreeChange::NodeInserted {
232 parent: Some(parent),
233 index,
234 node: node_id,
235 });
236 node_id
237 }
238
239 pub fn remove(&self, node: NodeId) {
244 let parent = {
245 let mut guard = self.inner.borrow_mut();
246 let parent = guard.arena[node.key()].parent;
247 if let Some(pid) = parent {
249 guard.arena[pid.key()].children.retain(|&c| c != node);
250 } else {
251 guard.roots.retain(|&r| r != node);
252 }
253 Self::remove_subtree(&mut guard.arena, node);
255 parent
256 };
257 self.notify(TreeChange::NodeRemoved { parent, node });
258 }
259
260 pub fn move_node(&self, node: NodeId, new_parent: NodeId, new_index: usize) {
266 let old_parent = {
267 let mut guard = self.inner.borrow_mut();
268 assert!(
270 !Self::is_descendant_of(&guard.arena, new_parent, node),
271 "cannot move a node into its own subtree"
272 );
273
274 let old_parent = guard.arena[node.key()].parent;
275
276 if let Some(pid) = old_parent {
278 guard.arena[pid.key()].children.retain(|&c| c != node);
279 } else {
280 guard.roots.retain(|&r| r != node);
281 }
282
283 guard.arena[node.key()].parent = Some(new_parent);
285 guard.arena[new_parent.key()]
286 .children
287 .insert(new_index, node);
288
289 old_parent
290 };
291 self.notify(TreeChange::NodeMoved {
292 node,
293 old_parent,
294 new_parent: Some(new_parent),
295 new_index,
296 });
297 }
298
299 pub fn move_to_root(&self, node: NodeId, new_index: usize) {
301 let old_parent = {
302 let mut guard = self.inner.borrow_mut();
303 let old_parent = guard.arena[node.key()].parent;
304
305 if let Some(pid) = old_parent {
307 guard.arena[pid.key()].children.retain(|&c| c != node);
308 } else {
309 guard.roots.retain(|&r| r != node);
310 }
311
312 guard.arena[node.key()].parent = None;
314 guard.roots.insert(new_index, node);
315
316 old_parent
317 };
318 self.notify(TreeChange::NodeMoved {
319 node,
320 old_parent,
321 new_parent: None,
322 new_index,
323 });
324 }
325
326 pub fn update(&self, node: NodeId, item: T) {
331 {
332 let mut guard = self.inner.borrow_mut();
333 guard.arena[node.key()].data = item;
334 }
335 self.notify(TreeChange::NodeUpdated { node });
336 }
337
338 pub fn observe_changes(&self, f: impl Fn(&TreeChange) + 'static) -> ObserverHandle {
343 let mut guard = self.inner.borrow_mut();
344 let id = guard.next_observer_id;
345 guard.next_observer_id += 1;
346 guard.observers.push(TreeObserverEntry {
347 id,
348 callback: Rc::new(f),
349 });
350 let inner = self.inner.clone();
351 ObserverHandle::new(
352 self.inner.clone(),
353 id,
354 Rc::new(move |observer_id| {
355 inner.borrow_mut().observers.retain(|e| e.id != observer_id);
356 }),
357 )
358 }
359
360 fn notify(&self, change: TreeChange) {
363 let callbacks: Vec<Rc<dyn Fn(&TreeChange)>> = self
364 .inner
365 .borrow()
366 .observers
367 .iter()
368 .map(|e| e.callback.clone())
369 .collect();
370 for cb in &callbacks {
371 cb(&change);
372 }
373 }
374
375 fn remove_subtree(arena: &mut SlotMap<slotmap::DefaultKey, TreeNode<T>>, node: NodeId) {
381 let mut stack = vec![node];
382 let mut to_remove = Vec::new();
383 while let Some(current) = stack.pop() {
384 if let Some(n) = arena.get(current.key()) {
385 stack.extend(n.children.iter().copied());
386 }
387 to_remove.push(current);
388 }
389 for id in to_remove {
390 arena.remove(id.key());
391 }
392 }
393
394 fn is_descendant_of(
395 arena: &SlotMap<slotmap::DefaultKey, TreeNode<T>>,
396 candidate: NodeId,
397 ancestor: NodeId,
398 ) -> bool {
399 let mut current = Some(candidate);
400 while let Some(nid) = current {
401 if nid == ancestor {
402 return true;
403 }
404 current = arena.get(nid.key()).and_then(|n| n.parent);
405 }
406 false
407 }
408}
409
410impl<T: std::fmt::Debug + 'static> TreeModel<T> {
411 pub fn debug_named(self, _name: impl Into<String>) -> Self {
419 #[cfg(debug_assertions)]
420 {
421 let weak = Rc::downgrade(&self.inner);
422 let adapter: Rc<dyn crate::debug_registry::ModelDebug> =
423 Rc::new(TreeModelDebug::<T> { weak });
424 let name = _name.into();
425 crate::debug_registry::register(name, Rc::downgrade(&adapter));
426 self.inner.borrow_mut().debug_adapter = Some(adapter);
427 }
428 self
429 }
430}
431
432#[cfg(debug_assertions)]
433struct TreeModelDebug<T> {
434 weak: std::rc::Weak<RefCell<TreeModelInner<T>>>,
435}
436
437#[cfg(debug_assertions)]
438impl<T: std::fmt::Debug + 'static> crate::debug_registry::ModelDebug for TreeModelDebug<T> {
439 fn kind(&self) -> &'static str {
440 "TreeModel"
441 }
442 fn len(&self) -> usize {
443 self.weak
444 .upgrade()
445 .map(|inner| inner.borrow().arena.len())
446 .unwrap_or(0)
447 }
448 fn debug_dump(&self, out: &mut dyn std::fmt::Write) {
449 let Some(inner) = self.weak.upgrade() else {
450 return;
451 };
452 let guard = inner.borrow();
453 let roots: Vec<NodeId> = guard.roots.clone();
455 for root in roots {
456 dump_subtree(&guard, root, 0, out);
457 }
458 }
459}
460
461#[cfg(debug_assertions)]
462fn dump_subtree<T: std::fmt::Debug>(
463 guard: &TreeModelInner<T>,
464 node: NodeId,
465 depth: usize,
466 out: &mut dyn std::fmt::Write,
467) {
468 let Some(n) = guard.arena.get(node.key()) else {
469 return;
470 };
471 let _ = writeln!(out, "{:indent$}{:?}", "", n.data, indent = depth * 2);
472 let children = n.children.clone();
473 for child in children {
474 dump_subtree(guard, child, depth + 1, out);
475 }
476}
477
478impl<T: 'static> Default for TreeModel<T> {
479 fn default() -> Self {
480 Self::new()
481 }
482}
483
484impl<T: 'static> Clone for TreeModel<T> {
485 fn clone(&self) -> Self {
486 Self {
487 inner: self.inner.clone(),
488 }
489 }
490}
491
492impl<T: std::fmt::Debug + 'static> std::fmt::Debug for TreeModel<T> {
493 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
494 let guard = self.inner.borrow();
495 f.debug_struct("TreeModel")
496 .field("root_count", &guard.roots.len())
497 .field("total_nodes", &guard.arena.len())
498 .finish()
499 }
500}
501
502#[cfg(test)]
503mod tests {
504 use std::cell::Cell;
505
506 use super::*;
507
508 fn sample_tree() -> (TreeModel<&'static str>, NodeId, NodeId, NodeId, NodeId) {
509 let tree = TreeModel::new();
510 let a = tree.insert_root(0, "A");
511 let b = tree.insert_root(1, "B");
512 let a1 = tree.insert_child(a, 0, "A1");
513 let a2 = tree.insert_child(a, 1, "A2");
514 (tree, a, b, a1, a2)
515 }
516
517 #[test]
518 fn empty_tree() {
519 let tree: TreeModel<i32> = TreeModel::new();
520 assert_eq!(tree.root_count(), 0);
521 }
522
523 #[test]
524 fn insert_roots() {
525 let tree = TreeModel::new();
526 let a = tree.insert_root(0, "A");
527 let b = tree.insert_root(1, "B");
528 assert_eq!(tree.root_count(), 2);
529 assert_eq!(tree.root(0), a);
530 assert_eq!(tree.root(1), b);
531 }
532
533 #[test]
534 fn insert_children() {
535 let (tree, a, _, a1, a2) = sample_tree();
536 assert_eq!(tree.child_count(a), 2);
537 assert_eq!(tree.child(a, 0), a1);
538 assert_eq!(tree.child(a, 1), a2);
539 }
540
541 #[test]
542 fn parent_and_depth() {
543 let (tree, a, _, a1, _) = sample_tree();
544 assert_eq!(tree.parent(a), None);
545 assert_eq!(tree.parent(a1), Some(a));
546 assert_eq!(tree.depth(a), 0);
547 assert_eq!(tree.depth(a1), 1);
548 }
549
550 #[test]
551 fn has_children_query() {
552 let (tree, a, b, _, _) = sample_tree();
553 assert!(tree.has_children(a));
554 assert!(!tree.has_children(b));
555 }
556
557 #[test]
558 fn with_item() {
559 let (tree, a, _, _, _) = sample_tree();
560 assert_eq!(tree.with_item(a, |v| *v), Some("A"));
561 }
562
563 #[test]
564 fn find_by() {
565 let (tree, _, _, a1, _) = sample_tree();
566 let found = tree.find_by(|v| *v == "A1");
567 assert_eq!(found, Some(a1));
568
569 let not_found = tree.find_by(|v| *v == "Z");
570 assert_eq!(not_found, None);
571 }
572
573 #[test]
574 fn insert_root_emits_change() {
575 let tree = TreeModel::new();
576 let changes: Rc<RefCell<Vec<TreeChange>>> = Rc::new(RefCell::new(Vec::new()));
577 let c = changes.clone();
578 let _handle = tree.observe_changes(move |change| {
579 c.borrow_mut().push(change.clone());
580 });
581
582 let a = tree.insert_root(0, "A");
583 let log = changes.borrow();
584 assert_eq!(
585 log[0],
586 TreeChange::NodeInserted {
587 parent: None,
588 index: 0,
589 node: a
590 }
591 );
592 }
593
594 #[test]
595 fn insert_child_emits_change() {
596 let tree = TreeModel::new();
597 let a = tree.insert_root(0, "A");
598
599 let changes: Rc<RefCell<Vec<TreeChange>>> = Rc::new(RefCell::new(Vec::new()));
600 let c = changes.clone();
601 let _handle = tree.observe_changes(move |change| {
602 c.borrow_mut().push(change.clone());
603 });
604
605 let a1 = tree.insert_child(a, 0, "A1");
606 let log = changes.borrow();
607 assert_eq!(log.len(), 1, "insert_child should emit exactly one change");
608 assert_eq!(
609 log[0],
610 TreeChange::NodeInserted {
611 parent: Some(a),
612 index: 0,
613 node: a1
614 }
615 );
616 }
617
618 #[test]
619 fn remove_emits_change() {
620 let (tree, a, _, a1, _) = sample_tree();
621 let changes: Rc<RefCell<Vec<TreeChange>>> = Rc::new(RefCell::new(Vec::new()));
622 let c = changes.clone();
623 let _handle = tree.observe_changes(move |change| {
624 c.borrow_mut().push(change.clone());
625 });
626
627 tree.remove(a1);
628 assert_eq!(tree.child_count(a), 1);
629 let log = changes.borrow();
630 assert_eq!(log.len(), 1, "remove should emit exactly one change");
631 assert_eq!(
632 log[0],
633 TreeChange::NodeRemoved {
634 parent: Some(a),
635 node: a1
636 }
637 );
638 }
639
640 #[test]
641 fn remove_subtree() {
642 let tree = TreeModel::new();
643 let a = tree.insert_root(0, "A");
644 let a1 = tree.insert_child(a, 0, "A1");
645 let a1a = tree.insert_child(a1, 0, "A1a");
646
647 tree.remove(a1);
648 assert_eq!(tree.child_count(a), 0);
649 assert_eq!(tree.with_item(a1, |_| ()), None, "a1 should be removed");
651 assert_eq!(
652 tree.with_item(a1a, |_| ()),
653 None,
654 "a1a (grandchild) should also be removed"
655 );
656 }
657
658 #[test]
659 fn remove_root() {
660 let (tree, a, b, _, _) = sample_tree();
661 tree.remove(a);
662 assert_eq!(tree.root_count(), 1);
663 assert_eq!(tree.root(0), b);
664 }
665
666 #[test]
667 fn move_node() {
668 let (tree, a, b, a1, _) = sample_tree();
669 let changes: Rc<RefCell<Vec<TreeChange>>> = Rc::new(RefCell::new(Vec::new()));
670 let c = changes.clone();
671 let _handle = tree.observe_changes(move |change| {
672 c.borrow_mut().push(change.clone());
673 });
674
675 tree.move_node(a1, b, 0);
676
677 assert_eq!(tree.child_count(a), 1); assert_eq!(tree.child_count(b), 1); assert_eq!(tree.child(b, 0), a1);
680 assert_eq!(tree.parent(a1), Some(b));
681
682 let log = changes.borrow();
683 assert_eq!(
684 log[0],
685 TreeChange::NodeMoved {
686 node: a1,
687 old_parent: Some(a),
688 new_parent: Some(b),
689 new_index: 0,
690 }
691 );
692 }
693
694 #[test]
695 fn move_to_root() {
696 let (tree, a, _, a1, _) = sample_tree();
697 tree.move_to_root(a1, 0);
698
699 assert_eq!(tree.root_count(), 3); assert_eq!(tree.root(0), a1);
701 assert_eq!(tree.parent(a1), None);
702 assert_eq!(tree.child_count(a), 1); }
704
705 #[test]
706 #[should_panic(expected = "cannot move a node into its own subtree")]
707 fn move_into_own_subtree_panics() {
708 let (tree, a, _, a1, _) = sample_tree();
709 tree.move_node(a, a1, 0); }
711
712 #[test]
713 fn update_emits_change() {
714 let (tree, a, _, _, _) = sample_tree();
715 let changes: Rc<RefCell<Vec<TreeChange>>> = Rc::new(RefCell::new(Vec::new()));
716 let c = changes.clone();
717 let _handle = tree.observe_changes(move |change| {
718 c.borrow_mut().push(change.clone());
719 });
720
721 tree.update(a, "A-updated");
722 assert_eq!(tree.with_item(a, |v| *v), Some("A-updated"));
723 let log = changes.borrow();
724 assert_eq!(log[0], TreeChange::NodeUpdated { node: a });
725 }
726
727 #[test]
728 fn observer_removed_on_handle_drop() {
729 let tree = TreeModel::new();
730 let count = Rc::new(Cell::new(0));
731 let c = count.clone();
732 let handle = tree.observe_changes(move |_| c.set(c.get() + 1));
733
734 tree.insert_root(0, "A");
735 assert_eq!(count.get(), 1);
736
737 drop(handle);
738 tree.insert_root(1, "B");
739 assert_eq!(count.get(), 1); }
741
742 #[test]
743 fn clone_shares_data() {
744 let tree = TreeModel::new();
745 let a = tree.insert_root(0, "A");
746
747 let clone = tree.clone();
748 assert_eq!(clone.root_count(), 1);
749 assert_eq!(clone.with_item(a, |v| *v), Some("A"));
750
751 clone.insert_root(1, "B");
752 assert_eq!(tree.root_count(), 2);
753 }
754
755 #[test]
756 fn deep_tree_depth() {
757 let tree = TreeModel::new();
758 let r = tree.insert_root(0, "r");
759 let c1 = tree.insert_child(r, 0, "c1");
760 let c2 = tree.insert_child(c1, 0, "c2");
761 let c3 = tree.insert_child(c2, 0, "c3");
762 assert_eq!(tree.depth(r), 0);
763 assert_eq!(tree.depth(c1), 1);
764 assert_eq!(tree.depth(c2), 2);
765 assert_eq!(tree.depth(c3), 3);
766 }
767
768 #[test]
769 fn children_returns_correct_ids() {
770 let (tree, a, _, a1, a2) = sample_tree();
771 let children = tree.children(a);
772 assert_eq!(children, vec![a1, a2]);
773 }
774
775 #[test]
779 fn remove_deep_chain_does_not_overflow() {
780 const DEPTH: usize = 50_000;
781 let tree = TreeModel::new();
782 let root = tree.insert_root(0, 0usize);
783 let mut leaf = root;
784 for i in 1..DEPTH {
785 leaf = tree.insert_child(leaf, 0, i);
786 }
787 tree.remove(root);
788 assert_eq!(tree.root_count(), 0);
789 assert_eq!(tree.with_item(leaf, |_| ()), None);
790 }
791}