syntree/node/walk_events.rs
1use core::fmt;
2use core::iter::FusedIterator;
3
4use crate::flavor::Flavor;
5use crate::links::Links;
6use crate::node::Node;
7use crate::pointer::Pointer;
8
9/// An event indicating how a tree is being walked with [`WalkEvents`].
10///
11/// See [`WalkEvents`] for documentation.
12#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
13pub enum Event {
14 /// Walk the next sibling node. This is also the initial event being emitted
15 /// when entering the iterator.
16 Next,
17 /// Walk down the first child of a sub tree.
18 Down,
19 /// Walk up a single step from a sub tree.
20 Up,
21}
22
23/// A low-level iterator which walks the tree while emitting [Event] instances
24/// indicating *how* the structure is being navigated.
25///
26/// See [`Tree::walk_events`][crate::Tree::walk_events] or
27/// [`Node::walk_events`][crate::Node::walk_events].
28///
29/// # Examples
30///
31/// ```
32/// use syntree::node::Event::*;
33///
34/// let tree = syntree::tree! {
35/// "root" => {
36/// "c1" => {
37/// "c2" => {},
38/// "c3" => {},
39/// "c4" => {},
40/// },
41/// "c5" => {},
42/// "c6" => {}
43/// }
44/// };
45///
46/// assert_eq!(
47/// tree.walk_events().map(|(e, n)| (e, n.value())).collect::<Vec<_>>(),
48/// [
49/// (Next, "root"),
50/// (Down, "c1"),
51/// (Down, "c2"),
52/// (Next, "c3"),
53/// (Next, "c4"),
54/// (Up, "c1"),
55/// (Next, "c5"),
56/// (Next, "c6"),
57/// (Up, "root")
58/// ]
59/// );
60///
61/// let root = tree.first().ok_or("missing root")?;
62///
63/// assert_eq!(
64/// root.walk_events().map(|(e, n)| (e, n.value())).collect::<Vec<_>>(),
65/// [
66/// (Next, "root"),
67/// (Down, "c1"),
68/// (Down, "c2"),
69/// (Next, "c3"),
70/// (Next, "c4"),
71/// (Up, "c1"),
72/// (Next, "c5"),
73/// (Next, "c6"),
74/// (Up, "root"),
75/// ]
76/// );
77///
78/// let c1 = root.first().ok_or("missing c1")?;
79///
80/// assert_eq!(
81/// c1.walk_events().map(|(e, n)| (e, n.value())).collect::<Vec<_>>(),
82/// [
83/// (Next, "c1"),
84/// (Down, "c2"),
85/// (Next, "c3"),
86/// (Next, "c4"),
87/// (Up, "c1"),
88/// (Next, "c5"),
89/// (Next, "c6"),
90/// (Up, "root"),
91/// ]
92/// );
93/// # Ok::<_, Box<dyn core::error::Error>>(())
94/// ```
95///
96/// Example showcasing how we can use events to keep track of the depth in which
97/// nodes are being traversed:
98///
99/// ```
100/// use syntree::node::Event::*;
101///
102/// let tree = syntree::tree! {
103/// "root" => {
104/// "c1" => {
105/// "c2" => {},
106/// "c3" => {},
107/// }
108/// }
109/// };
110///
111/// let mut it = tree.walk_events();
112/// let mut depth = 0;
113///
114/// let mut nodes = Vec::new();
115///
116/// while let Some((event, node)) = it.next() {
117/// // Only register each node once.
118/// match event {
119/// Up => {
120/// depth -= 1;
121/// }
122/// Down => {
123/// depth += 1;
124/// nodes.push((depth, node.value()));
125/// }
126/// Next => {
127/// nodes.push((depth, node.value()));
128/// }
129/// }
130/// }
131///
132/// assert_eq!(depth, 0);
133///
134/// assert_eq!(
135/// nodes,
136/// [(0, "root"), (1, "c1"), (2, "c2"), (2, "c3")]
137/// );
138/// # Ok::<_, Box<dyn core::error::Error>>(())
139/// ```
140pub struct WalkEvents<'a, T, F>
141where
142 T: Copy,
143 F: Flavor,
144{
145 /// The tree being iterated over.
146 tree: &'a [Links<T, F::Index, F::Pointer>],
147 // The current node.
148 node: Option<(F::Pointer, Event)>,
149 // Current depth being walked.
150 depth: isize,
151}
152
153impl<'a, T, F> WalkEvents<'a, T, F>
154where
155 T: Copy,
156 F: Flavor,
157{
158 /// Construct a new events walker.
159 #[inline]
160 pub(crate) fn new(
161 tree: &'a [Links<T, F::Index, F::Pointer>],
162 node: Option<F::Pointer>,
163 e: Event,
164 ) -> Self {
165 Self {
166 tree,
167 node: node.map(|n| (n, e)),
168 depth: 0,
169 }
170 }
171
172 /// Get the depth of the node that the next call to [`next`] returns,
173 /// relative to the node the walk started at, which has depth `0`.
174 ///
175 /// A node emitted with [`Event::Up`] has the depth of the node being
176 /// returned to. When a walk started at a node leaves that node's subtree,
177 /// for example by climbing up to its parent, the depth becomes negative.
178 ///
179 /// Once the iterator is exhausted, the depth is that of the last node it
180 /// returned.
181 ///
182 /// [`next`]: Iterator::next
183 ///
184 /// # Examples
185 ///
186 /// ```
187 /// use syntree::node::Event::*;
188 ///
189 /// let tree = syntree::tree! {
190 /// "root" => {
191 /// "c1" => {
192 /// "c2" => {},
193 /// },
194 /// "c3" => {}
195 /// }
196 /// };
197 ///
198 /// let mut it = tree.walk_events();
199 /// let mut out = Vec::new();
200 ///
201 /// loop {
202 /// let depth = it.depth();
203 /// let Some((event, node)) = it.next() else { break };
204 /// out.push((depth, event, node.value()));
205 /// }
206 ///
207 /// assert_eq!(
208 /// out,
209 /// [
210 /// (0, Next, "root"),
211 /// (1, Down, "c1"),
212 /// (2, Down, "c2"),
213 /// (1, Up, "c1"),
214 /// (1, Next, "c3"),
215 /// (0, Up, "root"),
216 /// ]
217 /// );
218 ///
219 /// let c1 = tree.first().and_then(|n| n.first()).ok_or("missing c1")?;
220 ///
221 /// let mut it = c1.walk_events();
222 /// let mut out = Vec::new();
223 ///
224 /// loop {
225 /// let depth = it.depth();
226 /// let Some((event, node)) = it.next() else { break };
227 /// out.push((depth, event, node.value()));
228 /// }
229 ///
230 /// assert_eq!(
231 /// out,
232 /// [
233 /// (0, Next, "c1"),
234 /// (1, Down, "c2"),
235 /// (0, Up, "c1"),
236 /// (0, Next, "c3"),
237 /// (-1, Up, "root"),
238 /// ]
239 /// );
240 /// # Ok::<_, Box<dyn core::error::Error>>(())
241 /// ```
242 #[inline]
243 #[must_use]
244 pub const fn depth(&self) -> isize {
245 self.depth
246 }
247
248 fn step(
249 &mut self,
250 links: &Links<T, F::Index, F::Pointer>,
251 event: Event,
252 ) -> Option<(F::Pointer, Event)> {
253 if let Event::Up = event {
254 if let Some(next) = links.next {
255 return Some((next, Event::Next));
256 }
257 } else {
258 if let Some(first) = links.first {
259 self.depth = self.depth.checked_add(1)?;
260 return Some((first, Event::Down));
261 }
262
263 if let Some(next) = links.next {
264 return Some((next, Event::Next));
265 }
266 }
267
268 let parent = links.parent?;
269 self.depth = self.depth.checked_sub(1)?;
270 Some((parent, Event::Up))
271 }
272}
273
274impl<T, F> Clone for WalkEvents<'_, T, F>
275where
276 T: Copy,
277 F: Flavor,
278{
279 #[inline]
280 fn clone(&self) -> Self {
281 Self {
282 tree: self.tree,
283 node: self.node,
284 depth: self.depth,
285 }
286 }
287}
288
289impl<T, F> Default for WalkEvents<'_, T, F>
290where
291 T: Copy,
292 F: Flavor,
293{
294 #[inline]
295 fn default() -> Self {
296 Self {
297 tree: &[],
298 node: None,
299 depth: 0,
300 }
301 }
302}
303
304impl<'a, T, F> Iterator for WalkEvents<'a, T, F>
305where
306 T: Copy,
307 F: Flavor,
308{
309 type Item = (Event, Node<'a, T, F>);
310
311 fn next(&mut self) -> Option<Self::Item> {
312 let (node, event) = self.node.take()?;
313 let links = self.tree.get(node.get())?;
314 self.node = self.step(links, event);
315 let node = Node::new(links, self.tree);
316 Some((event, node))
317 }
318
319 #[inline]
320 fn size_hint(&self) -> (usize, Option<usize>) {
321 (usize::from(self.node.is_some()), None)
322 }
323}
324
325impl<T, F> FusedIterator for WalkEvents<'_, T, F>
326where
327 T: Copy,
328 F: Flavor,
329{
330}
331
332impl<T, F> fmt::Debug for WalkEvents<'_, T, F>
333where
334 T: Copy + fmt::Debug,
335 F: Flavor<Index: fmt::Debug>,
336{
337 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
338 let next = self.node.and_then(|(id, event)| {
339 let links = self.tree.get(id.get())?;
340 Some((event, Node::<T, F>::new(links, self.tree)))
341 });
342
343 f.debug_struct("WalkEvents")
344 .field("next", &next)
345 .field("depth", &self.depth)
346 .finish()
347 }
348}