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}