1use super::{RecordId, RecordTree, TreeRecord};
4
5pub struct TreeWalker<'a, R> {
9 tree: &'a RecordTree<R>,
10 stack: Vec<(RecordId, usize)>,
12}
13
14impl<'a, R: TreeRecord> TreeWalker<'a, R> {
15 pub fn new(tree: &'a RecordTree<R>) -> Self {
17 let stack = tree.roots.iter().rev().map(|&id| (id, 0)).collect();
19
20 TreeWalker { tree, stack }
21 }
22
23 pub fn from_node(tree: &'a RecordTree<R>, start: RecordId) -> Self {
25 let depth = tree.depth(start);
26 TreeWalker {
27 tree,
28 stack: vec![(start, depth)],
29 }
30 }
31}
32
33impl<'a, R: TreeRecord> Iterator for TreeWalker<'a, R> {
34 type Item = (RecordId, &'a R, usize);
35
36 fn next(&mut self) -> Option<Self::Item> {
37 let (id, depth) = self.stack.pop()?;
38
39 let record = self.tree.get(id)?;
41
42 if let Some(children) = self.tree.children.get(&id) {
44 for &child_id in children.iter().rev() {
45 self.stack.push((child_id, depth + 1));
46 }
47 }
48
49 Some((id, record, depth))
50 }
51}
52
53pub struct BreadthFirstWalker<'a, R> {
57 tree: &'a RecordTree<R>,
58 queue: std::collections::VecDeque<(RecordId, usize)>,
60}
61
62impl<'a, R: TreeRecord> BreadthFirstWalker<'a, R> {
63 pub fn new(tree: &'a RecordTree<R>) -> Self {
65 let queue = tree.roots.iter().map(|&id| (id, 0)).collect();
66
67 BreadthFirstWalker { tree, queue }
68 }
69
70 pub fn from_node(tree: &'a RecordTree<R>, start: RecordId) -> Self {
72 let depth = tree.depth(start);
73 let mut queue = std::collections::VecDeque::new();
74 queue.push_back((start, depth));
75 BreadthFirstWalker { tree, queue }
76 }
77}
78
79impl<'a, R: TreeRecord> Iterator for BreadthFirstWalker<'a, R> {
80 type Item = (RecordId, &'a R, usize);
81
82 fn next(&mut self) -> Option<Self::Item> {
83 let (id, depth) = self.queue.pop_front()?;
84
85 let record = self.tree.get(id)?;
87
88 if let Some(children) = self.tree.children.get(&id) {
90 for &child_id in children.iter() {
91 self.queue.push_back((child_id, depth + 1));
92 }
93 }
94
95 Some((id, record, depth))
96 }
97}
98
99#[cfg(test)]
100mod tests {
101 use super::*;
102
103 #[derive(Debug, Clone, Default)]
104 struct TestRecord {
105 owner_index: i32,
106 name: String,
107 }
108
109 impl TreeRecord for TestRecord {
110 fn owner_index(&self) -> i32 {
111 self.owner_index
112 }
113
114 fn set_owner_index(&mut self, index: i32) {
115 self.owner_index = index;
116 }
117 }
118
119 #[test]
120 fn test_depth_first_walk() {
121 let records = vec![
127 TestRecord {
128 owner_index: -1,
129 name: "root".to_string(),
130 },
131 TestRecord {
132 owner_index: 0,
133 name: "child1".to_string(),
134 },
135 TestRecord {
136 owner_index: 0,
137 name: "child2".to_string(),
138 },
139 TestRecord {
140 owner_index: 1,
141 name: "grandchild".to_string(),
142 },
143 ];
144
145 let tree = RecordTree::from_records(records);
146 let walked: Vec<_> = tree
147 .walk_depth_first()
148 .map(|(_, r, d)| (r.name.clone(), d))
149 .collect();
150
151 assert_eq!(
153 walked,
154 vec![
155 ("root".to_string(), 0),
156 ("child1".to_string(), 1),
157 ("grandchild".to_string(), 2),
158 ("child2".to_string(), 1),
159 ]
160 );
161 }
162
163 #[test]
164 fn test_breadth_first_walk() {
165 let records = vec![
166 TestRecord {
167 owner_index: -1,
168 name: "root".to_string(),
169 },
170 TestRecord {
171 owner_index: 0,
172 name: "child1".to_string(),
173 },
174 TestRecord {
175 owner_index: 0,
176 name: "child2".to_string(),
177 },
178 TestRecord {
179 owner_index: 1,
180 name: "grandchild".to_string(),
181 },
182 ];
183
184 let tree = RecordTree::from_records(records);
185 let walker = BreadthFirstWalker::new(&tree);
186 let walked: Vec<_> = walker.map(|(_, r, d)| (r.name.clone(), d)).collect();
187
188 assert_eq!(
190 walked,
191 vec![
192 ("root".to_string(), 0),
193 ("child1".to_string(), 1),
194 ("child2".to_string(), 1),
195 ("grandchild".to_string(), 2),
196 ]
197 );
198 }
199}