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
98/// The `Position` struct provides a safe, lightweight handle to `Node` data.
99/// All meaningful accessors and mutators appear on the [CursorMut] struct.
100// Position only contains private members, but must be public due to its
101// presence as a CursorMut return type.
102pub struct Position<T> {
103    ptr: Option<Rc<RefCell<Node<T>>>>,
104}
105impl<T> Position<T> {
106    /// Creates a handle to Node and returns it as a Position.
107    fn new(ptr: Node<T>) -> Self {
108        Position {
109            ptr: Some(Rc::new(RefCell::new(ptr))),
110        }
111    }
112
113    /// Returns an reference to the data at the Position, if Some.
114    fn get_data(&self) -> Option<Ref<'_, T>> {
115        let node_ref: Ref<Node<T>> = self.ptr.as_ref()?.borrow();
116        Ref::filter_map(node_ref, |node| node.data.as_ref()).ok()
117        //if let Some(val) = self.ptr.as_ref() {
118        //    Some((*(*val)).borrow())
119        //} else { None }
120    }
121
122    /// Returns the Node from a Position, if Some.
123    //fn get_node(&self) -> Ref<Node<T>> {
124    //    self.ptr.as_ref().unwrap().borrow()
125    //}
126    fn get_node(&self) -> Option<Ref<'_, Node<T>>> {
127        self.ptr.as_ref().map(|rc| rc.borrow())
128    }
129
130    /// Returns the Position for the current Position's parent, if Some.
131    //fn get_parent_pos(&self) -> Option<Position<T>> {
132    //    if let Some(parent) = self.ptr.as_ref().unwrap().borrow().parent.clone() {
133    //        Some(parent)
134    //    } else { None }
135    //}
136    fn get_parent_pos(&self) -> Option<Position<T>> {
137        if let Some(weak_parent) = &self.ptr.as_ref()?.borrow().parent {
138            weak_parent.upgrade().map(|rc| Position { ptr: Some(rc) })
139        } else {
140            None
141        }
142    }
143}
144// "Shallow" clone only clones/increases the Rc, not the whole Node
145impl<T> Clone for Position<T> {
146    fn clone(&self) -> Self {
147        Position {
148            ptr: self.ptr.clone(),
149        }
150    }
151}
152impl<T> PartialEq for Position<T> {
153    fn eq(&self, other: &Self) -> bool {
154        match (&self.ptr, &other.ptr) {
155            (Some(a), Some(b)) => Rc::ptr_eq(a, b),
156            (None, None) => true,
157            _ => false,
158        }
159    }
160}
161impl<T> std::fmt::Debug for Position<T> {
162    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
163        match &self.ptr {
164            Some(rc) => write!(f, "Position({:p})", Rc::as_ptr(rc)),
165            None => write!(f, "Position(None)"),
166        }
167    }
168}
169
170/// Internal-only struct that represents the heart of the general tree. The `Node`
171/// struct contains strong pointers to children, but weak pointers to parent nodes
172/// for proper drop semantics to avoid reference cycles.
173struct Node<T> {
174    parent: Option<Weak<RefCell<Node<T>>>>,
175    children: Vec<Position<T>>, // Always exists for a Node, even if empty
176    data: Option<T>,
177}
178impl<T> Node<T> {
179    /// Builds a new Node and returns its position.
180    fn root(data: Option<T>) -> Node<T> {
181        Node {
182            parent: None,
183            children: Vec::new(),
184            data,
185        }
186    }
187
188    /// Creates a new `Node` with given data for the given `Position`.
189    fn new(parent: &Position<T>, data: T) -> Node<T> {
190        Node {
191            //parent: Some(parent.clone()),
192            parent: Some(Rc::downgrade(parent.ptr.as_ref().unwrap())),
193            children: Vec::new(),
194            data: Some(data),
195        }
196    }
197}
198
199/// The `GenTree` struct represents a positional, linked-based general
200/// tree structure that contains a pointer to the root node and the structure's size.
201/// The genericity of the struct means you'll have to explicitly type the
202/// tree at instantiation.
203///
204/// Most of the major accessors and mutators appear on the [CursorMut] struct.
205///
206/// Example:
207/// ```example
208///     // Creates a tree over Heading objects
209///     let mut tree: GenTree<Heading> = GenTree::<Heading>::new();
210///
211///     // Creates a CursorMut to navigate/mutate the tree,
212///     // starting at the root node
213///     let mut cursor = tree.cursor_mut();
214/// ```
215#[derive(Debug)]
216pub struct GenTree<T> {
217    root: Position<T>,
218    size: usize,
219}
220impl<T> Default for GenTree<T> {
221    fn default() -> Self {
222        Self::new()
223    }
224}
225impl<T> GenTree<T> {
226    /// Instantiates a new `GenTree`.
227    pub fn new() -> GenTree<T> {
228        let root: Position<T> = Position::new(Node::root(None));
229        GenTree { root, size: 0 }
230    }
231
232    /// Returns the `Position` of the tree's root.
233    pub fn root(&self) -> Position<T> {
234        self.root.clone()
235    }
236
237    /// Creates a `CursorMut` starting at the tree's root.
238    pub fn cursor_mut(&mut self) -> CursorMut<'_, T> {
239        CursorMut {
240            node: self.root.clone(),
241            tree: self,
242        }
243    }
244
245    /// Creates a `CursorMut` from a given `Position`.
246    pub fn cursor_from(&mut self, position: Position<T>) -> CursorMut<'_, T> {
247        CursorMut {
248            node: position,
249            tree: self,
250        }
251    }
252}
253
254/** A cursor over mutable `Node` data with safe, reference-counted `Position` handles.
255
256This struct represents the majority of major operations for the [GenTree] structure.
257All operations run in `O(1)` time unless otherwise noted. */
258pub struct CursorMut<'a, T> {
259    node: Position<T>,
260    tree: &'a mut GenTree<T>,
261}
262impl<'a, T> CursorMut<'a, T> {
263    // METADATA
264    ///////////
265
266    /** Returns `true` if the `Node` under the curosr is the tree's root */
267    pub fn is_root(&self) -> bool {
268        self.node.clone() == self.tree.root()
269    }
270
271    /** Returns `true` if the `Node` under the curosr has data */
272    pub fn is_some(&self) -> bool {
273        let val = self.node.get_data();
274        val.is_some()
275    }
276
277    /** Returns `true` if the `Node` under the cursor is empty */
278    pub fn is_none(&self) -> bool {
279        let val = self.node.get_data();
280        val.is_none()
281    }
282
283    /** Returns the number of children for the `Node` under the cursor as usize */
284    pub fn num_children(&self) -> usize {
285        if let Some(val) = self.node.ptr.clone() {
286            (*val).borrow().children.len()
287        } else {
288            0
289        }
290    }
291
292    /** Returns the depth of the cursor from the tree's root */
293    //pub fn depth(&mut self) -> usize {
294    //    let mut depth = 0;
295    //    let current = self.current().clone();
296    //    while !self.is_root() {
297    //        self.ascend().ok();
298    //        depth += 1;
299    //    }
300    //    self.jump(&current);
301    //    depth
302    //}
303    pub fn depth(&self) -> usize {
304        let mut depth = 0;
305        let mut current_ptr = self.node.clone().ptr;
306        //while let Some(pos) = current.ptr {
307        while let Some(pos) = current_ptr {
308            let node_ref = pos.borrow();
309            if let Some(parent_weak) = &node_ref.parent {
310                //current = Position { ptr: parent_weak.upgrade() };
311                current_ptr = parent_weak.upgrade();
312                depth += 1;
313            } else {
314                break;
315            }
316        }
317        depth
318    }
319
320    /** Returns the height of the tallest sub-tree for the current position */
321    //pub fn height(&self) -> usize {
322    //    let current = self.current();
323    //    self.height_rec(current.clone())
324    //}
325    ///** The recursive guts of the height function */
326    //#[allow(clippy::only_used_in_recursion)]
327    //fn height_rec(&self, node: Position<T>) -> usize {
328    //    let mut h = 0;
329    //    if let Some(n) = node.ptr.clone() {
330    //        for e in &(*n).borrow().children {
331    //            h = std::cmp::max(h, self.height_rec(e.clone()))
332    //        }
333    //    }
334    //    h + 1
335    //}
336    pub fn height(&self) -> usize {
337        let current = self.current();
338        fn height_rec<T>(node: &Position<T>) -> usize {
339            let mut h = 0;
340            if let Some(n) = node.ptr.clone() {
341                for e in &(*n).borrow().children {
342                    h = std::cmp::max(h, height_rec(&e.clone()))
343                }
344            }
345            h + 1
346        }
347        height_rec(current)
348    }
349
350    // ACCESSORS AND MUTATORS
351    /////////////////////////
352
353    /** Returns an _immutable_ reference to the data under the cursor, if `Some` */
354    pub fn get_data(&self) -> Option<Ref<'_, T>> {
355        let node_ref: Ref<Node<T>> = self.node.get_node()?;
356        Ref::filter_map(node_ref, |node| node.data.as_ref()).ok()
357    }
358
359    /** Returns an _immutable_ reference to the data for a supplied `Position` */
360    pub fn get_for_pos(&'a self, pos: &'a Position<T>) -> Option<Ref<'a, T>> {
361        let node_ref: Ref<Node<T>> = pos.get_node()?;
362        Ref::filter_map(node_ref, |node| node.data.as_ref()).ok()
363    }
364
365    // /** Overwrites the data for the current Node without affecting its position,
366    // returns the old data, if Some */
367    //pub fn set(&mut self, data: T) -> Option<T> {
368    //    if let Ok(n) = self.node.as_ptr() {
369    //        unsafe {
370    //            let old = (*n).data.take();
371    //            (*n).data = Some(data);
372    //            return old;
373    //        }
374    //    } else {
375    //        None
376    //    }
377    //}
378
379    /** Adds a new child `Node` under the current cursor and advances the cursor
380    to the new child */
381    pub fn add_child(&mut self, data: T) {
382        let parent = self.node.clone();
383
384        // Create the new child node and give it a Position
385        let new_node = Node::new(&parent, data);
386        let new_pos = Position::new(new_node);
387
388        // Add the new child to the parent's child list
389        let kids = parent.ptr.unwrap();
390        (*kids).borrow_mut().children.push(new_pos.clone());
391
392        // Mutates self to be the Position of the new node
393        self.node = new_pos;
394
395        // Increment the size of the tree
396        self.tree.size += 1;
397    }
398
399    /** Returns a list of owned descendant (child) `Position`s for the `Node`
400    under the cursor in `O(c)` time where `c` is the number of children; The
401    clone used here is a cheap pointer copy, not an underlying data copy */
402    //pub fn children(&self) -> Vec<Position<T>> {
403    //    self.node
404    //        .get_node()
405    //        .unwrap()
406    //        .children
407    //        .iter()
408    //        .cloned()
409    //        .collect::<Vec<_>>()
410    //}
411    // Allocates a new Vec and clones Positions in O(n) time
412    pub fn children(&self) -> Vec<Position<T>> {
413        self.node
414            .get_node()
415            //.map(|node| node.children.iter().cloned().collect())
416            .map(|node| node.children.to_vec())
417            .unwrap_or_default()
418    }
419
420    /// Warning: Broken! Does not handle root deletion properly.
421    ///
422    /// Removes the node at the current cursor position and returns its data,
423    /// if Some. Operation executes in `O(c)` time where `c` is the number of
424    /// children for the given node; Adds all children to the parent
425    /// (if `Some`), and returns the deleted `Node`; If the cursor is at the tree's
426    /// root, this just deletes the `Node`'s data, leaving `None`; Moves the cursor
427    /// to the parent, if `Some` */
428    pub fn delete(&mut self) -> Option<T> {
429        let self_pos = self.node.clone();
430        let self_rc = self_pos.ptr.clone()?;
431
432        // Check and get parent
433        let parent_pos = self_rc.borrow().parent.as_ref()?.upgrade()?;
434        let parent_pos = Position {
435            ptr: Some(parent_pos),
436        };
437        let parent_rc = parent_pos.ptr.clone().unwrap();
438
439        // 1. Remove self from parent.children
440        {
441            let mut parent_node = parent_rc.borrow_mut();
442            if let Some(index) = parent_node.children.iter().position(|c| *c == self.node) {
443                parent_node.children.remove(index);
444            }
445        }
446
447        // 2. Take self's children (detach them)
448        let mut self_children = {
449            let mut self_node = self_rc.borrow_mut();
450            std::mem::take(&mut self_node.children)
451        };
452
453        // 3. Reparent each child and move them to parent's children
454        {
455            let mut parent_node = parent_rc.borrow_mut();
456            for child in &mut self_children {
457                if let Some(child_rc) = child.ptr.clone() {
458                    child_rc.borrow_mut().parent = Some(Rc::downgrade(&parent_rc));
459                }
460                parent_node.children.push(child.clone());
461            }
462        }
463
464        // 4. Move cursor to parent
465        self.jump(&parent_pos);
466
467        // 5. Take and return data from the deleted node
468        let mut self_node = self_rc.borrow_mut();
469        self_node.data.take()
470    }
471
472    // NAVIGATION
473    /////////////
474
475    /** Returns a reference to the current `Position` */
476    pub fn current(&self) -> &Position<T> {
477        &self.node
478    }
479
480    /** Jump the cursor to the given `Position` */
481    pub fn jump(&mut self, new: &Position<T>) {
482        self.node = (*new).clone();
483    }
484
485    /** Moves the cursor up a generation, if `Some`; Trying to ascend past the root results in an error */
486    pub fn ascend(&mut self) -> Result<(), String> {
487        if let Some(parent) = self.node.get_parent_pos() {
488            self.node = parent;
489            Ok(())
490        } else {
491            Err("Error: Cannot ascend past root".to_string())
492        }
493    }
494}
495
496#[cfg(test)]
497mod tests {
498
499    // Both basic and dangle tests use the tree builder
500    use super::{GenTree, Position};
501    use crate::hierarchies::safe_linked_gentree_builder::{construct, Heading};
502
503    #[test]
504    /** Creates this tree to test properties
505        []
506        ├── Landlocked
507        │   ├── Switzerland
508        │   │   └── Geneva
509        │   │       └── Old Town
510        │   │           └── Cathédrale Saint-Pierre
511        │   └── Bolivia
512        │       └── []
513        │           └── []
514        │               ├── Puerta del Sol
515        │               └── Puerta de la Luna
516        └── Islands
517            ├── Marine
518            │   └── Australia
519            └── Fresh Water
520    */
521    fn basic() {
522        let tree_vec = vec![
523            Heading {
524                level: 2,
525                title: "Landlocked".to_string(),
526            },
527            Heading {
528                level: 3,
529                title: "Switzerland".to_string(),
530            },
531            Heading {
532                level: 4,
533                title: "Geneva".to_string(),
534            },
535            Heading {
536                level: 5,
537                title: "Old Town".to_string(),
538            },
539            Heading {
540                level: 6,
541                title: "Cathédrale Saint-Pierre".to_string(),
542            },
543            Heading {
544                level: 3,
545                title: "Bolivia".to_string(),
546            },
547            Heading {
548                level: 6,
549                title: "Puerta del Sol".to_string(),
550            },
551            Heading {
552                level: 6,
553                title: "Puerta de la Luna".to_string(),
554            },
555            Heading {
556                level: 2,
557                title: "Islands".to_string(),
558            },
559            Heading {
560                level: 3,
561                title: "Marine".to_string(),
562            },
563            Heading {
564                level: 4,
565                title: "Australia".to_string(),
566            },
567            Heading {
568                level: 3,
569                title: "Fresh Water".to_string(),
570            },
571        ];
572
573        // Constructs tree ignoring the first heading
574        let mut tree: GenTree<Heading> = construct(1, tree_vec);
575
576        assert!(tree.root.get_parent_pos().is_none());
577        assert!(tree.root().ptr.is_some());
578        let p = tree.root();
579        let _ = p.get_data();
580
581        // Tests root() -> Position<T>
582        // By identity (using custom PartialEq ipml)
583        assert!(tree.cursor_mut().node == tree.root);
584        // By assert_eq!'s default Debug route
585        let cursor = tree.cursor_mut();
586        assert_eq!(cursor.node, tree.root());
587
588        let mut cursor = tree.cursor_mut();
589        // Tests that root is empty with is_some() and is_none()
590        assert!(!cursor.is_some());
591        assert!(cursor.is_none());
592        // tests height and depth
593        assert_eq!(cursor.depth(), 0);
594        assert_eq!(cursor.height(), 6);
595
596        // Tests num_children()
597        assert_eq!(cursor.num_children(), 2); // Root has [Landlocked, Islands]
598
599        // Tests children(), jump(), and get_data()
600        let kids = cursor.children();
601        let mut kids_iter = kids.iter();
602
603        // Moves to first child "Landlocked"
604        cursor.jump(kids_iter.next().unwrap());
605        {
606            let data = cursor.get_data().unwrap();
607            assert_eq!(*data.title, "Landlocked".to_string());
608        }
609        assert_eq!(cursor.depth(), 1);
610        assert_eq!(cursor.height(), 5);
611
612        // Moves to second child "Islands"
613        cursor.jump(kids_iter.next().unwrap());
614        let curr: Position<Heading> = cursor.current().clone(); // Passes the torch
615        {
616            let data = cursor.get_data().unwrap();
617            assert_eq!(*data.title, "Islands".to_string());
618        }
619        assert_eq!(cursor.depth(), 1);
620        assert_eq!(cursor.height(), 3);
621
622        // Jumps down a generation to [Marine, Fresh Water]
623        cursor.jump(&curr);
624        {
625            let new_kids = cursor.children();
626            let mut kids_iter = new_kids.iter();
627            cursor.jump(kids_iter.next().unwrap()); // Moves to first child
628            let data = cursor.get_data().unwrap();
629            assert_eq!(*data.title, "Marine".to_string());
630        }
631        // tests height and depth
632        assert_eq!(cursor.depth(), 2);
633        assert_eq!(cursor.height(), 2);
634
635        // Jumps down a generation, for fun
636        let new_kids = cursor.children(); // Gets cursor's chidlren
637        let mut kids_iter = new_kids.iter(); // Creates an iterator
638        cursor.jump(kids_iter.next().unwrap()); // Moves to first child
639        {
640            let data = cursor.get_data().unwrap();
641            assert_eq!(*data.title, "Australia".to_string());
642        }
643        assert_eq!(cursor.depth(), 3);
644        assert_eq!(cursor.height(), 1);
645
646        // Tests ascend()
647        assert!(cursor.ascend().is_ok()); // Marine
648        assert!(cursor.ascend().is_ok()); // Islands
649        {
650            let data = cursor.get_data().unwrap();
651            assert_eq!(*data.title, "Islands".to_string());
652        }
653        assert!(cursor.ascend().is_ok()); // []
654        assert!(cursor.ascend().is_err()); // Cannot ascend() past root
655        assert!(cursor.is_root()); // Double checks, just in case
656        assert_eq!(cursor.depth(), 0);
657        assert_eq!(cursor.height(), 6);
658
659        // Descends to Islands to test delete()
660        let kids = cursor.children(); // Gets cursor's chidlren
661        let mut kids_iter = kids.iter(); // Creates an iterator
662        cursor.jump(kids_iter.next().unwrap()); // Moves to Landlocked
663        cursor.jump(kids_iter.next().unwrap()); // Moves to Islands
664        {
665            let data = cursor.get_data().unwrap();
666            assert_eq!(*data.title, "Islands".to_string());
667        }
668
669        // Tests delete()
670        // Creates placeholder Heading
671        let mut deleted = Heading {
672            title: String::new(),
673            level: 0,
674        };
675        // Iterates through the child position's under the cursor
676        // looking for a matching Heading; Once found, jumps to that position,
677        // and deletes the Heading; The delete() operation automatically jumps
678        // the cursor to the parent of the deleted position
679        for position in cursor.children().iter() {
680            if position.get_data().unwrap().title == "Marine" {
681                cursor.jump(position);
682                deleted = cursor.delete().unwrap();
683            }
684        }
685        // Tests that the correct Heading was deleted
686        assert_eq!(deleted.level, 3);
687        assert_eq!(deleted.title, "Marine".to_string());
688
689        // Tests that the cursor got bumped up to Islands
690        let data = cursor.get_data().unwrap();
691        assert_eq!(data.title, "Islands".to_string());
692
693        // Tests that the Islands node has the correct children
694        let mut kids = Vec::new();
695        assert_eq!(cursor.children().len(), 2);
696        for child in cursor.children().iter() {
697            let title = child.get_data().unwrap().title.clone();
698            kids.push(title)
699        }
700        assert_eq!(kids, ["Fresh Water".to_string(), "Australia".to_string()]);
701    }
702
703    #[test]
704    fn dangle() {
705        use super::{GenTree, Position};
706        let one = vec![
707            Heading {
708                level: 1,
709                title: "Landlocked".to_string(),
710            },
711            Heading {
712                level: 2,
713                title: "Switzerland".to_string(),
714            },
715        ];
716        let two = vec![
717            Heading {
718                level: 1,
719                title: "Bolivia".to_string(),
720            },
721            Heading {
722                level: 2,
723                title: "Zimbabwe".to_string(),
724            },
725        ];
726
727        // Creates a tree, Position, and CursorMut
728        let mut outer_tree: GenTree<Heading> = construct(0, one.clone());
729        let mut _pos: Position<Heading> = outer_tree.root();
730        let mut cursor = outer_tree.cursor_mut();
731
732        {
733            let inner_tree: GenTree<Heading> = construct(0, two.clone());
734            _pos = inner_tree.root();
735            cursor.jump(&_pos);
736        }
737
738        // No more UB!!
739        cursor.get_data();
740        _pos.get_data();
741
742        // Creates a tree, Position, and CursorMut
743        let mut outer_tree: GenTree<Heading> = construct(0, one);
744        let mut pos: Position<Heading> = outer_tree.root();
745        let mut cursor = outer_tree.cursor_from(pos);
746
747        {
748            let inner_tree: GenTree<Heading> = construct(0, two);
749            pos = inner_tree.root();
750            cursor.jump(&pos);
751        }
752
753        // No more UB!!
754        cursor.get_data();
755        _pos.get_data();
756    }
757}