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}