syntree/node/walk_events.rs
1use core::iter::FusedIterator;
2
3use crate::flavor::Flavor;
4use crate::links::Links;
5use crate::node::Node;
6use crate::pointer::Pointer;
7
8/// An event indicating how a tree is being walked with [`WalkEvents`].
9///
10/// See [`WalkEvents`] for documentation.
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
12pub enum Event {
13 /// Walk the next sibling node. This is also the initial event being emitted
14 /// when entering the iterator.
15 Next,
16 /// Walk down the first child of a sub tree.
17 Down,
18 /// Walk up a single step from a sub tree.
19 Up,
20}
21
22/// A low-level iterator which walks the tree while emitting [Event] instances
23/// indicating *how* the structure is being navigated.
24///
25/// See [`Tree::walk_events`][crate::Tree::walk_events] or
26/// [`Node::walk_events`][crate::Node::walk_events].
27///
28/// # Examples
29///
30/// ```
31/// use syntree::node::Event::*;
32///
33/// let tree = syntree::tree! {
34/// "root" => {
35/// "c1" => {
36/// "c2" => {},
37/// "c3" => {},
38/// "c4" => {},
39/// },
40/// "c5" => {},
41/// "c6" => {}
42/// }
43/// };
44///
45/// assert_eq!(
46/// tree.walk_events().map(|(e, n)| (e, n.value())).collect::<Vec<_>>(),
47/// [
48/// (Next, "root"),
49/// (Down, "c1"),
50/// (Down, "c2"),
51/// (Next, "c3"),
52/// (Next, "c4"),
53/// (Up, "c1"),
54/// (Next, "c5"),
55/// (Next, "c6"),
56/// (Up, "root")
57/// ]
58/// );
59///
60/// let root = tree.first().ok_or("missing root")?;
61///
62/// assert_eq!(
63/// root.walk_events().map(|(e, n)| (e, n.value())).collect::<Vec<_>>(),
64/// [
65/// (Next, "root"),
66/// (Down, "c1"),
67/// (Down, "c2"),
68/// (Next, "c3"),
69/// (Next, "c4"),
70/// (Up, "c1"),
71/// (Next, "c5"),
72/// (Next, "c6"),
73/// (Up, "root"),
74/// ]
75/// );
76///
77/// let c1 = root.first().ok_or("missing c1")?;
78///
79/// assert_eq!(
80/// c1.walk_events().map(|(e, n)| (e, n.value())).collect::<Vec<_>>(),
81/// [
82/// (Next, "c1"),
83/// (Down, "c2"),
84/// (Next, "c3"),
85/// (Next, "c4"),
86/// (Up, "c1"),
87/// (Next, "c5"),
88/// (Next, "c6"),
89/// (Up, "root"),
90/// ]
91/// );
92/// # Ok::<_, Box<dyn core::error::Error>>(())
93/// ```
94///
95/// Example showcasing how we can use events to keep track of the depth in which
96/// nodes are being traversed:
97///
98/// ```
99/// use syntree::node::Event::*;
100///
101/// let tree = syntree::tree! {
102/// "root" => {
103/// "c1" => {
104/// "c2" => {},
105/// "c3" => {},
106/// }
107/// }
108/// };
109///
110/// let mut it = tree.walk_events();
111/// let mut depth = 0;
112///
113/// let mut nodes = Vec::new();
114///
115/// while let Some((event, node)) = it.next() {
116/// // Only register each node once.
117/// match event {
118/// Up => {
119/// depth -= 1;
120/// }
121/// Down => {
122/// depth += 1;
123/// nodes.push((depth, node.value()));
124/// }
125/// Next => {
126/// nodes.push((depth, node.value()));
127/// }
128/// }
129/// }
130///
131/// assert_eq!(depth, 0);
132///
133/// assert_eq!(
134/// nodes,
135/// [(0, "root"), (1, "c1"), (2, "c2"), (2, "c3")]
136/// );
137/// # Ok::<_, Box<dyn core::error::Error>>(())
138/// ```
139pub struct WalkEvents<'a, T, F>
140where
141 T: Copy,
142 F: Flavor,
143{
144 /// The tree being iterated over.
145 tree: &'a [Links<T, F::Index, F::Pointer>],
146 // The current node.
147 node: Option<(F::Pointer, Event)>,
148 // Current depth being walked.
149 depth: isize,
150}
151
152impl<'a, T, F> WalkEvents<'a, T, F>
153where
154 T: Copy,
155 F: Flavor,
156{
157 /// Construct a new events walker.
158 #[inline]
159 pub(crate) fn new(
160 tree: &'a [Links<T, F::Index, F::Pointer>],
161 node: Option<F::Pointer>,
162 e: Event,
163 ) -> Self {
164 Self {
165 tree,
166 node: node.map(|n| (n, e)),
167 depth: 0,
168 }
169 }
170
171 /// Get current depth.
172 #[inline]
173 pub(crate) const fn depth(&self) -> isize {
174 self.depth
175 }
176
177 fn step(
178 &mut self,
179 links: &Links<T, F::Index, F::Pointer>,
180 event: Event,
181 ) -> Option<(F::Pointer, Event)> {
182 if let Event::Up = event {
183 if let Some(next) = links.next {
184 return Some((next, Event::Next));
185 }
186 } else {
187 if let Some(first) = links.first {
188 self.depth = self.depth.checked_add(1)?;
189 return Some((first, Event::Down));
190 }
191
192 if let Some(next) = links.next {
193 return Some((next, Event::Next));
194 }
195 }
196
197 self.depth = self.depth.checked_sub(1)?;
198 Some((links.parent?, Event::Up))
199 }
200}
201
202impl<T, F> Clone for WalkEvents<'_, T, F>
203where
204 T: Copy,
205 F: Flavor,
206{
207 #[inline]
208 fn clone(&self) -> Self {
209 Self {
210 tree: self.tree,
211 node: self.node,
212 depth: self.depth,
213 }
214 }
215}
216
217impl<T, F> Default for WalkEvents<'_, T, F>
218where
219 T: Copy,
220 F: Flavor,
221{
222 #[inline]
223 fn default() -> Self {
224 Self {
225 tree: &[],
226 node: None,
227 depth: 0,
228 }
229 }
230}
231
232impl<'a, T, F> Iterator for WalkEvents<'a, T, F>
233where
234 T: Copy,
235 F: Flavor,
236{
237 type Item = (Event, Node<'a, T, F>);
238
239 fn next(&mut self) -> Option<Self::Item> {
240 let (node, event) = self.node.take()?;
241 let links = self.tree.get(node.get())?;
242 self.node = self.step(links, event);
243 let node = Node::new(links, self.tree);
244 Some((event, node))
245 }
246}
247
248impl<T, F> FusedIterator for WalkEvents<'_, T, F>
249where
250 T: Copy,
251 F: Flavor,
252{
253}