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}