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    []
1718    ├── 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.borrow().parent.as_ref()
479        .and_then(|weak| weak.upgrade());
480
481    let old_data = {
482        let mut self_node = self_rc.borrow_mut();
483        self_node.data.take()
484    };
485
486    if let Some(parent_rc) = parent_maybe {
487        let parent_pos = Position { ptr: Some(parent_rc.clone()) };
488
489        // 1. Remove self from parent.children by checking pointer address identity
490{
491    let mut parent_node = parent_rc.borrow_mut();
492    
493    // Extract our underlying Rc pointer to compare against
494    if let Some(self_inner_rc) = &self.node.ptr {
495        if let Some(index) = parent_node.children.iter().position(|c| {
496            if let Some(child_inner_rc) = &c.ptr {
497                // Check if they point to the exact same memory allocation
498                Rc::ptr_eq(child_inner_rc, self_inner_rc)
499            } else {
500                false
501            }
502        }) {
503            parent_node.children.remove(index);
504        }
505    }
506}
507
508        // 2. Take self's children (detach them)
509        let mut self_children = {
510            let mut self_node = self_rc.borrow_mut();
511            std::mem::take(&mut self_node.children)
512        };
513
514        // 3. Reparent each child and move them to parent's children
515        {
516            let mut parent_node = parent_rc.borrow_mut();
517            for child in &mut self_children {
518                if let Some(child_rc) = child.ptr.clone() {
519                    child_rc.borrow_mut().parent = Some(Rc::downgrade(&parent_rc));
520                }
521                parent_node.children.push(child.clone());
522            }
523        }
524
525        // 4. Move cursor to parent
526        self.jump(&parent_pos);
527    } else {
528        // Root deletion handling: If you delete the root, you decide where the cursor goes.
529        // For example, making the tree entirely None, or making a child the new root.
530        self.node = Position { ptr: None }; 
531    }
532
533    // 5. Explicitly decrement the size track!
534    self.tree.size -= 1;
535
536    old_data
537}
538
539    // NAVIGATION
540    /////////////
541
542    /** Returns a reference to the current `Position` */
543    pub fn current(&self) -> &Position<T> {
544        &self.node
545    }
546
547    /** Jump the cursor to the given `Position` */
548    pub fn jump(&mut self, new: &Position<T>) {
549        self.node = (*new).clone();
550    }
551
552    /** Moves the cursor up a generation, if `Some`; Trying to ascend past the root results in an error */
553    pub fn ascend(&mut self) -> Result<(), String> {
554        if let Some(parent) = self.node.get_parent_pos() {
555            self.node = parent;
556            Ok(())
557        } else {
558            Err("Error: Cannot ascend past root".to_string())
559        }
560    }
561}
562
563#[cfg(test)]
564mod tests {
565
566    // Both basic and dangle tests use the tree builder
567    use super::{GenTree, Position};
568    use crate::hierarchies::safe_linked_gentree_builder::{construct, Heading};
569
570    #[test]
571    /** Creates this tree to test properties
572        []
573        ├── Landlocked
574        │   ├── Switzerland
575        │   │   └── Geneva
576        │   │       └── Old Town
577        │   │           └── Cathédrale Saint-Pierre
578        │   └── Bolivia
579        │       └── []
580        │           └── []
581        │               ├── Puerta del Sol
582        │               └── Puerta de la Luna
583        └── Islands
584            ├── Marine
585            │   └── Australia
586            └── Fresh Water
587    */
588    fn basic() {
589        let tree_vec = vec![
590            Heading {
591                level: 2,
592                title: "Landlocked".to_string(),
593            },
594            Heading {
595                level: 3,
596                title: "Switzerland".to_string(),
597            },
598            Heading {
599                level: 4,
600                title: "Geneva".to_string(),
601            },
602            Heading {
603                level: 5,
604                title: "Old Town".to_string(),
605            },
606            Heading {
607                level: 6,
608                title: "Cathédrale Saint-Pierre".to_string(),
609            },
610            Heading {
611                level: 3,
612                title: "Bolivia".to_string(),
613            },
614            Heading {
615                level: 6,
616                title: "Puerta del Sol".to_string(),
617            },
618            Heading {
619                level: 6,
620                title: "Puerta de la Luna".to_string(),
621            },
622            Heading {
623                level: 2,
624                title: "Islands".to_string(),
625            },
626            Heading {
627                level: 3,
628                title: "Marine".to_string(),
629            },
630            Heading {
631                level: 4,
632                title: "Australia".to_string(),
633            },
634            Heading {
635                level: 3,
636                title: "Fresh Water".to_string(),
637            },
638        ];
639
640        // Constructs tree ignoring the first heading
641        let mut tree: GenTree<Heading> = construct(1, tree_vec);
642
643        assert!(tree.root.get_parent_pos().is_none());
644        assert!(tree.root().ptr.is_some());
645        let p = tree.root();
646        let _ = p.get_data();
647
648        // Tests root() -> Position<T>
649        // By identity (using custom PartialEq ipml)
650        assert!(tree.cursor_mut().node == tree.root);
651        // By assert_eq!'s default Debug route
652        let cursor = tree.cursor_mut();
653        assert_eq!(cursor.node, tree.root());
654
655        let mut cursor = tree.cursor_mut();
656        // Tests that root is empty with is_some() and is_none()
657        assert!(!cursor.is_some());
658        assert!(cursor.is_none());
659        // tests height and depth
660        assert_eq!(cursor.depth(), 0);
661        assert_eq!(cursor.height(), 6);
662
663        // Tests num_children()
664        assert_eq!(cursor.num_children(), 2); // Root has [Landlocked, Islands]
665
666        // Tests children(), jump(), and get_data()
667        let kids = cursor.children();
668        let mut kids_iter = kids.iter();
669
670        // Moves to first child "Landlocked"
671        cursor.jump(kids_iter.next().unwrap());
672        {
673            let data = cursor.get_data().unwrap();
674            assert_eq!(*data.title, "Landlocked".to_string());
675        }
676        assert_eq!(cursor.depth(), 1);
677        assert_eq!(cursor.height(), 5);
678
679        // Moves to second child "Islands"
680        cursor.jump(kids_iter.next().unwrap());
681        let curr: Position<Heading> = cursor.current().clone(); // Passes the torch
682        {
683            let data = cursor.get_data().unwrap();
684            assert_eq!(*data.title, "Islands".to_string());
685        }
686        assert_eq!(cursor.depth(), 1);
687        assert_eq!(cursor.height(), 3);
688
689        // Jumps down a generation to [Marine, Fresh Water]
690        cursor.jump(&curr);
691        {
692            let new_kids = cursor.children();
693            let mut kids_iter = new_kids.iter();
694            cursor.jump(kids_iter.next().unwrap()); // Moves to first child
695            let data = cursor.get_data().unwrap();
696            assert_eq!(*data.title, "Marine".to_string());
697        }
698        // tests height and depth
699        assert_eq!(cursor.depth(), 2);
700        assert_eq!(cursor.height(), 2);
701
702        // Jumps down a generation, for fun
703        let new_kids = cursor.children(); // Gets cursor's chidlren
704        let mut kids_iter = new_kids.iter(); // Creates an iterator
705        cursor.jump(kids_iter.next().unwrap()); // Moves to first child
706        {
707            let data = cursor.get_data().unwrap();
708            assert_eq!(*data.title, "Australia".to_string());
709        }
710        assert_eq!(cursor.depth(), 3);
711        assert_eq!(cursor.height(), 1);
712
713        // Tests ascend()
714        assert!(cursor.ascend().is_ok()); // Marine
715        assert!(cursor.ascend().is_ok()); // Islands
716        {
717            let data = cursor.get_data().unwrap();
718            assert_eq!(*data.title, "Islands".to_string());
719        }
720        assert!(cursor.ascend().is_ok()); // []
721        assert!(cursor.ascend().is_err()); // Cannot ascend() past root
722        assert!(cursor.is_root()); // Double checks, just in case
723        assert_eq!(cursor.depth(), 0);
724        assert_eq!(cursor.height(), 6);
725
726        // Descends to Islands to test delete()
727        let kids = cursor.children(); // Gets cursor's chidlren
728        let mut kids_iter = kids.iter(); // Creates an iterator
729        cursor.jump(kids_iter.next().unwrap()); // Moves to Landlocked
730        cursor.jump(kids_iter.next().unwrap()); // Moves to Islands
731        {
732            let data = cursor.get_data().unwrap();
733            assert_eq!(*data.title, "Islands".to_string());
734        }
735
736        // Tests delete()
737        // Creates placeholder Heading
738        let mut deleted = Heading {
739            title: String::new(),
740            level: 0,
741        };
742        // Iterates through the child position's under the cursor
743        // looking for a matching Heading; Once found, jumps to that position,
744        // and deletes the Heading; The delete() operation automatically jumps
745        // the cursor to the parent of the deleted position
746        for position in cursor.children().iter() {
747            if position.get_data().unwrap().title == "Marine" {
748                cursor.jump(position);
749                deleted = cursor.delete().unwrap();
750            }
751        }
752        // Tests that the correct Heading was deleted
753        assert_eq!(deleted.level, 3);
754        assert_eq!(deleted.title, "Marine".to_string());
755
756        // Tests that the cursor got bumped up to Islands
757        let data = cursor.get_data().unwrap();
758        assert_eq!(data.title, "Islands".to_string());
759
760        // Tests that the Islands node has the correct children
761        let mut kids = Vec::new();
762        assert_eq!(cursor.children().len(), 2);
763        for child in cursor.children().iter() {
764            let title = child.get_data().unwrap().title.clone();
765            kids.push(title)
766        }
767        assert_eq!(kids, ["Fresh Water".to_string(), "Australia".to_string()]);
768    }
769
770    #[test]
771    fn dangle() {
772        use super::{GenTree, Position};
773        let one = vec![
774            Heading {
775                level: 1,
776                title: "Landlocked".to_string(),
777            },
778            Heading {
779                level: 2,
780                title: "Switzerland".to_string(),
781            },
782        ];
783        let two = vec![
784            Heading {
785                level: 1,
786                title: "Bolivia".to_string(),
787            },
788            Heading {
789                level: 2,
790                title: "Zimbabwe".to_string(),
791            },
792        ];
793
794        // Creates a tree, Position, and CursorMut
795        let mut outer_tree: GenTree<Heading> = construct(0, one.clone());
796        let mut _pos: Position<Heading> = outer_tree.root();
797        let mut cursor = outer_tree.cursor_mut();
798
799        {
800            let inner_tree: GenTree<Heading> = construct(0, two.clone());
801            _pos = inner_tree.root();
802            cursor.jump(&_pos);
803        }
804
805        // No more UB!!
806        cursor.get_data();
807        _pos.get_data();
808
809        // Creates a tree, Position, and CursorMut
810        let mut outer_tree: GenTree<Heading> = construct(0, one);
811        let mut pos: Position<Heading> = outer_tree.root();
812        let mut cursor = outer_tree.cursor_from(pos);
813
814        {
815            let inner_tree: GenTree<Heading> = construct(0, two);
816            pos = inner_tree.root();
817            cursor.jump(&pos);
818        }
819
820        // No more UB!!
821        cursor.get_data();
822        _pos.get_data();
823    }
824
825    use super::*;
826    use std::rc::Rc;
827use std::cell::RefCell;
828
829fn create_initialized_tree<T>() -> GenTree<T> {
830    // Instantiate the inner Node layout directly
831    let root_node = Rc::new(RefCell::new(Node {
832        parent: None,
833        children: Vec::new(),
834        data: None, // Initialized with None, ready to populate
835    }));
836
837    // Build the actual GenTree struct using its true fields
838    GenTree {
839        root: Position { ptr: Some(root_node) },
840        size: 1,
841    }
842}
843
844#[test]
845fn test_rc_isolation_and_no_overlapping_data() {
846    let mut tree = GenTree::new();
847    let mut cursor = tree.cursor_mut();
848    
849    // 1. Add a child node (auto-descends into Child A)
850    cursor.add_child("Child A".to_string());
851    
852    // Capture the handle to Child A
853    let child_pos = cursor.current().clone();
854    
855    // 2. Delete Child A. 
856    // This moves the cursor to Root and returns Child A's data as an Option!
857    let deleted_data = cursor.delete();
858    assert_eq!(deleted_data, Some("Child A".to_string()));
859    
860    // VERIFICATION: Verify cursor successfully jumped back to the root node
861    assert!(cursor.is_root());
862
863    // 3. THE LIFECYCLE CHECK:
864    // Jump back to the isolated handle. Its internal data should now be None.
865    cursor.jump(&child_pos);
866    assert!(cursor.get_data().is_none());
867}
868
869#[test]
870fn test_parent_child_severance_on_delete() {
871    let mut tree = create_initialized_tree();
872    let mut cursor = tree.cursor_mut();
873    
874    // Create: Root -> Parent Node (cursor enters Parent Node)
875    cursor.add_child("Parent Node".to_string());
876    let parent_pos = cursor.current().clone();
877    
878    // Create child: Parent Node -> Leaf Node (cursor enters Leaf Node)
879    cursor.add_child("Leaf Node".to_string());
880    
881    // Jump back to Parent Node and delete it
882    cursor.jump(&parent_pos);
883    cursor.delete();
884    
885    // VERIFICATION: Because the delete method hoists children up,
886    // the Root node should now have exactly 1 child (the promoted Leaf Node!)
887    assert!(cursor.is_root());
888    assert_eq!(cursor.num_children(), 1);
889}
890
891#[test]
892fn test_rc_tree_churn_and_metrics() {
893    let mut tree = create_initialized_tree();
894    let mut cursor = tree.cursor_mut();
895    
896    // 1. Build a deep linear spine: Root -> N1 -> N2 -> N3
897    cursor.add_child("N1".to_string());
898    let n1_pos = cursor.current().clone();
899    
900    cursor.add_child("N2".to_string());
901    let n2_pos = cursor.current().clone();
902    
903    cursor.add_child("N3".to_string());
904    
905    // VERIFICATION: Confirming the depth logic measures a full 3 edges from the root!
906    assert_eq!(cursor.depth(), 3);
907    
908    // 2. Erase the middle node (N2)
909    cursor.jump(&n2_pos);
910    cursor.delete();
911    
912    // 3. Verify metrics adjust automatically based on hoisting logic
913    // N3 should now be a direct child of N1
914    cursor.jump(&n1_pos);
915    assert_eq!(cursor.num_children(), 1);
916}
917}