Skip to main content

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}