Skip to main content

syntree/node/
skip_tokens.rs

1use core::fmt;
2use core::iter::FusedIterator;
3
4use crate::flavor::Flavor;
5use crate::node::Node;
6
7/// Wrapped around an iterator that excludes nodes without children.
8///
9/// See [`Children::skip_tokens`], [`Siblings::skip_tokens`],
10/// [`Ancestors::skip_tokens`] or [`Walk::skip_tokens`].
11///
12/// [`Children::skip_tokens`]: crate::node::Children::skip_tokens
13/// [`Siblings::skip_tokens`]: crate::node::Siblings::skip_tokens
14/// [`Ancestors::skip_tokens`]: crate::node::Ancestors::skip_tokens
15/// [`Walk::skip_tokens`]: crate::node::Walk::skip_tokens
16///
17/// # Examples
18///
19/// Filtering childless nodes from a [`Children`] iterator:
20///
21/// ```
22/// let tree = syntree::tree! {
23///     ("token1", 1),
24///     "child1" => {
25///         "token2"
26///     },
27///     ("token3", 1),
28///     "child2" => {
29///         "token4"
30///     },
31///     ("token5", 1),
32///     "child3" => {
33///         "token6"
34///     },
35///     ("token7", 1)
36/// };
37///
38/// let it = tree.children().skip_tokens();
39///
40/// assert_eq!(
41///     it.map(|n| n.value()).collect::<Vec<_>>(),
42///     ["child1", "child2", "child3"]
43/// );
44/// # Ok::<_, Box<dyn core::error::Error>>(())
45/// ```
46///
47/// Filtering tokens from a [`Walk`] iterator:
48///
49/// ```
50/// let tree = syntree::tree! {
51///     "child1" => {
52///         "child2" => {
53///             "token1"
54///         },
55///         ("token2", 1),
56///         "child3" => {
57///             "token3"
58///         },
59///     },
60///     "child4" => {
61///         ("token4", 1)
62///     }
63/// };
64///
65/// let it = tree.walk().skip_tokens();
66///
67/// assert_eq!(
68///     it.map(|n| n.value()).collect::<Vec<_>>(),
69///     ["child1", "child2", "child3", "child4"]
70/// );
71/// # Ok::<_, Box<dyn core::error::Error>>(())
72/// ```
73///
74/// [`Children`]: crate::node::Children
75/// [`Walk`]: crate::node::Walk
76pub struct SkipTokens<U> {
77    iter: U,
78}
79
80impl<U> SkipTokens<U> {
81    #[inline]
82    pub(crate) const fn new(iter: U) -> Self {
83        Self { iter }
84    }
85}
86
87impl<'a, U, T: 'a, F: 'a> Iterator for SkipTokens<U>
88where
89    T: Copy,
90    F: Flavor,
91    U: Iterator<Item = Node<'a, T, F>>,
92{
93    type Item = U::Item;
94
95    #[inline]
96    fn next(&mut self) -> Option<Self::Item> {
97        self.iter.find(|n| n.has_children())
98    }
99
100    #[inline]
101    fn size_hint(&self) -> (usize, Option<usize>) {
102        let (_, upper) = self.iter.size_hint();
103        (0, upper)
104    }
105
106    #[inline]
107    fn find<P>(&mut self, mut predicate: P) -> Option<Self::Item>
108    where
109        Self: Sized,
110        P: FnMut(&Self::Item) -> bool,
111    {
112        self.iter.find(move |n| n.has_children() && predicate(n))
113    }
114}
115
116impl<'a, U, T: 'a, F: 'a> DoubleEndedIterator for SkipTokens<U>
117where
118    T: Copy,
119    F: Flavor,
120    U: DoubleEndedIterator<Item = Node<'a, T, F>>,
121{
122    #[inline]
123    fn next_back(&mut self) -> Option<Self::Item> {
124        self.iter.rfind(|n| n.has_children())
125    }
126
127    #[inline]
128    fn rfind<P>(&mut self, mut predicate: P) -> Option<Self::Item>
129    where
130        Self: Sized,
131        P: FnMut(&Self::Item) -> bool,
132    {
133        self.iter.rfind(move |n| n.has_children() && predicate(n))
134    }
135}
136
137impl<'a, U, T: 'a, F: 'a> FusedIterator for SkipTokens<U>
138where
139    T: Copy,
140    F: Flavor,
141    U: FusedIterator<Item = Node<'a, T, F>>,
142{
143}
144
145impl<U> Clone for SkipTokens<U>
146where
147    U: Clone,
148{
149    #[inline]
150    fn clone(&self) -> Self {
151        Self {
152            iter: self.iter.clone(),
153        }
154    }
155}
156
157impl<U> Default for SkipTokens<U>
158where
159    U: Default,
160{
161    #[inline]
162    fn default() -> Self {
163        Self {
164            iter: Default::default(),
165        }
166    }
167}
168
169impl<U> fmt::Debug for SkipTokens<U>
170where
171    U: fmt::Debug,
172{
173    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
174        f.debug_struct("SkipTokens")
175            .field("iter", &self.iter)
176            .finish()
177    }
178}