dsa_rust/hierarchies/
safe_linked_gentree.rs

1/*! A safe, linked, n-ary tree implementation
2
3# About
4Following classical DSA curricula, this implementation relies on pointers for the structure's composition and navigation. This module explores the use of reference counting and interior mutability through the [Rc] and [RefCell] types (respectively) for a safe, positional implementation that avoids dangling pointers and reference cycles for proper [Drop] semantics.
5
6Reference counting provides a synchronous, deterministic form of memory management that acts like a garbage collector and prevents dangling pointers by automatically managing lifetimes. The structure is able to keep objects alive until their reference count hits zero, potentially even after they've gone out of their original scope. To avoid memory leaks caused by reference cycles, tree nodes use strong `Rc` pointers for children and [Weak] pointers for parent links. This ensures the tree can be correctly dropped recursively from the top down.
7
8Using smart pointers to manage reference counting and interior mutability to skirt multiple mutable references is an elegant solution to the linked desgin, but its still a bit painful, and potentially overkill for many applications. The good news is that there are much easier ways to accomplish similar goals. To wit, this library also includes a `Vec`-backed tree structure with a similar API. For more polished levels of functionality with the same arena-style backing structure concepts see [id_tree](https://docs.rs/id_tree/latest/id_tree/). It is worth noting that `id_tree` uses a hash map to store node IDs, so it may not be as performanat as either a pointer-backed or simple indexed tree structure for smaller, short-lived tree structures.
9
10# Design
11The base [GenTree] structure is sparse and only contains basic operations for constructors and metadata retrieval. Most of the magic happens in the [CursorMut] struct. Both structs rely on a [Position] struct which provides a safe handle to all the reference-counted pointers required to make tree go brrr.
12
13# Example
14This section presents an algorithm that builds a tree from a `Vec` of custom `Heading` objects that contain a level and a heading value. Assume the inputs to the algorithm start at level 1 with the first (and lowest) level in the `Vec<Heading>` list being 2. The result is a single, empty root node represented by `[]`.
15```text
16    []
17    │
18    ├── Landlocked
19    │   ├── Switzerland
20    │   │   └── Geneva
21    │   │       └── Old Town
22    │   │           └── Cathédrale Saint-Pierre
23    │   └── Bolivia
24    │       └── []
25    │           └── []
26    │               ├── Puerta del Sol
27    │               └── Puerta de la Luna
28    └── Islands
29        ├── Marine
30        │   └── Australia
31        └── Fresh Water
32```
33```rust
34    use dsa_rust::hierarchies::safe_linked_gentree::GenTree;
35
36    struct Heading {
37        level: usize,
38        title: String,
39    }
40    impl Heading {
41        fn new(title: String, level: usize) -> Heading {
42            Heading { level, title }
43        }
44    }
45
46    pub fn construct(mut cur_level: usize, data: Vec<Heading>) -> GenTree<Heading> {
47        // Instantiates a Tree with a generic root and traversal positioning
48        let mut tree: GenTree<Heading> = GenTree::<Heading>::new();
49        let mut cursor = tree.cursor_mut(); // Sets cursor to tree.root
50
51        // Constructs tree from Vec<T>
52        for heading in data {
53            let data_level = heading.level;
54
55            // Case 1: Adds a child to the current parent and sets level cursor
56            if data_level == cur_level + 1 {
57                cursor.add_child(heading);
58                cur_level += 1;
59            }
60            // Case 2: Adds a child with multi-generational skips
61            else if data_level > cur_level {
62                let diff = data_level - cur_level;
63                for _ in 1..diff {
64                    let empty = Heading::new("[]".to_string(), 0);
65                    cursor.add_child(empty);
66                    cur_level += 1;
67                }
68                cursor.add_child(heading);
69                cur_level += 1;
70            }
71            // Case 3: Adds sibling to current parent
72            else if data_level == cur_level {
73                cursor.ascend().ok();
74                cursor.add_child(heading);
75            }
76            // Case 4: Adds a child to the appropriate ancestor,
77            // ensuring proper generational skips
78            else {
79                let diff = cur_level - data_level;
80                for _ in 0..=diff {
81                    cursor.ascend().ok();
82                    cur_level -= 1;
83                }
84                cursor.add_child(heading);
85                cur_level += 1;
86            }
87        }
88        tree
89    }
90
91```
92
93*/
94
95use std::cell::{Ref, RefCell};
96use std::rc::{Rc, Weak};
97//use std::marker::PhantomData;
98
99/// The `Position` struct provides a safe, lightweight handle to `Node` data.
100/// All meaningful accessors and mutators appear on the [CursorMut] struct.
101// Position only contains private members, but must be public due to its
102// presence as a CursorMut return type.
103pub struct Position<T> {
104    ptr: Option<Rc<RefCell<Node<T>>>>,
105}
106impl<T> Position<T> {
107    /// Creates a handle to Node and returns it as a Position.
108    fn new(ptr: Node<T>) -> Self {
109        Position {
110            ptr: Some(Rc::new(RefCell::new(ptr))),
111        }
112    }
113
114    /// Returns an reference to the data at the Position, if Some.
115    fn get_data(&self) -> Option<Ref<'_, T>> {
116        let node_ref: Ref<Node<T>> = self.ptr.as_ref()?.borrow();
117        Ref::filter_map(node_ref, |node| node.data.as_ref()).ok()
118        //if let Some(val) = self.ptr.as_ref() {
119        //    Some((*(*val)).borrow())
120        //} else { None }
121    }
122
123    /// Returns the Node from a Position, if Some.
124    //fn get_node(&self) -> Ref<Node<T>> {
125    //    self.ptr.as_ref().unwrap().borrow()
126    //}
127    fn get_node(&self) -> Option<Ref<'_, Node<T>>> {
128        self.ptr.as_ref().map(|rc| rc.borrow())
129    }
130
131    /// Returns the Position for the current Position's parent, if Some.
132    //fn get_parent_pos(&self) -> Option<Position<T>> {
133    //    if let Some(parent) = self.ptr.as_ref().unwrap().borrow().parent.clone() {
134    //        Some(parent)
135    //    } else { None }
136    //}
137    fn get_parent_pos(&self) -> Option<Position<T>> {
138        if let Some(weak_parent) = &self.ptr.as_ref()?.borrow().parent {
139            weak_parent.upgrade().map(|rc| Position { ptr: Some(rc) })
140        } else {
141            None
142        }
143    }
144}
145// "Shallow" clone only clones/increases the Rc, not the whole Node
146impl<T> Clone for Position<T> {
147    fn clone(&self) -> Self {
148        Position {
149            ptr: self.ptr.clone(),
150        }
151    }
152}
153impl<T> PartialEq for Position<T> {
154    fn eq(&self, other: &Self) -> bool {
155        match (&self.ptr, &other.ptr) {
156            (Some(a), Some(b)) => Rc::ptr_eq(a, b),
157            (None, None) => true,
158            _ => false,
159        }
160    }
161}
162impl<T> std::fmt::Debug for Position<T> {
163    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
164        match &self.ptr {
165            Some(rc) => write!(f, "Position({:p})", Rc::as_ptr(rc)),
166            None => write!(f, "Position(None)"),
167        }
168    }
169}
170
171/// Internal-only struct that represents the heart of the general tree. The `Node`
172/// struct contains strong pointers to children, but weak pointers to parent nodes
173/// for proper drop semantics to avoid reference cycles.
174struct Node<T> {
175    parent: Option<Weak<RefCell<Node<T>>>>,
176    children: Vec<Position<T>>,
177    data: Option<T>,
178}
179impl<T> Node<T> {
180    /// Builds a new Node and returns its position.
181    fn root(data: Option<T>) -> Node<T> {
182        Node {
183            parent: None,
184            children: Vec::new(),
185            data,
186        }
187    }
188
189    /// Creates a new `Node` with given data for the given `Position`.
190    fn new(parent: &Position<T>, data: T) -> Node<T> {
191        Node {
192            //parent: Some(parent.clone()),
193            parent: Some(Rc::downgrade(parent.ptr.as_ref().unwrap())),
194            children: Vec::new(),
195            data: Some(data),
196        }
197    }
198}
199
200/// The `GenTree` struct represents a positional, linked-based general
201/// tree structure that contains a pointer to the root node and the structure's size.
202/// The genericity of the struct means you'll have to explicitly type the
203/// tree at instantiation.
204///
205/// Most of the major accessors and mutators appear on the [CursorMut] struct.
206///
207/// Example:
208/// ```example
209///     // Creates a tree over Heading objects
210///     let mut tree: GenTree<Heading> = GenTree::<Heading>::new();
211///
212///     // Creates a CursorMut to navigate/mutate the tree,
213///     // starting at the root node
214///     let mut cursor = tree.cursor_mut();
215/// ```
216#[derive(Debug)]
217pub struct GenTree<T> {
218    root: Position<T>,
219    size: usize,
220}
221impl<T> Default for GenTree<T> {
222    fn default() -> Self {
223        Self::new()
224    }
225}
226impl<T> GenTree<T> {
227    /// Instantiates a new `GenTree`.
228    pub fn new() -> GenTree<T> {
229        let root: Position<T> = Position::new(Node::root(None));
230        GenTree { root, size: 0 }
231    }
232
233    /// Returns the `Position` of the tree's root.
234    pub fn root(&self) -> Position<T> {
235        self.root.clone()
236    }
237
238    /// Creates a `CursorMut` starting at the tree's root.
239    pub fn cursor_mut(&mut self) -> CursorMut<'_, T> {
240        CursorMut {
241            node: self.root.clone(),
242            tree: self,
243        }
244    }
245
246    /// Creates a `CursorMut` from a given `Position`.
247    pub fn cursor_from(&mut self, position: Position<T>) -> CursorMut<'_, T> {
248        CursorMut {
249            node: position,
250            tree: self,
251        }
252    }
253}
254
255/** A cursor over mutable `Node` data with safe, reference-counted `Position` handles.
256
257This struct represents the majority of major operations for the [GenTree] structure.
258All operations run in `O(1)` time unless otherwise noted. */
259pub struct CursorMut<'a, T> {
260    node: Position<T>,
261    tree: &'a mut GenTree<T>,
262}
263impl<'a, T> CursorMut<'a, T> {
264    // METADATA
265    ///////////
266
267    /** Returns `true` if the `Node` under the curosr is the tree's root */
268    pub fn is_root(&self) -> bool {
269        self.node.clone() == self.tree.root()
270    }
271
272    /** Returns `true` if the `Node` under the curosr has data */
273    pub fn is_some(&self) -> bool {
274        let val = self.node.get_data();
275        val.is_some()
276    }
277
278    /** Returns `true` if the `Node` under the cursor is empty */
279    pub fn is_none(&self) -> bool {
280        let val = self.node.get_data();
281        val.is_none()
282    }
283
284    /** Returns the number of children for the `Node` under the cursor as usize */
285    pub fn num_children(&self) -> usize {
286        if let Some(val) = self.node.ptr.clone() {
287            (*val).borrow().children.len()
288        } else {
289            0
290        }
291    }
292
293    /** Returns the depth of the cursor from the tree's root */
294    //pub fn depth(&mut self) -> usize {
295    //    let mut depth = 0;
296    //    let current = self.current().clone();
297    //    while !self.is_root() {
298    //        self.ascend().ok();
299    //        depth += 1;
300    //    }
301    //    self.jump(&current);
302    //    depth
303    //}
304    pub fn depth(&self) -> usize {
305        let mut depth = 0;
306        let mut current_ptr = self.node.clone().ptr;
307        //while let Some(pos) = current.ptr {
308        while let Some(pos) = current_ptr {
309            let node_ref = pos.borrow();
310            if let Some(parent_weak) = &node_ref.parent {
311                //current = Position { ptr: parent_weak.upgrade() };
312                current_ptr = parent_weak.upgrade();
313                depth += 1;
314            } else {
315                break;
316            }
317        }
318        depth
319    }
320
321    /** Returns the height of the tallest sub-tree for the current position */
322    //pub fn height(&self) -> usize {
323    //    let current = self.current();
324    //    self.height_rec(current.clone())
325    //}
326    ///** The recursive guts of the height function */
327    //#[allow(clippy::only_used_in_recursion)]
328    //fn height_rec(&self, node: Position<T>) -> usize {
329    //    let mut h = 0;
330    //    if let Some(n) = node.ptr.clone() {
331    //        for e in &(*n).borrow().children {
332    //            h = std::cmp::max(h, self.height_rec(e.clone()))
333    //        }
334    //    }
335    //    h + 1
336    //}
337    pub fn height(&self) -> usize {
338        let current = self.current();
339        fn height_rec<T>(node: &Position<T>) -> usize {
340            let mut h = 0;
341            if let Some(n) = node.ptr.clone() {
342                for e in &(*n).borrow().children {
343                    h = std::cmp::max(h, height_rec(&e.clone()))
344                }
345            }
346            h + 1
347        }
348        height_rec(current)
349    }
350
351    // ACCESSORS AND MUTATORS
352    /////////////////////////
353
354    /** Returns an _immutable_ reference to the data under the cursor, if `Some` */
355    pub fn get_data(&self) -> Option<Ref<'_, T>> {
356        let node_ref: Ref<Node<T>> = self.node.get_node()?;
357        Ref::filter_map(node_ref, |node| node.data.as_ref()).ok()
358    }
359
360    /** Returns an _immutable_ reference to the data for a supplied `Position` */
361    pub fn get_for_pos(&'a self, pos: &'a Position<T>) -> Option<Ref<'a, T>> {
362        let node_ref: Ref<Node<T>> = pos.get_node()?;
363        Ref::filter_map(node_ref, |node| node.data.as_ref()).ok()
364    }
365
366    // /** Overwrites the data for the current Node without affecting its position,
367    // returns the old data, if Some */
368    //pub fn set(&mut self, data: T) -> Option<T> {
369    //    if let Ok(n) = self.node.as_ptr() {
370    //        unsafe {
371    //            let old = (*n).data.take();
372    //            (*n).data = Some(data);
373    //            return old;
374    //        }
375    //    } else {
376    //        None
377    //    }
378    //}
379
380    /** Adds a new child `Node` under the current cursor and advances the cursor
381    to the new child */
382    pub fn add_child(&mut self, data: T) {
383        let parent = self.node.clone();
384
385        // Create the new child node and give it a Position
386        let new_node = Node::new(&parent, data);
387        let new_pos = Position::new(new_node);
388
389        // Add the new child to the parent's child list
390        let kids = parent.ptr.unwrap();
391        (*kids).borrow_mut().children.push(new_pos.clone());
392
393        // Mutates self to be the Position of the new node
394        self.node = new_pos;
395
396        // Increment the size of the tree
397        self.tree.size += 1;
398    }
399
400    /** Returns a list of owned descendant (child) `Position`s for the `Node`
401    under the cursor in `O(c)` time where `c` is the number of children; The
402    clone used here is a cheap pointer copy, not an underlying data copy */
403    //pub fn children(&self) -> Vec<Position<T>> {
404    //    self.node
405    //        .get_node()
406    //        .unwrap()
407    //        .children
408    //        .iter()
409    //        .cloned()
410    //        .collect::<Vec<_>>()
411    //}
412    // Allocates a new Vec and clones Positions in O(n) time
413    pub fn children(&self) -> Vec<Position<T>> {
414        self.node
415            .get_node()
416            //.map(|node| node.children.iter().cloned().collect())
417            .map(|node| node.children.to_vec())
418            .unwrap_or_default()
419    }
420
421    /// Warning: Broken! Does not handle root deletion properly.
422    ///
423    /// Removes the node at the current cursor position and returns its data,
424    /// if Some. Operation executes in `O(c)` time where `c` is the number of
425    /// children for the given node; Adds all children to the parent
426    /// (if `Some`), and returns the deleted `Node`; If the cursor is at the tree's
427    /// root, this just deletes the `Node`'s data, leaving `None`; Moves the cursor
428    /// to the parent, if `Some` */
429    /// TODO: Unsound; need to remove reference from parent too
430    //pub fn delete(&mut self) -> Option<T> {
431    //    let self_pos = self.node.clone();
432    //    let self_rc = self_pos.ptr.clone()?;
433    //
434    //    // Check and get parent
435    //    let parent_pos = self_rc.borrow().parent.as_ref()?.upgrade()?;
436    //    let parent_pos = Position {
437    //        ptr: Some(parent_pos),
438    //    };
439    //    let parent_rc = parent_pos.ptr.clone().unwrap();
440    //
441    //    // 1. Remove self from parent.children
442    //    {
443    //        let mut parent_node = parent_rc.borrow_mut();
444    //        if let Some(index) = parent_node.children.iter().position(|c| *c == self.node) {
445    //            parent_node.children.remove(index);
446    //        }
447    //    }
448    //
449    //    // 2. Take self's children (detach them)
450    //    let mut self_children = {
451    //        let mut self_node = self_rc.borrow_mut();
452    //        std::mem::take(&mut self_node.children)
453    //    };
454    //
455    //    // 3. Reparent each child and move them to parent's children
456    //    {
457    //        let mut parent_node = parent_rc.borrow_mut();
458    //        for child in &mut self_children {
459    //            if let Some(child_rc) = child.ptr.clone() {
460    //                child_rc.borrow_mut().parent = Some(Rc::downgrade(&parent_rc));
461    //            }
462    //            parent_node.children.push(child.clone());
463    //        }
464    //    }
465    //
466    //    // 4. Move cursor to parent
467    //    self.jump(&parent_pos);
468    //
469    //    // 5. Take and return data from the deleted node
470    //    let mut self_node = self_rc.borrow_mut();
471    //    self_node.data.take()
472    //}
473    pub fn delete(&mut self) -> Option<T> {
474        let self_pos = self.node.clone();
475        let self_rc = self_pos.ptr.clone()?;
476
477        // Check if we have a parent. If not, we are deleting the root!
478        let parent_maybe = self_rc
479            .borrow()
480            .parent
481            .as_ref()
482            .and_then(|weak| weak.upgrade());
483
484        let old_data = {
485            let mut self_node = self_rc.borrow_mut();
486            self_node.data.take()
487        };
488
489        if let Some(parent_rc) = parent_maybe {
490            let parent_pos = Position {
491                ptr: Some(parent_rc.clone()),
492            };
493
494            // 1. Remove self from parent.children by checking pointer address identity
495            {
496                let mut parent_node = parent_rc.borrow_mut();
497
498                // Extract our underlying Rc pointer to compare against
499                if let Some(self_inner_rc) = &self.node.ptr {
500                    if let Some(index) = parent_node.children.iter().position(|c| {
501                        if let Some(child_inner_rc) = &c.ptr {
502                            // Check if they point to the exact same memory allocation
503                            Rc::ptr_eq(child_inner_rc, self_inner_rc)
504                        } else {
505                            false
506                        }
507                    }) {
508                        parent_node.children.remove(index);
509                    }
510                }
511            }
512
513            // 2. Take self's children (detach them)
514            let mut self_children = {
515                let mut self_node = self_rc.borrow_mut();
516                std::mem::take(&mut self_node.children)
517            };
518
519            // 3. Reparent each child and move them to parent's children
520            {
521                let mut parent_node = parent_rc.borrow_mut();
522                for child in &mut self_children {
523                    if let Some(child_rc) = child.ptr.clone() {
524                        child_rc.borrow_mut().parent = Some(Rc::downgrade(&parent_rc));
525                    }
526                    parent_node.children.push(child.clone());
527                }
528            }
529
530            // 4. Move cursor to parent
531            self.jump(&parent_pos);
532        } else {
533            // Root deletion handling: If you delete the root, you decide where the cursor goes.
534            // For example, making the tree entirely None, or making a child the new root.
535            self.node = Position { ptr: None };
536        }
537
538        // 5. Explicitly decrement the size track!
539        self.tree.size -= 1;
540
541        old_data
542    }
543
544    // NAVIGATION
545    /////////////
546
547    /** Returns a reference to the current `Position` */
548    pub fn current(&self) -> &Position<T> {
549        &self.node
550    }
551
552    /** Jump the cursor to the given `Position` */
553    pub fn jump(&mut self, new: &Position<T>) {
554        self.node = (*new).clone();
555    }
556
557    /** Moves the cursor up a generation, if `Some`; Trying to ascend past the root results in an error */
558    pub fn ascend(&mut self) -> Result<(), String> {
559        if let Some(parent) = self.node.get_parent_pos() {
560            self.node = parent;
561            Ok(())
562        } else {
563            Err("Error: Cannot ascend past root".to_string())
564        }
565    }
566}
567
568#[cfg(test)]
569mod tests {
570
571    // Both basic and dangle tests use the tree builder
572    use super::{GenTree, Position};
573    use crate::hierarchies::safe_linked_gentree_builder::{construct, Heading};
574
575    #[test]
576    /** Creates this tree to test properties
577        []
578        ├── Landlocked
579        │   ├── Switzerland
580        │   │   └── Geneva
581        │   │       └── Old Town
582        │   │           └── Cathédrale Saint-Pierre
583        │   └── Bolivia
584        │       └── []
585        │           └── []
586        │               ├── Puerta del Sol
587        │               └── Puerta de la Luna
588        └── Islands
589            ├── Marine
590            │   └── Australia
591            └── Fresh Water
592    */
593    fn basic() {
594        let tree_vec = vec![
595            Heading {
596                level: 2,
597                title: "Landlocked".to_string(),
598            },
599            Heading {
600                level: 3,
601                title: "Switzerland".to_string(),
602            },
603            Heading {
604                level: 4,
605                title: "Geneva".to_string(),
606            },
607            Heading {
608                level: 5,
609                title: "Old Town".to_string(),
610            },
611            Heading {
612                level: 6,
613                title: "Cathédrale Saint-Pierre".to_string(),
614            },
615            Heading {
616                level: 3,
617                title: "Bolivia".to_string(),
618            },
619            Heading {
620                level: 6,
621                title: "Puerta del Sol".to_string(),
622            },
623            Heading {
624                level: 6,
625                title: "Puerta de la Luna".to_string(),
626            },
627            Heading {
628                level: 2,
629                title: "Islands".to_string(),
630            },
631            Heading {
632                level: 3,
633                title: "Marine".to_string(),
634            },
635            Heading {
636                level: 4,
637                title: "Australia".to_string(),
638            },
639            Heading {
640                level: 3,
641                title: "Fresh Water".to_string(),
642            },
643        ];
644
645        // Constructs tree ignoring the first heading
646        let mut tree: GenTree<Heading> = construct(1, tree_vec);
647
648        assert!(tree.root.get_parent_pos().is_none());
649        assert!(tree.root().ptr.is_some());
650        let p = tree.root();
651        let _ = p.get_data();
652
653        // Tests root() -> Position<T>
654        // By identity (using custom PartialEq ipml)
655        assert!(tree.cursor_mut().node == tree.root);
656        // By assert_eq!'s default Debug route
657        let cursor = tree.cursor_mut();
658        assert_eq!(cursor.node, tree.root());
659
660        let mut cursor = tree.cursor_mut();
661        // Tests that root is empty with is_some() and is_none()
662        assert!(!cursor.is_some());
663        assert!(cursor.is_none());
664        // tests height and depth
665        assert_eq!(cursor.depth(), 0);
666        assert_eq!(cursor.height(), 6);
667
668        // Tests num_children()
669        assert_eq!(cursor.num_children(), 2); // Root has [Landlocked, Islands]
670
671        // Tests children(), jump(), and get_data()
672        let kids = cursor.children();
673        let mut kids_iter = kids.iter();
674
675        // Moves to first child "Landlocked"
676        cursor.jump(kids_iter.next().unwrap());
677        {
678            let data = cursor.get_data().unwrap();
679            assert_eq!(*data.title, "Landlocked".to_string());
680        }
681        assert_eq!(cursor.depth(), 1);
682        assert_eq!(cursor.height(), 5);
683
684        // Moves to second child "Islands"
685        cursor.jump(kids_iter.next().unwrap());
686        let curr: Position<Heading> = cursor.current().clone(); // Passes the torch
687        {
688            let data = cursor.get_data().unwrap();
689            assert_eq!(*data.title, "Islands".to_string());
690        }
691        assert_eq!(cursor.depth(), 1);
692        assert_eq!(cursor.height(), 3);
693
694        // Jumps down a generation to [Marine, Fresh Water]
695        cursor.jump(&curr);
696        {
697            let new_kids = cursor.children();
698            let mut kids_iter = new_kids.iter();
699            cursor.jump(kids_iter.next().unwrap()); // Moves to first child
700            let data = cursor.get_data().unwrap();
701            assert_eq!(*data.title, "Marine".to_string());
702        }
703        // tests height and depth
704        assert_eq!(cursor.depth(), 2);
705        assert_eq!(cursor.height(), 2);
706
707        // Jumps down a generation, for fun
708        let new_kids = cursor.children(); // Gets cursor's chidlren
709        let mut kids_iter = new_kids.iter(); // Creates an iterator
710        cursor.jump(kids_iter.next().unwrap()); // Moves to first child
711        {
712            let data = cursor.get_data().unwrap();
713            assert_eq!(*data.title, "Australia".to_string());
714        }
715        assert_eq!(cursor.depth(), 3);
716        assert_eq!(cursor.height(), 1);
717
718        // Tests ascend()
719        assert!(cursor.ascend().is_ok()); // Marine
720        assert!(cursor.ascend().is_ok()); // Islands
721        {
722            let data = cursor.get_data().unwrap();
723            assert_eq!(*data.title, "Islands".to_string());
724        }
725        assert!(cursor.ascend().is_ok()); // []
726        assert!(cursor.ascend().is_err()); // Cannot ascend() past root
727        assert!(cursor.is_root()); // Double checks, just in case
728        assert_eq!(cursor.depth(), 0);
729        assert_eq!(cursor.height(), 6);
730
731        // Descends to Islands to test delete()
732        let kids = cursor.children(); // Gets cursor's chidlren
733        let mut kids_iter = kids.iter(); // Creates an iterator
734        cursor.jump(kids_iter.next().unwrap()); // Moves to Landlocked
735        cursor.jump(kids_iter.next().unwrap()); // Moves to Islands
736        {
737            let data = cursor.get_data().unwrap();
738            assert_eq!(*data.title, "Islands".to_string());
739        }
740
741        // Tests delete()
742        // Creates placeholder Heading
743        let mut deleted = Heading {
744            title: String::new(),
745            level: 0,
746        };
747        // Iterates through the child position's under the cursor
748        // looking for a matching Heading; Once found, jumps to that position,
749        // and deletes the Heading; The delete() operation automatically jumps
750        // the cursor to the parent of the deleted position
751        for position in cursor.children().iter() {
752            if position.get_data().unwrap().title == "Marine" {
753                cursor.jump(position);
754                deleted = cursor.delete().unwrap();
755            }
756        }
757        // Tests that the correct Heading was deleted
758        assert_eq!(deleted.level, 3);
759        assert_eq!(deleted.title, "Marine".to_string());
760
761        // Tests that the cursor got bumped up to Islands
762        let data = cursor.get_data().unwrap();
763        assert_eq!(data.title, "Islands".to_string());
764
765        // Tests that the Islands node has the correct children
766        let mut kids = Vec::new();
767        assert_eq!(cursor.children().len(), 2);
768        for child in cursor.children().iter() {
769            let title = child.get_data().unwrap().title.clone();
770            kids.push(title)
771        }
772        assert_eq!(kids, ["Fresh Water".to_string(), "Australia".to_string()]);
773    }
774
775    #[test]
776    fn dangle() {
777        use super::{GenTree, Position};
778        let one = vec![
779            Heading {
780                level: 1,
781                title: "Landlocked".to_string(),
782            },
783            Heading {
784                level: 2,
785                title: "Switzerland".to_string(),
786            },
787        ];
788        let two = vec![
789            Heading {
790                level: 1,
791                title: "Bolivia".to_string(),
792            },
793            Heading {
794                level: 2,
795                title: "Zimbabwe".to_string(),
796            },
797        ];
798
799        // Creates a tree, Position, and CursorMut
800        let mut outer_tree: GenTree<Heading> = construct(0, one.clone());
801        let mut _pos: Position<Heading> = outer_tree.root();
802        let mut cursor = outer_tree.cursor_mut();
803
804        {
805            let inner_tree: GenTree<Heading> = construct(0, two.clone());
806            _pos = inner_tree.root();
807            cursor.jump(&_pos);
808        }
809
810        // No more UB!!
811        cursor.get_data();
812        _pos.get_data();
813
814        // Creates a tree, Position, and CursorMut
815        let mut outer_tree: GenTree<Heading> = construct(0, one);
816        let mut pos: Position<Heading> = outer_tree.root();
817        let mut cursor = outer_tree.cursor_from(pos);
818
819        {
820            let inner_tree: GenTree<Heading> = construct(0, two);
821            pos = inner_tree.root();
822            cursor.jump(&pos);
823        }
824
825        // No more UB!!
826        cursor.get_data();
827        _pos.get_data();
828    }
829
830    use super::*;
831    use std::cell::RefCell;
832    use std::rc::Rc;
833
834    fn create_initialized_tree<T>() -> GenTree<T> {
835        // Instantiate the inner Node layout directly
836        let root_node = Rc::new(RefCell::new(Node {
837            parent: None,
838            children: Vec::new(),
839            data: None, // Initialized with None, ready to populate
840        }));
841
842        // Build the actual GenTree struct using its true fields
843        GenTree {
844            root: Position {
845                ptr: Some(root_node),
846            },
847            size: 1,
848        }
849    }
850
851    #[test]
852    fn test_rc_isolation_and_no_overlapping_data() {
853        let mut tree = GenTree::new();
854        let mut cursor = tree.cursor_mut();
855
856        // 1. Add a child node (auto-descends into Child A)
857        cursor.add_child("Child A".to_string());
858
859        // Capture the handle to Child A
860        let child_pos = cursor.current().clone();
861
862        // 2. Delete Child A.
863        // This moves the cursor to Root and returns Child A's data as an Option!
864        let deleted_data = cursor.delete();
865        assert_eq!(deleted_data, Some("Child A".to_string()));
866
867        // VERIFICATION: Verify cursor successfully jumped back to the root node
868        assert!(cursor.is_root());
869
870        // 3. THE LIFECYCLE CHECK:
871        // Jump back to the isolated handle. Its internal data should now be None.
872        cursor.jump(&child_pos);
873        assert!(cursor.get_data().is_none());
874    }
875
876    #[test]
877    fn test_parent_child_severance_on_delete() {
878        let mut tree = create_initialized_tree();
879        let mut cursor = tree.cursor_mut();
880
881        // Create: Root -> Parent Node (cursor enters Parent Node)
882        cursor.add_child("Parent Node".to_string());
883        let parent_pos = cursor.current().clone();
884
885        // Create child: Parent Node -> Leaf Node (cursor enters Leaf Node)
886        cursor.add_child("Leaf Node".to_string());
887
888        // Jump back to Parent Node and delete it
889        cursor.jump(&parent_pos);
890        cursor.delete();
891
892        // VERIFICATION: Because the delete method hoists children up,
893        // the Root node should now have exactly 1 child (the promoted Leaf Node!)
894        assert!(cursor.is_root());
895        assert_eq!(cursor.num_children(), 1);
896    }
897
898    #[test]
899    fn test_rc_tree_churn_and_metrics() {
900        let mut tree = create_initialized_tree();
901        let mut cursor = tree.cursor_mut();
902
903        // 1. Build a deep linear spine: Root -> N1 -> N2 -> N3
904        cursor.add_child("N1".to_string());
905        let n1_pos = cursor.current().clone();
906
907        cursor.add_child("N2".to_string());
908        let n2_pos = cursor.current().clone();
909
910        cursor.add_child("N3".to_string());
911
912        // VERIFICATION: Confirming the depth logic measures a full 3 edges from the root!
913        assert_eq!(cursor.depth(), 3);
914
915        // 2. Erase the middle node (N2)
916        cursor.jump(&n2_pos);
917        cursor.delete();
918
919        // 3. Verify metrics adjust automatically based on hoisting logic
920        // N3 should now be a direct child of N1
921        cursor.jump(&n1_pos);
922        assert_eq!(cursor.num_children(), 1);
923    }
924}