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}