easy_tree/
lib.rs

1//! # easy-tree
2//!
3//! `easy-tree` is a lightweight library for creating and manipulating tree structures in Rust.
4//! It provides a simple and efficient interface for managing hierarchical data and supports
5//! **depth-first traversal** with pre- and post-processing callbacks for flexible operations.
6//!
7//! ## Features
8//!
9//! - **Simple API**: Easily create, add, and retrieve nodes in the tree.
10//! - **Depth-first traversal**: Recursively traverse the tree with callbacks before and after processing subtrees.
11//! - **Flexible node access**: Access parent-child relationships and modify node data.
12//! - **Optional parallel iteration**: Speed up iteration with [rayon](https://docs.rs/rayon) when enabled.
13//!
14//! ## Use Cases
15//!
16//! `easy-tree` is ideal for representing and traversing hierarchical data, such as:
17//! - **File systems**
18//! - **Organizational charts**
19//! - **Abstract syntax trees (ASTs)**
20//! - **Graph-like structures with one parent per node**
21//!
22//! # Examples
23//!
24//! ## 1. Basic Tree Operations
25//! ```rust
26//!  use easy_tree::Tree;
27//!
28//!  let mut tree = Tree::new();
29//!  let root = tree.add_node("root");
30//!  let child1 = tree.add_child(root, "child1");
31//!  let child2 = tree.add_child(root, "child2");
32//!  let grandchild = tree.add_child(child1, "grandchild");
33//!
34//!  assert_eq!(tree.get(root), Some(&"root"));
35//!  assert_eq!(tree.get(grandchild), Some(&"grandchild"));
36//!  assert_eq!(tree.children(root), &[child1, child2]);
37//!  assert_eq!(tree.parent_index_unchecked(grandchild), Some(child1));
38//! ```
39//!
40//! ## 2. Depth-First Traversal
41//! Process nodes before and after their children using callbacks.
42//!
43//! ```rust
44//!  use easy_tree::Tree;
45//!
46//!  let mut tree = Tree::new();
47//!  let root = tree.add_node("root");
48//!  let child1 = tree.add_child(root, "child1");
49//!  let child2 = tree.add_child(root, "child2");
50//!
51//!  let mut result = vec![];
52//!  tree.traverse(
53//!     |idx, data, result| result.push(format!("Entering node {}: {}", idx, data)),
54//!     |idx, data, result| result.push(format!("Leaving node {}: {}", idx, data)),
55//!     &mut result,
56//!  );
57//!
58//!  assert_eq!(result, vec![
59//!     "Entering node 0: root",
60//!     "Entering node 1: child1",
61//!     "Leaving node 1: child1",
62//!     "Entering node 2: child2",
63//!     "Leaving node 2: child2",
64//!     "Leaving node 0: root",
65//!  ]);
66//! ```
67//!
68//! ## 3. Iteration
69//!
70//! Iterate over nodes and modify their data.
71//!
72//! ```rust
73//!  use easy_tree::Tree;
74//!
75//!  let mut tree = Tree::new();
76//!  let root = tree.add_node(0);
77//!  let child1 = tree.add_child(root, 1);
78//!  let child2 = tree.add_child(root, 2);
79//!
80//!  for (idx, data) in tree.iter_mut() {
81//!     *data += 10;
82//!  }
83//!
84//!  assert_eq!(tree.get(root), Some(&10));
85//!  assert_eq!(tree.get(child1), Some(&11));
86//!  assert_eq!(tree.get(child2), Some(&12));
87//! ```
88//!
89//! ## 4. Parallel Iteration (Optional)
90//!
91//! Use the `rayon` feature for parallel processing of nodes.
92//!
93//! ```rust
94//! #[cfg(feature = "rayon")]
95//! use easy_tree::Tree;
96//! #[cfg(feature = "rayon")]
97//! use rayon::prelude::*;
98//!
99//! #[cfg(feature = "rayon")]
100//! fn main() {
101//!     let mut tree = Tree::new();
102//!     let root = tree.add_node(0);
103//!     tree.add_child(root, 1);
104//!     tree.add_child(root, 2);
105//!
106//!     tree.par_iter().for_each(|(idx, data)| {
107//!         println!("Processing node {}: {}", idx, data);
108//!     });
109//! }
110//!
111//! #[cfg(not(feature = "rayon"))]
112//! fn main() {}
113//! ```
114//!
115//! ## API Overview
116//!
117//! - `Tree<T>`: Represents the tree structure containing nodes of type `T`.
118//! - `Node<T>`: Represents a single node in the tree.
119//! - `Tree::add_node(data: T) -> usize`: Adds a new root node.
120//! - `Tree::add_child(parent: usize, data: T) -> usize`: Adds a child node to a parent.
121//! - `Tree::traverse`: Walks the tree recursively with customizable callbacks.
122//! - `Tree::iter` / `Tree::iter_mut`: Provides immutable and mutable iterators over the nodes.
123//!
124//! ## Contributing
125//! Contributions are welcome! For more details, see the [GitHub repository](https://github.com/antouhou/easy-tree).
126//!
127//! ## License
128//! This project is licensed under the MIT License. See [LICENSE](https://github.com/antouhou/easy-tree/blob/main/LICENSE) for details.
129
130#[cfg(feature = "rayon")]
131pub use rayon;
132#[cfg(feature = "rayon")]
133use rayon::prelude::*;
134
135/// Represents a single node in a tree structure.
136///
137/// Each node contains:
138/// - **data**: A payload of generic type `T`.
139/// - **children**: A list of indices referring to its child nodes.
140/// - **parent**: An optional index referring to its parent node (or `None` if the node is a root).
141///
142/// Normally, you should use the `Tree::add_node` and
143/// `Tree::add_child` methods to create nodes and add them to the tree. There's no need to
144/// address `Node` directly in most cases.
145#[derive(Clone)]
146pub struct Node<T> {
147    data: T,
148    children: Vec<usize>,
149    parent: Option<usize>,
150}
151
152impl<T> Node<T> {
153    /// Creates a new node with the given data. Normally, you should use the `Tree::add_node` and
154    /// `Tree::add_child` methods to create nodes and add them to the tree. There's no need to
155    /// address `Node` directly in most cases.
156    ///
157    /// # Parameters
158    /// - `data`: The data to associate with this node.
159    ///
160    /// # Returns
161    /// A new `Node` instance.
162    ///
163    /// # Example
164    /// ```
165    /// use easy_tree::Node;
166    ///
167    /// let node = Node::new("example");
168    /// ```
169    pub fn new(data: T) -> Self {
170        Self {
171            data,
172            children: Vec::new(),
173            parent: None,
174        }
175    }
176
177    /// Adds a child to this node.
178    ///
179    /// # Parameters
180    /// - `child`: The index of the child node to add.
181    ///
182    /// # Internal Use
183    /// This method is used internally by the `Tree` struct.
184    pub(crate) fn add_child(&mut self, child: usize) {
185        self.children.push(child);
186    }
187
188    /// Sets the parent for this node.
189    ///
190    /// # Parameters
191    /// - `parent`: The index of the parent node to set.
192    ///
193    /// # Internal Use
194    /// This method is used internally by the `Tree` struct.
195    pub(crate) fn set_parent(&mut self, parent: usize) {
196        self.parent = Some(parent);
197    }
198}
199
200/// A tree structure containing multiple nodes of generic type `T`.
201///
202/// Each node in the tree is indexed by its position in the internal vector.
203/// The tree supports operations for adding, accessing, and traversing nodes.
204///
205/// # Example
206/// ```rust
207/// use easy_tree::Tree;
208///
209/// let mut tree = Tree::new();
210/// let root = tree.add_node("root");
211/// let child = tree.add_child(root, "child");
212/// ```
213#[derive(Clone)]
214pub struct Tree<T> {
215    nodes: Vec<Node<T>>,
216}
217
218impl<T> Default for Tree<T> {
219    fn default() -> Self {
220        Self::new()
221    }
222}
223
224impl<T> Tree<T> {
225    /// Creates a new, empty tree.
226    ///
227    /// # Returns
228    /// A `Tree` instance with no nodes.
229    ///
230    /// # Example
231    /// ```rust
232    /// use easy_tree::Tree;
233    ///
234    /// let tree: Tree<i32> = Tree::new();
235    /// ```
236    pub fn new() -> Self {
237        Self { nodes: Vec::new() }
238    }
239
240    /// Adds a new node to the tree.
241    ///
242    /// This method is typically used to add a root node or a disconnected node.
243    ///
244    /// # Parameters
245    /// - `data`: The data to associate with the new node.
246    ///
247    /// # Returns
248    /// The index of the newly added node.
249    ///
250    /// # Example
251    /// ```rust
252    /// use easy_tree::Tree;
253    ///
254    /// let mut tree = Tree::new();
255    /// let root = tree.add_node("root");
256    /// ```
257    pub fn add_node(&mut self, data: T) -> usize {
258        let node = Node::new(data);
259        let index = self.nodes.len();
260        self.nodes.push(node);
261        index
262    }
263
264    /// Adds a child node to an existing node in the tree.
265    ///
266    /// # Parameters
267    /// - `parent`: The index of the parent node.
268    /// - `data`: The data to associate with the new child node.
269    ///
270    /// # Returns
271    /// The index of the newly added child node.
272    ///
273    /// # Example
274    /// ```rust
275    /// use easy_tree::Tree;
276    ///
277    /// let mut tree = Tree::new();
278    /// let root = tree.add_node("root");
279    /// let child = tree.add_child(root, "child");
280    /// ```
281    pub fn add_child(&mut self, parent: usize, data: T) -> usize {
282        let index = self.add_node(data);
283        self.nodes[parent].add_child(index);
284        self.nodes[index].set_parent(parent);
285        index
286    }
287
288    /// Adds a child node to the tree root.
289    ///
290    /// # Parameters
291    /// - `data`: The data to associate with the new child node.
292    ///
293    /// # Returns
294    /// The index of the newly added child node.
295    ///
296    /// # Example
297    /// ```rust
298    /// use easy_tree::Tree;
299    ///
300    /// let mut tree = Tree::new();
301    /// let root = tree.add_node("root");
302    /// let child = tree.add_child_to_root("child");
303    /// ```
304    pub fn add_child_to_root(&mut self, data: T) -> usize {
305        self.add_child(0, data)
306    }
307
308    /// Retrieves a reference to the data stored in a node.
309    ///
310    /// # Parameters
311    /// - `index`: The index of the node to access.
312    ///
313    /// # Returns
314    /// `Some(&T)` if the node exists, or `None` if the index is out of bounds.
315    ///
316    /// # Example
317    /// ```rust
318    /// use easy_tree::Tree;
319    ///
320    /// let mut tree = Tree::new();
321    /// let root = tree.add_node(42);
322    /// assert_eq!(tree.get(root), Some(&42));
323    /// ```
324    pub fn get(&self, index: usize) -> Option<&T> {
325        self.nodes.get(index).map(|node| &node.data)
326    }
327
328    /// Retrieves a reference to the data stored in a node without bounds checking.
329    ///
330    /// This method is faster than [`Tree::get`] because it does not perform any bounds checking.
331    /// However, it is unsafe to use if the provided index is out of bounds or invalid.
332    ///
333    /// # Parameters
334    /// - `index`: The index of the node to access.
335    ///
336    /// # Returns
337    /// A reference to the data stored in the node.
338    ///
339    /// # Safety
340    /// Ensure that:
341    /// - The `index` is within the valid range of node indices in the tree (0 to `Tree::len() - 1`).
342    /// - The node at the given index exists and has not been removed (if applicable).
343    ///
344    /// # Example
345    /// ```rust
346    /// use easy_tree::Tree;
347    ///
348    /// let mut tree = Tree::new();
349    /// let root = tree.add_node(42);
350    ///
351    /// // Safe use: The index is valid.
352    /// assert_eq!(tree.get_unchecked(root), &42);
353    ///
354    /// // Unsafe use: Accessing an invalid index would cause undefined behavior.
355    /// // let invalid = tree.get_unchecked(999); // Avoid this!
356    /// ```
357    #[inline(always)]
358    pub fn get_unchecked(&self, index: usize) -> &T {
359        &self.nodes[index].data
360    }
361
362    /// Retrieves a mutable reference to the data stored in a node.
363    ///
364    /// # Parameters
365    /// - `index`: The index of the node to access.
366    ///
367    /// # Returns
368    /// `Some(&mut T)` if the node exists, or `None` if the index is out of bounds.
369    ///
370    /// # Example
371    /// ```rust
372    /// use easy_tree::Tree;
373    ///
374    /// let mut tree = Tree::new();
375    /// let root = tree.add_node(42);
376    /// *tree.get_mut(root).unwrap() = 43;
377    /// assert_eq!(tree.get(root), Some(&43));
378    /// ```
379    pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
380        self.nodes.get_mut(index).map(|node| &mut node.data)
381    }
382
383    /// Retrieves a mutable reference to the data stored in a node without bounds checking.
384    ///
385    /// This method is faster than [`Tree::get_mut`] because it does not perform any bounds checking.
386    /// However, it is unsafe to use if the provided index is out of bounds or invalid.
387    ///
388    /// # Parameters
389    /// - `index`: The index of the node to access.
390    ///
391    /// # Returns
392    /// A mutable reference to the data stored in the node.
393    ///
394    /// # Safety
395    /// Ensure that:
396    /// - The `index` is within the valid range of node indices in the tree (0 to `Tree::len() - 1`).
397    /// - The node at the given index exists and has not been removed (if applicable).
398    /// - No other references to the same node are active during this call, to avoid data races or aliasing violations.
399    ///
400    /// # Example
401    /// ```rust
402    /// use easy_tree::Tree;
403    ///
404    /// let mut tree = Tree::new();
405    /// let root = tree.add_node(42);
406    ///
407    /// // Safe use: The index is valid.
408    /// *tree.get_unchecked_mut(root) = 99;
409    /// assert_eq!(tree.get_unchecked(root), &99);
410    ///
411    /// // Unsafe use: Accessing an invalid index would cause undefined behavior.
412    /// // let invalid = tree.get_unchecked_mut(999); // Avoid this!
413    /// ```
414    #[inline(always)]
415    pub fn get_unchecked_mut(&mut self, index: usize) -> &mut T {
416        &mut self.nodes[index].data
417    }
418
419    /// Returns the parent index of a node, if it has a parent.
420    ///
421    /// # Parameters
422    /// - `index`: The index of the node.
423    ///
424    /// # Returns
425    /// `Some(parent_index)` if the node has a parent, or `None` otherwise.
426    ///
427    /// # Panics
428    /// This method panics if the index is out of bounds.
429    ///
430    /// # Example
431    /// ```rust
432    /// use easy_tree::Tree;
433    ///
434    /// let mut tree = Tree::new();
435    /// let root = tree.add_node(42);
436    /// let child = tree.add_child(root, 99);
437    /// assert_eq!(tree.parent_index_unchecked(child), Some(root));
438    /// ```
439    pub fn parent_index_unchecked(&self, index: usize) -> Option<usize> {
440        self.nodes[index].parent
441    }
442
443    /// Returns a slice of the indices of the children of a node.
444    ///
445    /// # Parameters
446    /// - `index`: The index of the node.
447    ///
448    /// # Returns
449    /// A slice containing the indices of the node's children.
450    ///
451    /// # Panics
452    /// This method panics if the index is out of bounds.
453    ///
454    /// # Example
455    /// ```rust
456    /// use easy_tree::Tree;
457    ///
458    /// let mut tree = Tree::new();
459    /// let root = tree.add_node("root");
460    /// let child = tree.add_child(root, "child");
461    /// assert_eq!(tree.children(root), &[child]);
462    /// ```
463    pub fn children(&self, index: usize) -> &[usize] {
464        &self.nodes[index].children
465    }
466
467    /// Traverses the tree in a depth-first manner.
468    ///
469    /// The traversal applies two callbacks:
470    /// - `before_processing_children`: Called before processing the children of a node.
471    /// - `after_processing_the_subtree`: Called after processing all children of a node.
472    ///
473    /// # Parameters
474    /// - `before_processing_children`: A function to apply before visiting children.
475    /// - `after_processing_the_subtree`: A function to apply after visiting children.
476    /// - `state`: Mutable state to share across callbacks.
477    ///
478    /// # Example
479    /// ```rust
480    /// use easy_tree::Tree;
481    ///
482    /// let mut tree = Tree::new();
483    /// let root = tree.add_node("root");
484    /// let child = tree.add_child(root, "child");
485    ///
486    /// let mut log = vec![];
487    /// tree.traverse(
488    ///     |idx, data, log| log.push(format!("Entering node {}: {}", idx, data)),
489    ///     |idx, data, log| log.push(format!("Leaving node {}: {}", idx, data)),
490    ///     &mut log,
491    /// );
492    /// ```
493    pub fn traverse<'a, S>(
494        &'a self,
495        mut before_processing_children: impl FnMut(usize, &'a T, &mut S),
496        mut after_processing_the_subtree: impl FnMut(usize, &'a T, &mut S),
497        s: &mut S,
498    ) {
499        if self.is_empty() {
500            return;
501        }
502
503        let mut stack = vec![(0, false)];
504
505        while let Some((index, children_visited)) = stack.pop() {
506            if children_visited {
507                // All children are processed, call f2
508                let node = &self.nodes[index];
509                after_processing_the_subtree(index, &node.data, s);
510            } else {
511                // Call f and mark this node's children for processing
512                let node = &self.nodes[index];
513                before_processing_children(index, &node.data, s);
514
515                // Re-push the current node with children_visited set to true
516                stack.push((index, true));
517
518                // Push all children onto the stack
519                for &child in node.children.iter().rev() {
520                    stack.push((child, false));
521                }
522            }
523        }
524    }
525
526    /// Returns an iterator over the indices and data of the nodes in the tree.
527    pub fn iter(&self) -> impl Iterator<Item = (usize, &T)> {
528        self.nodes
529            .iter()
530            .enumerate()
531            .map(|(index, node)| (index, &node.data))
532    }
533
534    /// Returns a mutable iterator over the indices and data of the nodes in the tree.
535    pub fn iter_mut(&mut self) -> impl Iterator<Item = (usize, &mut T)> {
536        self.nodes
537            .iter_mut()
538            .enumerate()
539            .map(|(index, node)| (index, &mut node.data))
540    }
541
542    /// Returns `true` if the tree contains no nodes.
543    pub fn is_empty(&self) -> bool {
544        self.nodes.is_empty()
545    }
546
547    /// Returns the number of nodes in the tree.
548    pub fn len(&self) -> usize {
549        self.nodes.len()
550    }
551
552    /// Removes all nodes from the tree.
553    pub fn clear(&mut self) {
554        self.nodes.clear();
555    }
556}
557
558#[cfg(feature = "rayon")]
559impl<T: Send + Sync> Tree<T> {
560    #[cfg(feature = "rayon")]
561    /// Returns a parallel iterator over the indices and data of the nodes in the tree.
562    pub fn par_iter(&self) -> impl ParallelIterator<Item = (usize, &T)> {
563        self.nodes
564            .par_iter()
565            .enumerate()
566            .map(|(index, node)| (index, &node.data))
567    }
568
569    #[cfg(feature = "rayon")]
570    /// Returns a mutable parallel iterator over the indices and data of the nodes in the tree.
571    pub fn par_iter_mut(&mut self) -> impl ParallelIterator<Item = (usize, &mut T)> {
572        self.nodes
573            .par_iter_mut()
574            .enumerate()
575            .map(|(index, node)| (index, &mut node.data))
576    }
577}
578
579#[cfg(test)]
580mod tests {
581    use super::*;
582
583    #[test]
584    fn test_tree() {
585        let mut tree = Tree::new();
586        let root = tree.add_node(0);
587        let child1 = tree.add_child(root, 1);
588        let child2 = tree.add_child(root, 2);
589        let child3 = tree.add_child(child1, 3);
590
591        assert_eq!(tree.get(root), Some(&0));
592        assert_eq!(tree.get(child1), Some(&1));
593        assert_eq!(tree.get(child2), Some(&2));
594        assert_eq!(tree.get(child3), Some(&3));
595
596        assert_eq!(tree.parent_index_unchecked(child1), Some(root));
597        assert_eq!(tree.parent_index_unchecked(child2), Some(root));
598        assert_eq!(tree.parent_index_unchecked(child3), Some(child1));
599
600        assert_eq!(tree.children(root), &[child1, child2]);
601        assert_eq!(tree.children(child1), &[child3]);
602        assert_eq!(tree.children(child2), &[]);
603        assert_eq!(tree.children(child3), &[]);
604    }
605
606    #[test]
607    fn test_tree_iter() {
608        let mut tree = Tree::new();
609        let root = tree.add_node(0);
610        let child1 = tree.add_child(root, 1);
611        let child2 = tree.add_child(root, 2);
612        let child3 = tree.add_child(child1, 3);
613
614        let mut iter = tree.iter();
615        assert_eq!(iter.next(), Some((root, &0)));
616        assert_eq!(iter.next(), Some((child1, &1)));
617        assert_eq!(iter.next(), Some((child2, &2)));
618        assert_eq!(iter.next(), Some((child3, &3)));
619        assert_eq!(iter.next(), None);
620    }
621
622    #[test]
623    fn test_tree_iter_mut() {
624        let mut tree = Tree::new();
625        let root = tree.add_node(0);
626        let child1 = tree.add_child(root, 1);
627        let child2 = tree.add_child(root, 2);
628        let child3 = tree.add_child(child1, 3);
629
630        let mut iter = tree.iter_mut();
631        assert_eq!(iter.next(), Some((root, &mut 0)));
632        assert_eq!(iter.next(), Some((child1, &mut 1)));
633        assert_eq!(iter.next(), Some((child2, &mut 2)));
634        assert_eq!(iter.next(), Some((child3, &mut 3)));
635        assert_eq!(iter.next(), None);
636    }
637
638    #[test]
639    fn test_tree_traverse() {
640        let mut tree = Tree::new();
641        let root = tree.add_node(0); // Root node with data 0
642        let child1 = tree.add_child(root, 1); // Child node with data 1
643        let _child2 = tree.add_child(root, 2); // Child node with data 2
644        let _child3 = tree.add_child(child1, 3); // Child node with data 3
645
646        let mut result = vec![];
647
648        tree.traverse(
649            |index, node, result| {
650                result.push(format!("Calling handler for node {}: {}", index, node))
651            },
652            |index, _node, result| {
653                result.push(format!(
654                    "Finished handling node {} and all it's children",
655                    index
656                ))
657            },
658            &mut result,
659        );
660
661        assert_eq!(
662            result,
663            vec![
664                "Calling handler for node 0: 0",
665                "Calling handler for node 1: 1",
666                "Calling handler for node 3: 3",
667                "Finished handling node 3 and all it's children",
668                "Finished handling node 1 and all it's children",
669                "Calling handler for node 2: 2",
670                "Finished handling node 2 and all it's children",
671                "Finished handling node 0 and all it's children",
672            ]
673        );
674    }
675}