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    /// Stack for traverse_mut to avoid allocations
217    stack: Vec<(usize, bool)>,
218}
219
220impl<T> Default for Tree<T> {
221    fn default() -> Self {
222        Self::new()
223    }
224}
225
226impl<T> Tree<T> {
227    /// Creates a new, empty tree.
228    ///
229    /// # Returns
230    /// A `Tree` instance with no nodes.
231    ///
232    /// # Example
233    /// ```rust
234    /// use easy_tree::Tree;
235    ///
236    /// let tree: Tree<i32> = Tree::new();
237    /// ```
238    pub fn new() -> Self {
239        Self {
240            nodes: Vec::new(),
241            stack: Vec::new(),
242        }
243    }
244
245    /// Adds a new node to the tree.
246    ///
247    /// This method is typically used to add a root node or a disconnected node.
248    ///
249    /// # Parameters
250    /// - `data`: The data to associate with the new node.
251    ///
252    /// # Returns
253    /// The index of the newly added node.
254    ///
255    /// # Example
256    /// ```rust
257    /// use easy_tree::Tree;
258    ///
259    /// let mut tree = Tree::new();
260    /// let root = tree.add_node("root");
261    /// ```
262    pub fn add_node(&mut self, data: T) -> usize {
263        let node = Node::new(data);
264        let index = self.nodes.len();
265        self.nodes.push(node);
266        index
267    }
268
269    /// Adds a child node to an existing node in the tree.
270    ///
271    /// # Parameters
272    /// - `parent`: The index of the parent node.
273    /// - `data`: The data to associate with the new child node.
274    ///
275    /// # Returns
276    /// The index of the newly added child node.
277    ///
278    /// # Example
279    /// ```rust
280    /// use easy_tree::Tree;
281    ///
282    /// let mut tree = Tree::new();
283    /// let root = tree.add_node("root");
284    /// let child = tree.add_child(root, "child");
285    /// ```
286    pub fn add_child(&mut self, parent: usize, data: T) -> usize {
287        let index = self.add_node(data);
288        self.nodes[parent].add_child(index);
289        self.nodes[index].set_parent(parent);
290        index
291    }
292
293    /// Adds a child node to the tree root.
294    ///
295    /// # Parameters
296    /// - `data`: The data to associate with the new child node.
297    ///
298    /// # Returns
299    /// The index of the newly added child node.
300    ///
301    /// # Example
302    /// ```rust
303    /// use easy_tree::Tree;
304    ///
305    /// let mut tree = Tree::new();
306    /// let root = tree.add_node("root");
307    /// let child = tree.add_child_to_root("child");
308    /// ```
309    pub fn add_child_to_root(&mut self, data: T) -> usize {
310        self.add_child(0, data)
311    }
312
313    /// Retrieves a reference to the data stored in a node.
314    ///
315    /// # Parameters
316    /// - `index`: The index of the node to access.
317    ///
318    /// # Returns
319    /// `Some(&T)` if the node exists, or `None` if the index is out of bounds.
320    ///
321    /// # Example
322    /// ```rust
323    /// use easy_tree::Tree;
324    ///
325    /// let mut tree = Tree::new();
326    /// let root = tree.add_node(42);
327    /// assert_eq!(tree.get(root), Some(&42));
328    /// ```
329    pub fn get(&self, index: usize) -> Option<&T> {
330        self.nodes.get(index).map(|node| &node.data)
331    }
332
333    /// Retrieves a reference to the data stored in a node without bounds checking.
334    ///
335    /// This method is faster than [`Tree::get`] because it does not perform any bounds checking.
336    /// However, it is unsafe to use if the provided index is out of bounds or invalid.
337    ///
338    /// # Parameters
339    /// - `index`: The index of the node to access.
340    ///
341    /// # Returns
342    /// A reference to the data stored in the node.
343    ///
344    /// # Safety
345    /// Ensure that:
346    /// - The `index` is within the valid range of node indices in the tree (0 to `Tree::len() - 1`).
347    /// - The node at the given index exists and has not been removed (if applicable).
348    ///
349    /// # Example
350    /// ```rust
351    /// use easy_tree::Tree;
352    ///
353    /// let mut tree = Tree::new();
354    /// let root = tree.add_node(42);
355    ///
356    /// // Safe use: The index is valid.
357    /// assert_eq!(tree.get_unchecked(root), &42);
358    ///
359    /// // Unsafe use: Accessing an invalid index would cause undefined behavior.
360    /// // let invalid = tree.get_unchecked(999); // Avoid this!
361    /// ```
362    #[inline(always)]
363    pub fn get_unchecked(&self, index: usize) -> &T {
364        &self.nodes[index].data
365    }
366
367    /// Retrieves a mutable reference to the data stored in a node.
368    ///
369    /// # Parameters
370    /// - `index`: The index of the node to access.
371    ///
372    /// # Returns
373    /// `Some(&mut T)` if the node exists, or `None` if the index is out of bounds.
374    ///
375    /// # Example
376    /// ```rust
377    /// use easy_tree::Tree;
378    ///
379    /// let mut tree = Tree::new();
380    /// let root = tree.add_node(42);
381    /// *tree.get_mut(root).unwrap() = 43;
382    /// assert_eq!(tree.get(root), Some(&43));
383    /// ```
384    pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
385        self.nodes.get_mut(index).map(|node| &mut node.data)
386    }
387
388    /// Retrieves a mutable reference to the data stored in a node without bounds checking.
389    ///
390    /// This method is faster than [`Tree::get_mut`] because it does not perform any bounds checking.
391    /// However, it is unsafe to use if the provided index is out of bounds or invalid.
392    ///
393    /// # Parameters
394    /// - `index`: The index of the node to access.
395    ///
396    /// # Returns
397    /// A mutable reference to the data stored in the node.
398    ///
399    /// # Safety
400    /// Ensure that:
401    /// - The `index` is within the valid range of node indices in the tree (0 to `Tree::len() - 1`).
402    /// - The node at the given index exists and has not been removed (if applicable).
403    /// - No other references to the same node are active during this call, to avoid data races or aliasing violations.
404    ///
405    /// # Example
406    /// ```rust
407    /// use easy_tree::Tree;
408    ///
409    /// let mut tree = Tree::new();
410    /// let root = tree.add_node(42);
411    ///
412    /// // Safe use: The index is valid.
413    /// *tree.get_unchecked_mut(root) = 99;
414    /// assert_eq!(tree.get_unchecked(root), &99);
415    ///
416    /// // Unsafe use: Accessing an invalid index would cause undefined behavior.
417    /// // let invalid = tree.get_unchecked_mut(999); // Avoid this!
418    /// ```
419    #[inline(always)]
420    pub fn get_unchecked_mut(&mut self, index: usize) -> &mut T {
421        &mut self.nodes[index].data
422    }
423
424    /// Returns the parent index of a node, if it has a parent.
425    ///
426    /// # Parameters
427    /// - `index`: The index of the node.
428    ///
429    /// # Returns
430    /// `Some(parent_index)` if the node has a parent, or `None` otherwise.
431    ///
432    /// # Panics
433    /// This method panics if the index is out of bounds.
434    ///
435    /// # Example
436    /// ```rust
437    /// use easy_tree::Tree;
438    ///
439    /// let mut tree = Tree::new();
440    /// let root = tree.add_node(42);
441    /// let child = tree.add_child(root, 99);
442    /// assert_eq!(tree.parent_index_unchecked(child), Some(root));
443    /// ```
444    pub fn parent_index_unchecked(&self, index: usize) -> Option<usize> {
445        self.nodes[index].parent
446    }
447
448    /// Returns a slice of the indices of the children of a node.
449    ///
450    /// # Parameters
451    /// - `index`: The index of the node.
452    ///
453    /// # Returns
454    /// A slice containing the indices of the node's children.
455    ///
456    /// # Panics
457    /// This method panics if the index is out of bounds.
458    ///
459    /// # Example
460    /// ```rust
461    /// use easy_tree::Tree;
462    ///
463    /// let mut tree = Tree::new();
464    /// let root = tree.add_node("root");
465    /// let child = tree.add_child(root, "child");
466    /// assert_eq!(tree.children(root), &[child]);
467    /// ```
468    pub fn children(&self, index: usize) -> &[usize] {
469        &self.nodes[index].children
470    }
471
472    /// Traverses the tree in a depth-first manner.
473    ///
474    /// The traversal applies two callbacks:
475    /// - `before_processing_children`: Called before processing the children of a node.
476    /// - `after_processing_the_subtree`: Called after processing all children of a node.
477    ///
478    /// # Parameters
479    /// - `before_processing_children`: A function to apply before visiting children.
480    /// - `after_processing_the_subtree`: A function to apply after visiting children.
481    /// - `state`: Mutable state to share across callbacks.
482    ///
483    /// # Example
484    /// ```rust
485    /// use easy_tree::Tree;
486    ///
487    /// let mut tree = Tree::new();
488    /// let root = tree.add_node("root");
489    /// let child = tree.add_child(root, "child");
490    ///
491    /// let mut log = vec![];
492    /// tree.traverse(
493    ///     |idx, data, log| log.push(format!("Entering node {}: {}", idx, data)),
494    ///     |idx, data, log| log.push(format!("Leaving node {}: {}", idx, data)),
495    ///     &mut log,
496    /// );
497    /// ```
498    pub fn traverse<'a, S>(
499        &'a self,
500        mut before_processing_children: impl FnMut(usize, &'a T, &mut S),
501        mut after_processing_the_subtree: impl FnMut(usize, &'a T, &mut S),
502        s: &mut S,
503    ) {
504        if self.is_empty() {
505            return;
506        }
507
508        let mut stack = vec![(0, false)];
509
510        while let Some((index, children_visited)) = stack.pop() {
511            if children_visited {
512                // All children are processed, call f2
513                let node = &self.nodes[index];
514                after_processing_the_subtree(index, &node.data, s);
515            } else {
516                // Call f and mark this node's children for processing
517                let node = &self.nodes[index];
518                before_processing_children(index, &node.data, s);
519
520                // Re-push the current node with children_visited set to true
521                stack.push((index, true));
522
523                // Push all children onto the stack
524                for &child in node.children.iter().rev() {
525                    stack.push((child, false));
526                }
527            }
528        }
529    }
530
531    /// Walks the tree recursively, applying the given functions before and after processing the
532    /// children of each node. This version allows for mutable access to the nodes.
533    pub fn traverse_mut<S>(
534        &mut self,
535        mut before_processing_children: impl FnMut(usize, &mut T, &mut S),
536        mut after_processing_the_subtree: impl FnMut(usize, &mut T, &mut S),
537        s: &mut S,
538    ) {
539        if self.is_empty() {
540            return;
541        }
542
543        self.stack.clear();
544        self.stack.push((0, false));
545
546        while let Some((index, children_visited)) = self.stack.pop() {
547            if children_visited {
548                // All children are processed, call f2
549                let node = &mut self.nodes[index];
550                after_processing_the_subtree(index, &mut node.data, s);
551            } else {
552                // Call f and mark this node's children for processing
553                let node = &mut self.nodes[index];
554                before_processing_children(index, &mut node.data, s);
555
556                // Re-push the current node with children_visited set to true
557                self.stack.push((index, true));
558
559                // Push all children onto the stack
560                for &child in node.children.iter().rev() {
561                    self.stack.push((child, false));
562                }
563            }
564        }
565    }
566
567    /// Returns an iterator over the indices and data of the nodes in the tree.
568    pub fn iter(&self) -> impl Iterator<Item = (usize, &T)> {
569        self.nodes
570            .iter()
571            .enumerate()
572            .map(|(index, node)| (index, &node.data))
573    }
574
575    /// Returns a mutable iterator over the indices and data of the nodes in the tree.
576    pub fn iter_mut(&mut self) -> impl Iterator<Item = (usize, &mut T)> {
577        self.nodes
578            .iter_mut()
579            .enumerate()
580            .map(|(index, node)| (index, &mut node.data))
581    }
582
583    /// Returns `true` if the tree contains no nodes.
584    pub fn is_empty(&self) -> bool {
585        self.nodes.is_empty()
586    }
587
588    /// Returns the number of nodes in the tree.
589    pub fn len(&self) -> usize {
590        self.nodes.len()
591    }
592
593    /// Removes all nodes from the tree.
594    pub fn clear(&mut self) {
595        self.nodes.clear();
596    }
597}
598
599#[cfg(feature = "rayon")]
600impl<T: Send + Sync> Tree<T> {
601    #[cfg(feature = "rayon")]
602    /// Returns a parallel iterator over the indices and data of the nodes in the tree.
603    pub fn par_iter(&self) -> impl ParallelIterator<Item = (usize, &T)> {
604        self.nodes
605            .par_iter()
606            .enumerate()
607            .map(|(index, node)| (index, &node.data))
608    }
609
610    #[cfg(feature = "rayon")]
611    /// Returns a mutable parallel iterator over the indices and data of the nodes in the tree.
612    pub fn par_iter_mut(&mut self) -> impl ParallelIterator<Item = (usize, &mut T)> {
613        self.nodes
614            .par_iter_mut()
615            .enumerate()
616            .map(|(index, node)| (index, &mut node.data))
617    }
618}
619
620#[cfg(test)]
621mod tests {
622    use super::*;
623
624    #[test]
625    fn test_tree() {
626        let mut tree = Tree::new();
627        let root = tree.add_node(0);
628        let child1 = tree.add_child(root, 1);
629        let child2 = tree.add_child(root, 2);
630        let child3 = tree.add_child(child1, 3);
631
632        assert_eq!(tree.get(root), Some(&0));
633        assert_eq!(tree.get(child1), Some(&1));
634        assert_eq!(tree.get(child2), Some(&2));
635        assert_eq!(tree.get(child3), Some(&3));
636
637        assert_eq!(tree.parent_index_unchecked(child1), Some(root));
638        assert_eq!(tree.parent_index_unchecked(child2), Some(root));
639        assert_eq!(tree.parent_index_unchecked(child3), Some(child1));
640
641        assert_eq!(tree.children(root), &[child1, child2]);
642        assert_eq!(tree.children(child1), &[child3]);
643        assert_eq!(tree.children(child2), &[]);
644        assert_eq!(tree.children(child3), &[]);
645    }
646
647    #[test]
648    fn test_tree_iter() {
649        let mut tree = Tree::new();
650        let root = tree.add_node(0);
651        let child1 = tree.add_child(root, 1);
652        let child2 = tree.add_child(root, 2);
653        let child3 = tree.add_child(child1, 3);
654
655        let mut iter = tree.iter();
656        assert_eq!(iter.next(), Some((root, &0)));
657        assert_eq!(iter.next(), Some((child1, &1)));
658        assert_eq!(iter.next(), Some((child2, &2)));
659        assert_eq!(iter.next(), Some((child3, &3)));
660        assert_eq!(iter.next(), None);
661    }
662
663    #[test]
664    fn test_tree_iter_mut() {
665        let mut tree = Tree::new();
666        let root = tree.add_node(0);
667        let child1 = tree.add_child(root, 1);
668        let child2 = tree.add_child(root, 2);
669        let child3 = tree.add_child(child1, 3);
670
671        let mut iter = tree.iter_mut();
672        assert_eq!(iter.next(), Some((root, &mut 0)));
673        assert_eq!(iter.next(), Some((child1, &mut 1)));
674        assert_eq!(iter.next(), Some((child2, &mut 2)));
675        assert_eq!(iter.next(), Some((child3, &mut 3)));
676        assert_eq!(iter.next(), None);
677    }
678
679    #[test]
680    fn test_tree_traverse() {
681        let mut tree = Tree::new();
682        let root = tree.add_node(0); // Root node with data 0
683        let child1 = tree.add_child(root, 1); // Child node with data 1
684        let _child2 = tree.add_child(root, 2); // Child node with data 2
685        let _child3 = tree.add_child(child1, 3); // Child node with data 3
686
687        let mut result = vec![];
688
689        tree.traverse(
690            |index, node, result| result.push(format!("Calling handler for node {index}: {node}")),
691            |index, _node, result| {
692                result.push(format!(
693                    "Finished handling node {index} and all its children"
694                ))
695            },
696            &mut result,
697        );
698
699        assert_eq!(
700            result,
701            vec![
702                "Calling handler for node 0: 0",
703                "Calling handler for node 1: 1",
704                "Calling handler for node 3: 3",
705                "Finished handling node 3 and all its children",
706                "Finished handling node 1 and all its children",
707                "Calling handler for node 2: 2",
708                "Finished handling node 2 and all its children",
709                "Finished handling node 0 and all its children",
710            ]
711        );
712    }
713}