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<Option<Node<T>>>,
216 /// Indices of removed nodes available for reuse.
217 free_list: Vec<usize>,
218 /// Number of live (non-removed) nodes.
219 node_count: usize,
220 /// Stack for traverse_mut to avoid allocations
221 stack: Vec<(usize, bool)>,
222}
223
224impl<T> Default for Tree<T> {
225 fn default() -> Self {
226 Self::new()
227 }
228}
229
230impl<T> Tree<T> {
231 /// Creates a new, empty tree.
232 ///
233 /// # Returns
234 /// A `Tree` instance with no nodes.
235 ///
236 /// # Example
237 /// ```rust
238 /// use easy_tree::Tree;
239 ///
240 /// let tree: Tree<i32> = Tree::new();
241 /// ```
242 pub fn new() -> Self {
243 Self {
244 nodes: Vec::new(),
245 free_list: Vec::new(),
246 node_count: 0,
247 stack: Vec::new(),
248 }
249 }
250
251 /// Adds a new node to the tree.
252 ///
253 /// This method is typically used to add a root node or a disconnected node.
254 ///
255 /// # Parameters
256 /// - `data`: The data to associate with the new node.
257 ///
258 /// # Returns
259 /// The index of the newly added node.
260 ///
261 /// # Example
262 /// ```rust
263 /// use easy_tree::Tree;
264 ///
265 /// let mut tree = Tree::new();
266 /// let root = tree.add_node("root");
267 /// ```
268 pub fn add_node(&mut self, data: T) -> usize {
269 let node = Node::new(data);
270 self.node_count += 1;
271 if let Some(index) = self.free_list.pop() {
272 self.nodes[index] = Some(node);
273 index
274 } else {
275 let index = self.nodes.len();
276 self.nodes.push(Some(node));
277 index
278 }
279 }
280
281 /// Adds a child node to an existing node in the tree.
282 ///
283 /// # Parameters
284 /// - `parent`: The index of the parent node.
285 /// - `data`: The data to associate with the new child node.
286 ///
287 /// # Returns
288 /// The index of the newly added child node.
289 ///
290 /// # Example
291 /// ```rust
292 /// use easy_tree::Tree;
293 ///
294 /// let mut tree = Tree::new();
295 /// let root = tree.add_node("root");
296 /// let child = tree.add_child(root, "child");
297 /// ```
298 pub fn add_child(&mut self, parent: usize, data: T) -> usize {
299 let index = self.add_node(data);
300 self.nodes[parent].as_mut().unwrap().add_child(index);
301 self.nodes[index].as_mut().unwrap().set_parent(parent);
302 index
303 }
304
305 /// Adds a child node to the tree root.
306 ///
307 /// # Parameters
308 /// - `data`: The data to associate with the new child node.
309 ///
310 /// # Returns
311 /// The index of the newly added child node.
312 ///
313 /// # Example
314 /// ```rust
315 /// use easy_tree::Tree;
316 ///
317 /// let mut tree = Tree::new();
318 /// let root = tree.add_node("root");
319 /// let child = tree.add_child_to_root("child");
320 /// ```
321 pub fn add_child_to_root(&mut self, data: T) -> usize {
322 self.add_child(0, data)
323 }
324
325 /// Retrieves a reference to the data stored in a node.
326 ///
327 /// # Parameters
328 /// - `index`: The index of the node to access.
329 ///
330 /// # Returns
331 /// `Some(&T)` if the node exists, or `None` if the index is out of bounds.
332 ///
333 /// # Example
334 /// ```rust
335 /// use easy_tree::Tree;
336 ///
337 /// let mut tree = Tree::new();
338 /// let root = tree.add_node(42);
339 /// assert_eq!(tree.get(root), Some(&42));
340 /// ```
341 pub fn get(&self, index: usize) -> Option<&T> {
342 self.nodes
343 .get(index)
344 .and_then(|slot| slot.as_ref().map(|node| &node.data))
345 }
346
347 /// Retrieves a reference to the data stored in a node without bounds checking.
348 ///
349 /// This method is faster than [`Tree::get`] because it does not perform any bounds checking.
350 /// However, it is unsafe to use if the provided index is out of bounds or invalid.
351 ///
352 /// # Parameters
353 /// - `index`: The index of the node to access.
354 ///
355 /// # Returns
356 /// A reference to the data stored in the node.
357 ///
358 /// # Safety
359 /// Ensure that:
360 /// - The `index` is within the valid range of node indices in the tree (0 to `Tree::len() - 1`).
361 /// - The node at the given index exists and has not been removed (if applicable).
362 ///
363 /// # Example
364 /// ```rust
365 /// use easy_tree::Tree;
366 ///
367 /// let mut tree = Tree::new();
368 /// let root = tree.add_node(42);
369 ///
370 /// // Safe use: The index is valid.
371 /// assert_eq!(tree.get_unchecked(root), &42);
372 ///
373 /// // Unsafe use: Accessing an invalid index would cause undefined behavior.
374 /// // let invalid = tree.get_unchecked(999); // Avoid this!
375 /// ```
376 #[inline(always)]
377 pub fn get_unchecked(&self, index: usize) -> &T {
378 &self.nodes[index].as_ref().unwrap().data
379 }
380
381 /// Retrieves a mutable reference to the data stored in a node.
382 ///
383 /// # Parameters
384 /// - `index`: The index of the node to access.
385 ///
386 /// # Returns
387 /// `Some(&mut T)` if the node exists, or `None` if the index is out of bounds.
388 ///
389 /// # Example
390 /// ```rust
391 /// use easy_tree::Tree;
392 ///
393 /// let mut tree = Tree::new();
394 /// let root = tree.add_node(42);
395 /// *tree.get_mut(root).unwrap() = 43;
396 /// assert_eq!(tree.get(root), Some(&43));
397 /// ```
398 pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
399 self.nodes
400 .get_mut(index)
401 .and_then(|slot| slot.as_mut().map(|node| &mut node.data))
402 }
403
404 /// Retrieves a mutable reference to the data stored in a node without bounds checking.
405 ///
406 /// This method is faster than [`Tree::get_mut`] because it does not perform any bounds checking.
407 /// However, it is unsafe to use if the provided index is out of bounds or invalid.
408 ///
409 /// # Parameters
410 /// - `index`: The index of the node to access.
411 ///
412 /// # Returns
413 /// A mutable reference to the data stored in the node.
414 ///
415 /// # Safety
416 /// Ensure that:
417 /// - The `index` is within the valid range of node indices in the tree (0 to `Tree::len() - 1`).
418 /// - The node at the given index exists and has not been removed (if applicable).
419 /// - No other references to the same node are active during this call, to avoid data races or aliasing violations.
420 ///
421 /// # Example
422 /// ```rust
423 /// use easy_tree::Tree;
424 ///
425 /// let mut tree = Tree::new();
426 /// let root = tree.add_node(42);
427 ///
428 /// // Safe use: The index is valid.
429 /// *tree.get_unchecked_mut(root) = 99;
430 /// assert_eq!(tree.get_unchecked(root), &99);
431 ///
432 /// // Unsafe use: Accessing an invalid index would cause undefined behavior.
433 /// // let invalid = tree.get_unchecked_mut(999); // Avoid this!
434 /// ```
435 #[inline(always)]
436 pub fn get_unchecked_mut(&mut self, index: usize) -> &mut T {
437 &mut self.nodes[index].as_mut().unwrap().data
438 }
439
440 /// Returns the parent index of a node, if it has a parent.
441 ///
442 /// # Parameters
443 /// - `index`: The index of the node.
444 ///
445 /// # Returns
446 /// `Some(parent_index)` if the node has a parent, or `None` otherwise.
447 ///
448 /// # Panics
449 /// This method panics if the index is out of bounds.
450 ///
451 /// # Example
452 /// ```rust
453 /// use easy_tree::Tree;
454 ///
455 /// let mut tree = Tree::new();
456 /// let root = tree.add_node(42);
457 /// let child = tree.add_child(root, 99);
458 /// assert_eq!(tree.parent_index_unchecked(child), Some(root));
459 /// ```
460 pub fn parent_index_unchecked(&self, index: usize) -> Option<usize> {
461 self.nodes[index].as_ref().unwrap().parent
462 }
463
464 /// Returns a slice of the indices of the children of a node.
465 ///
466 /// # Parameters
467 /// - `index`: The index of the node.
468 ///
469 /// # Returns
470 /// A slice containing the indices of the node's children.
471 ///
472 /// # Panics
473 /// This method panics if the index is out of bounds.
474 ///
475 /// # Example
476 /// ```rust
477 /// use easy_tree::Tree;
478 ///
479 /// let mut tree = Tree::new();
480 /// let root = tree.add_node("root");
481 /// let child = tree.add_child(root, "child");
482 /// assert_eq!(tree.children(root), &[child]);
483 /// ```
484 pub fn children(&self, index: usize) -> &[usize] {
485 &self.nodes[index].as_ref().unwrap().children
486 }
487
488 /// Traverses the tree in a depth-first manner.
489 ///
490 /// The traversal applies two callbacks:
491 /// - `before_processing_children`: Called before processing the children of a node.
492 /// - `after_processing_the_subtree`: Called after processing all children of a node.
493 ///
494 /// # Parameters
495 /// - `before_processing_children`: A function to apply before visiting children.
496 /// - `after_processing_the_subtree`: A function to apply after visiting children.
497 /// - `state`: Mutable state to share across callbacks.
498 ///
499 /// # Example
500 /// ```rust
501 /// use easy_tree::Tree;
502 ///
503 /// let mut tree = Tree::new();
504 /// let root = tree.add_node("root");
505 /// let child = tree.add_child(root, "child");
506 ///
507 /// let mut log = vec![];
508 /// tree.traverse(
509 /// |idx, data, log| log.push(format!("Entering node {}: {}", idx, data)),
510 /// |idx, data, log| log.push(format!("Leaving node {}: {}", idx, data)),
511 /// &mut log,
512 /// );
513 /// ```
514 pub fn traverse<'a, S>(
515 &'a self,
516 mut before_processing_children: impl FnMut(usize, &'a T, &mut S),
517 mut after_processing_the_subtree: impl FnMut(usize, &'a T, &mut S),
518 s: &mut S,
519 ) {
520 if !matches!(self.nodes.first(), Some(Some(_))) {
521 return;
522 }
523
524 let mut stack = vec![(0, false)];
525
526 while let Some((index, children_visited)) = stack.pop() {
527 let node = self.nodes[index].as_ref().unwrap();
528 if children_visited {
529 // All children are processed, call f2
530 after_processing_the_subtree(index, &node.data, s);
531 } else {
532 // Call f and mark this node's children for processing
533 before_processing_children(index, &node.data, s);
534
535 // Re-push the current node with children_visited set to true
536 stack.push((index, true));
537
538 // Push all children onto the stack
539 for &child in node.children.iter().rev() {
540 stack.push((child, false));
541 }
542 }
543 }
544 }
545
546 /// Walks the tree recursively, applying the given functions before and after processing the
547 /// children of each node. This version allows for mutable access to the nodes.
548 pub fn traverse_mut<S>(
549 &mut self,
550 mut before_processing_children: impl FnMut(usize, &mut T, &mut S),
551 mut after_processing_the_subtree: impl FnMut(usize, &mut T, &mut S),
552 s: &mut S,
553 ) {
554 if matches!(self.nodes.first(), Some(Some(_))) {
555 self.traverse_subtree_mut(
556 0,
557 &mut before_processing_children,
558 &mut after_processing_the_subtree,
559 s,
560 );
561 }
562 }
563
564 /// Walks the tree recursively starting from a specific node, applying the given functions
565 /// before and after processing the children of each node. This version allows for mutable
566 /// access to the nodes.
567 pub fn traverse_subtree_mut<S>(
568 &mut self,
569 start: usize,
570 mut before_processing_children: impl FnMut(usize, &mut T, &mut S),
571 mut after_processing_the_subtree: impl FnMut(usize, &mut T, &mut S),
572 s: &mut S,
573 ) {
574 if self.is_empty() || self.nodes.get(start).and_then(|n| n.as_ref()).is_none() {
575 return;
576 }
577
578 self.stack.clear();
579 self.stack.push((start, false));
580
581 while let Some((index, children_visited)) = self.stack.pop() {
582 if children_visited {
583 // All children are processed, call f2
584 let node = self.nodes[index].as_mut().unwrap();
585 after_processing_the_subtree(index, &mut node.data, s);
586 } else {
587 // Call f and mark this node's children for processing
588 let node = self.nodes[index].as_mut().unwrap();
589 before_processing_children(index, &mut node.data, s);
590
591 // Re-push the current node with children_visited set to true
592 self.stack.push((index, true));
593
594 // Push all children onto the stack
595 for &child in node.children.iter().rev() {
596 self.stack.push((child, false));
597 }
598 }
599 }
600 }
601
602 /// Returns an iterator over the indices and data of the nodes in the tree.
603 pub fn iter(&self) -> impl Iterator<Item = (usize, &T)> {
604 self.nodes
605 .iter()
606 .enumerate()
607 .filter_map(|(index, slot)| slot.as_ref().map(|node| (index, &node.data)))
608 }
609
610 /// Returns a mutable iterator over the indices and data of the nodes in the tree.
611 pub fn iter_mut(&mut self) -> impl Iterator<Item = (usize, &mut T)> {
612 self.nodes
613 .iter_mut()
614 .enumerate()
615 .filter_map(|(index, slot)| slot.as_mut().map(|node| (index, &mut node.data)))
616 }
617
618 /// Returns `true` if the tree contains no nodes.
619 pub fn is_empty(&self) -> bool {
620 self.node_count == 0
621 }
622
623 /// Returns the number of nodes in the tree.
624 pub fn len(&self) -> usize {
625 self.node_count
626 }
627
628 /// Removes all nodes from the tree.
629 pub fn clear(&mut self) {
630 self.nodes.clear();
631 self.free_list.clear();
632 self.node_count = 0;
633 }
634
635 /// Removes a node and all of its descendants from the tree.
636 ///
637 /// The removed node is detached from its parent, and all indices occupied by the
638 /// removed nodes are added to an internal free list for reuse by future
639 /// [`add_node`](Tree::add_node) or [`add_child`](Tree::add_child) calls.
640 ///
641 /// If `index` is out of bounds or refers to a previously removed node, this method
642 /// is a no-op.
643 ///
644 /// # Parameters
645 /// - `index`: The index of the root of the subtree to remove.
646 ///
647 /// # Example
648 /// ```rust
649 /// use easy_tree::Tree;
650 ///
651 /// let mut tree = Tree::new();
652 /// let root = tree.add_node("root");
653 /// let child1 = tree.add_child(root, "child1");
654 /// let child2 = tree.add_child(root, "child2");
655 /// let grandchild = tree.add_child(child1, "grandchild");
656 ///
657 /// assert_eq!(tree.len(), 4);
658 ///
659 /// tree.remove_subtree(child1);
660 ///
661 /// assert_eq!(tree.len(), 2);
662 /// assert_eq!(tree.get(child1), None);
663 /// assert_eq!(tree.get(grandchild), None);
664 /// assert_eq!(tree.children(root), &[child2]);
665 /// ```
666 pub fn remove_subtree(&mut self, index: usize) {
667 if !matches!(self.nodes.get(index), Some(Some(_))) {
668 return;
669 }
670
671 // Detach from parent
672 if let Some(parent_idx) = self.nodes[index].as_ref().unwrap().parent {
673 if let Some(parent) = self.nodes[parent_idx].as_mut() {
674 parent.children.retain(|&child| child != index);
675 }
676 }
677
678 // Remove all nodes in the subtree via iterative DFS
679 let mut removal_stack = vec![index];
680 while let Some(current) = removal_stack.pop() {
681 if let Some(node) = self.nodes[current].take() {
682 removal_stack.extend(node.children);
683 self.free_list.push(current);
684 self.node_count -= 1;
685 }
686 }
687
688 // Reset storage when the tree becomes empty, so the next add_node
689 // starts fresh from index 0.
690 if self.node_count == 0 {
691 self.nodes.clear();
692 self.free_list.clear();
693 }
694 }
695}
696
697#[cfg(feature = "rayon")]
698impl<T: Send + Sync> Tree<T> {
699 #[cfg(feature = "rayon")]
700 /// Returns a parallel iterator over the indices and data of the nodes in the tree.
701 pub fn par_iter(&self) -> impl ParallelIterator<Item = (usize, &T)> {
702 self.nodes
703 .par_iter()
704 .enumerate()
705 .filter_map(|(index, slot)| slot.as_ref().map(|node| (index, &node.data)))
706 }
707
708 #[cfg(feature = "rayon")]
709 /// Returns a mutable parallel iterator over the indices and data of the nodes in the tree.
710 pub fn par_iter_mut(&mut self) -> impl ParallelIterator<Item = (usize, &mut T)> {
711 self.nodes
712 .par_iter_mut()
713 .enumerate()
714 .filter_map(|(index, slot)| slot.as_mut().map(|node| (index, &mut node.data)))
715 }
716}
717
718#[cfg(test)]
719mod tests {
720 use super::*;
721
722 #[test]
723 fn test_tree() {
724 let mut tree = Tree::new();
725 let root = tree.add_node(0);
726 let child1 = tree.add_child(root, 1);
727 let child2 = tree.add_child(root, 2);
728 let child3 = tree.add_child(child1, 3);
729
730 assert_eq!(tree.get(root), Some(&0));
731 assert_eq!(tree.get(child1), Some(&1));
732 assert_eq!(tree.get(child2), Some(&2));
733 assert_eq!(tree.get(child3), Some(&3));
734
735 assert_eq!(tree.parent_index_unchecked(child1), Some(root));
736 assert_eq!(tree.parent_index_unchecked(child2), Some(root));
737 assert_eq!(tree.parent_index_unchecked(child3), Some(child1));
738
739 assert_eq!(tree.children(root), &[child1, child2]);
740 assert_eq!(tree.children(child1), &[child3]);
741 assert_eq!(tree.children(child2), &[]);
742 assert_eq!(tree.children(child3), &[]);
743 }
744
745 #[test]
746 fn test_tree_iter() {
747 let mut tree = Tree::new();
748 let root = tree.add_node(0);
749 let child1 = tree.add_child(root, 1);
750 let child2 = tree.add_child(root, 2);
751 let child3 = tree.add_child(child1, 3);
752
753 let mut iter = tree.iter();
754 assert_eq!(iter.next(), Some((root, &0)));
755 assert_eq!(iter.next(), Some((child1, &1)));
756 assert_eq!(iter.next(), Some((child2, &2)));
757 assert_eq!(iter.next(), Some((child3, &3)));
758 assert_eq!(iter.next(), None);
759 }
760
761 #[test]
762 fn test_tree_iter_mut() {
763 let mut tree = Tree::new();
764 let root = tree.add_node(0);
765 let child1 = tree.add_child(root, 1);
766 let child2 = tree.add_child(root, 2);
767 let child3 = tree.add_child(child1, 3);
768
769 let mut iter = tree.iter_mut();
770 assert_eq!(iter.next(), Some((root, &mut 0)));
771 assert_eq!(iter.next(), Some((child1, &mut 1)));
772 assert_eq!(iter.next(), Some((child2, &mut 2)));
773 assert_eq!(iter.next(), Some((child3, &mut 3)));
774 assert_eq!(iter.next(), None);
775 }
776
777 #[test]
778 fn test_tree_traverse() {
779 let mut tree = Tree::new();
780 let root = tree.add_node(0); // Root node with data 0
781 let child1 = tree.add_child(root, 1); // Child node with data 1
782 let _child2 = tree.add_child(root, 2); // Child node with data 2
783 let _child3 = tree.add_child(child1, 3); // Child node with data 3
784
785 let mut result = vec![];
786
787 tree.traverse(
788 |index, node, result| result.push(format!("Calling handler for node {index}: {node}")),
789 |index, _node, result| {
790 result.push(format!(
791 "Finished handling node {index} and all its children"
792 ))
793 },
794 &mut result,
795 );
796
797 assert_eq!(
798 result,
799 vec![
800 "Calling handler for node 0: 0",
801 "Calling handler for node 1: 1",
802 "Calling handler for node 3: 3",
803 "Finished handling node 3 and all its children",
804 "Finished handling node 1 and all its children",
805 "Calling handler for node 2: 2",
806 "Finished handling node 2 and all its children",
807 "Finished handling node 0 and all its children",
808 ]
809 );
810 }
811
812 #[test]
813 fn test_remove_subtree() {
814 let mut tree = Tree::new();
815 let root = tree.add_node("root");
816 let child1 = tree.add_child(root, "child1");
817 let child2 = tree.add_child(root, "child2");
818 let grandchild1 = tree.add_child(child1, "grandchild1");
819 let _grandchild2 = tree.add_child(child1, "grandchild2");
820
821 assert_eq!(tree.len(), 5);
822
823 tree.remove_subtree(child1);
824
825 assert_eq!(tree.len(), 2);
826 assert_eq!(tree.get(root), Some(&"root"));
827 assert_eq!(tree.get(child1), None);
828 assert_eq!(tree.get(child2), Some(&"child2"));
829 assert_eq!(tree.get(grandchild1), None);
830 assert_eq!(tree.children(root), &[child2]);
831 }
832
833 #[test]
834 fn test_remove_leaf_node() {
835 let mut tree = Tree::new();
836 let root = tree.add_node("root");
837 let child1 = tree.add_child(root, "child1");
838 let child2 = tree.add_child(root, "child2");
839
840 tree.remove_subtree(child1);
841
842 assert_eq!(tree.len(), 2);
843 assert_eq!(tree.get(child1), None);
844 assert_eq!(tree.children(root), &[child2]);
845 }
846
847 #[test]
848 fn test_remove_root() {
849 let mut tree = Tree::new();
850 let root = tree.add_node("root");
851 tree.add_child(root, "child1");
852 tree.add_child(root, "child2");
853
854 tree.remove_subtree(root);
855
856 assert!(tree.is_empty());
857 assert_eq!(tree.len(), 0);
858 }
859
860 #[test]
861 fn test_remove_and_reuse() {
862 let mut tree = Tree::new();
863 let root = tree.add_node(0);
864 let child1 = tree.add_child(root, 1);
865 tree.add_child(root, 2);
866 tree.add_child(child1, 3);
867
868 // Remove child1 subtree (indices 1 and 3)
869 tree.remove_subtree(child1);
870
871 // Add new nodes — should reuse freed indices
872 let new_child = tree.add_child(root, 10);
873 assert!(new_child == 3 || new_child == 1);
874
875 assert_eq!(tree.len(), 3);
876 assert_eq!(tree.get(new_child), Some(&10));
877 }
878
879 #[test]
880 fn test_iter_after_remove() {
881 let mut tree = Tree::new();
882 let root = tree.add_node(0);
883 let child1 = tree.add_child(root, 1);
884 let child2 = tree.add_child(root, 2);
885 tree.add_child(child1, 3);
886
887 tree.remove_subtree(child1);
888
889 let items: Vec<_> = tree.iter().collect();
890 assert_eq!(items.len(), 2);
891 assert_eq!(items[0], (root, &0));
892 assert_eq!(items[1], (child2, &2));
893 }
894
895 #[test]
896 fn test_traverse_after_remove() {
897 let mut tree = Tree::new();
898 let root = tree.add_node(0);
899 let child1 = tree.add_child(root, 1);
900 tree.add_child(root, 2);
901 tree.add_child(child1, 3);
902
903 tree.remove_subtree(child1);
904
905 let mut result = vec![];
906 tree.traverse(
907 |idx, data, result: &mut Vec<String>| result.push(format!("enter {idx}:{data}")),
908 |idx, data, result: &mut Vec<String>| result.push(format!("leave {idx}:{data}")),
909 &mut result,
910 );
911
912 assert_eq!(
913 result,
914 vec!["enter 0:0", "enter 2:2", "leave 2:2", "leave 0:0",]
915 );
916 }
917
918 #[test]
919 fn test_traverse_after_removing_first_root() {
920 let mut tree = Tree::new();
921 let root0 = tree.add_node("root0");
922 let root1 = tree.add_node("root1");
923 tree.add_child(root1, "child");
924
925 tree.remove_subtree(root0);
926
927 let mut result = vec![];
928 tree.traverse(
929 |idx, data, result: &mut Vec<String>| result.push(format!("enter {idx}:{data}")),
930 |idx, data, result: &mut Vec<String>| result.push(format!("leave {idx}:{data}")),
931 &mut result,
932 );
933
934 assert!(result.is_empty());
935 }
936
937 #[test]
938 fn test_traverse_mut_after_removing_first_root() {
939 let mut tree = Tree::new();
940 let root0 = tree.add_node(0);
941 let root1 = tree.add_node(10);
942 let child = tree.add_child(root1, 20);
943
944 tree.remove_subtree(root0);
945
946 let mut visited = vec![];
947 tree.traverse_mut(
948 |idx, data, visited: &mut Vec<(usize, i32)>| {
949 *data += 1;
950 visited.push((idx, *data));
951 },
952 |_, _, _| {},
953 &mut visited,
954 );
955
956 assert!(visited.is_empty());
957 assert_eq!(tree.get(root1), Some(&10));
958 assert_eq!(tree.get(child), Some(&20));
959 }
960
961 #[test]
962 fn test_remove_idempotent() {
963 let mut tree = Tree::new();
964 let root = tree.add_node("root");
965 let child = tree.add_child(root, "child");
966
967 tree.remove_subtree(child);
968 tree.remove_subtree(child); // no-op
969
970 assert_eq!(tree.len(), 1);
971 }
972
973 #[test]
974 fn test_remove_out_of_bounds() {
975 let mut tree = Tree::new();
976 let root = tree.add_node("root");
977
978 tree.remove_subtree(999); // no-op
979
980 assert_eq!(tree.len(), 1);
981 assert_eq!(tree.get(root), Some(&"root"));
982 }
983
984 #[test]
985 fn test_add_after_remove_root() {
986 let mut tree = Tree::new();
987 let root = tree.add_node("root");
988 tree.add_child(root, "child");
989
990 tree.remove_subtree(root);
991 assert!(tree.is_empty());
992
993 // New root should start fresh at index 0
994 let new_root = tree.add_node("new_root");
995 assert_eq!(new_root, 0);
996 assert_eq!(tree.get(new_root), Some(&"new_root"));
997 assert_eq!(tree.len(), 1);
998 }
999}