xtri/iter/leaves.rs
1use crate::tree::RadixNode;
2
3/// Iterator for traversing only the leaf nodes of a radix tree.
4///
5/// A leaf node is defined as a node that has a value but no children,
6/// representing the end of a key path with no further extensions.
7/// This iterator performs lazy traversal using a stack-based approach.
8/// Memory usage is O(tree depth) storing only node references and child indices.
9pub struct LeavesIterator<'a, T> {
10 // Stack of (node, child_index, current_key) pairs for traversal state
11 stack: Vec<(&'a RadixNode<T>, usize, Vec<u8>)>,
12}
13
14impl<'a, T> LeavesIterator<'a, T> {
15 pub(crate) fn new(root: &'a RadixNode<T>) -> Self {
16 let mut iterator = Self { stack: Vec::new() };
17
18 // Start traversal from the root with empty key
19 iterator.stack.push((root, 0, Vec::new()));
20 iterator
21 }
22}
23
24impl<'a, T> Iterator for LeavesIterator<'a, T> {
25 type Item = (Vec<u8>, &'a T);
26
27 fn next(&mut self) -> Option<Self::Item> {
28 loop {
29 let (node, child_index, current_key) = self.stack.pop()?;
30
31 // If this is the first visit to this node (child_index == 0), check if it's a leaf
32 if child_index == 0 {
33 // A leaf node has a value and no children
34 if let Some(ref value) = node.value {
35 if node.children.is_empty() {
36 // This is a leaf node - return it
37 return Some((current_key.clone(), value));
38 }
39 }
40
41 // Not a leaf or no value, start processing children
42 if !node.children.is_empty() {
43 self.stack.push((node, 1, current_key));
44 }
45 continue;
46 }
47
48 // Processing children: child_index - 1 is the current child being processed
49 let current_child_idx = child_index - 1;
50
51 if current_child_idx < node.children.len() {
52 // Push the next child index for this node
53 if current_child_idx + 1 < node.children.len() {
54 self.stack
55 .push((node, child_index + 1, current_key.clone()));
56 }
57
58 // Push the current child to be processed
59 let (_, child) = &node.children[current_child_idx];
60 let mut child_key = current_key;
61 child_key.extend_from_slice(&child.key);
62
63 self.stack.push((child, 0, child_key));
64 }
65 }
66 }
67}