kuchikikiki/
iter.rs

1//! Node iterators
2
3// Addressing this lint is a semver-breaking change.
4// Remove this once the issue has been addressed.
5#![allow(clippy::result_unit_err)]
6
7use std::borrow::Borrow;
8use std::cell::RefCell;
9use std::iter::Rev;
10
11use crate::node_data_ref::NodeDataRef;
12use crate::select::Selectors;
13use crate::tree::{ElementData, NodeRef};
14
15impl NodeRef {
16    /// Return an iterator of references to this node and its ancestors.
17    #[inline]
18    pub fn inclusive_ancestors(&self) -> Ancestors {
19        Ancestors(Some(self.clone()))
20    }
21
22    /// Return an iterator of references to this node’s ancestors.
23    #[inline]
24    pub fn ancestors(&self) -> Ancestors {
25        Ancestors(self.parent())
26    }
27
28    /// Return an iterator of references to this node and the siblings before it.
29    #[inline]
30    pub fn inclusive_preceding_siblings(&self) -> Rev<Siblings> {
31        match self.parent() {
32            Some(parent) => {
33                let first_sibling = parent.first_child().unwrap();
34                debug_assert!(self.previous_sibling().is_some() || *self == first_sibling);
35                Siblings(Some(State {
36                    next: first_sibling,
37                    next_back: self.clone(),
38                }))
39            }
40            None => {
41                debug_assert!(self.previous_sibling().is_none());
42                Siblings(Some(State {
43                    next: self.clone(),
44                    next_back: self.clone(),
45                }))
46            }
47        }
48        .rev()
49    }
50
51    /// Return an iterator of references to this node’s siblings before it.
52    #[inline]
53    pub fn preceding_siblings(&self) -> Rev<Siblings> {
54        match (self.parent(), self.previous_sibling()) {
55            (Some(parent), Some(previous_sibling)) => {
56                let first_sibling = parent.first_child().unwrap();
57                Siblings(Some(State {
58                    next: first_sibling,
59                    next_back: previous_sibling,
60                }))
61            }
62            _ => Siblings(None),
63        }
64        .rev()
65    }
66
67    /// Return an iterator of references to this node and the siblings after it.
68    #[inline]
69    pub fn inclusive_following_siblings(&self) -> Siblings {
70        match self.parent() {
71            Some(parent) => {
72                let last_sibling = parent.last_child().unwrap();
73                debug_assert!(self.next_sibling().is_some() || *self == last_sibling);
74                Siblings(Some(State {
75                    next: self.clone(),
76                    next_back: last_sibling,
77                }))
78            }
79            None => {
80                debug_assert!(self.next_sibling().is_none());
81                Siblings(Some(State {
82                    next: self.clone(),
83                    next_back: self.clone(),
84                }))
85            }
86        }
87    }
88
89    /// Return an iterator of references to this node’s siblings after it.
90    #[inline]
91    pub fn following_siblings(&self) -> Siblings {
92        match (self.parent(), self.next_sibling()) {
93            (Some(parent), Some(next_sibling)) => {
94                let last_sibling = parent.last_child().unwrap();
95                Siblings(Some(State {
96                    next: next_sibling,
97                    next_back: last_sibling,
98                }))
99            }
100            _ => Siblings(None),
101        }
102    }
103
104    /// Return an iterator of references to this node’s children.
105    #[inline]
106    pub fn children(&self) -> Siblings {
107        match (self.first_child(), self.last_child()) {
108            (Some(first_child), Some(last_child)) => Siblings(Some(State {
109                next: first_child,
110                next_back: last_child,
111            })),
112            (None, None) => Siblings(None),
113            _ => unreachable!(),
114        }
115    }
116
117    /// Return an iterator of references to this node and its descendants, in tree order.
118    ///
119    /// Parent nodes appear before the descendants.
120    ///
121    /// Note: this is the `NodeEdge::Start` items from `traverse()`.
122    #[inline]
123    pub fn inclusive_descendants(&self) -> Descendants {
124        Descendants(self.traverse_inclusive())
125    }
126
127    /// Return an iterator of references to this node’s descendants, in tree order.
128    ///
129    /// Parent nodes appear before the descendants.
130    ///
131    /// Note: this is the `NodeEdge::Start` items from `traverse()`.
132    #[inline]
133    pub fn descendants(&self) -> Descendants {
134        Descendants(self.traverse())
135    }
136
137    /// Return an iterator of the start and end edges of this node and its descendants,
138    /// in tree order.
139    #[inline]
140    pub fn traverse_inclusive(&self) -> Traverse {
141        Traverse(Some(State {
142            next: NodeEdge::Start(self.clone()),
143            next_back: NodeEdge::End(self.clone()),
144        }))
145    }
146
147    /// Return an iterator of the start and end edges of this node’s descendants,
148    /// in tree order.
149    #[inline]
150    pub fn traverse(&self) -> Traverse {
151        match (self.first_child(), self.last_child()) {
152            (Some(first_child), Some(last_child)) => Traverse(Some(State {
153                next: NodeEdge::Start(first_child),
154                next_back: NodeEdge::End(last_child),
155            })),
156            (None, None) => Traverse(None),
157            _ => unreachable!(),
158        }
159    }
160
161    /// Return an iterator of the inclusive descendants element that match the given selector list.
162    #[inline]
163    pub fn select(&self, selectors: &str) -> Result<Select<Elements<Descendants>>, ()> {
164        self.inclusive_descendants().select(selectors)
165    }
166
167    /// Return the first inclusive descendants element that match the given selector list.
168    #[inline]
169    pub fn select_first(&self, selectors: &str) -> Result<NodeDataRef<ElementData>, ()> {
170        let mut elements = self.select(selectors)?;
171        elements.next().ok_or(())
172    }
173}
174
175#[derive(Debug, Clone)]
176struct State<T> {
177    next: T,
178    next_back: T,
179}
180
181/// A double-ended iterator of sibling nodes.
182#[derive(Debug, Clone)]
183pub struct Siblings(Option<State<NodeRef>>);
184
185macro_rules! siblings_next {
186    ($next: ident, $next_back: ident, $next_sibling: ident) => {
187        fn $next(&mut self) -> Option<NodeRef> {
188            #![allow(non_shorthand_field_patterns)]
189            self.0.take().map(
190                |State {
191                     $next: next,
192                     $next_back: next_back,
193                 }| {
194                    if let Some(sibling) = next.$next_sibling() {
195                        if next != next_back {
196                            self.0 = Some(State {
197                                $next: sibling,
198                                $next_back: next_back,
199                            })
200                        }
201                    }
202                    next
203                },
204            )
205        }
206    };
207}
208
209impl Iterator for Siblings {
210    type Item = NodeRef;
211    siblings_next!(next, next_back, next_sibling);
212}
213
214impl DoubleEndedIterator for Siblings {
215    siblings_next!(next_back, next, previous_sibling);
216}
217
218/// An iterator on ancestor nodes.
219#[derive(Debug, Clone)]
220pub struct Ancestors(Option<NodeRef>);
221
222impl Iterator for Ancestors {
223    type Item = NodeRef;
224
225    #[inline]
226    fn next(&mut self) -> Option<NodeRef> {
227        self.0.take().inspect(|node| {
228            self.0 = node.parent();
229        })
230    }
231}
232
233/// An iterator of references to a given node and its descendants, in tree order.
234#[derive(Debug, Clone)]
235pub struct Descendants(Traverse);
236
237macro_rules! descendants_next {
238    ($next: ident) => {
239        #[inline]
240        fn $next(&mut self) -> Option<NodeRef> {
241            loop {
242                match (self.0).$next() {
243                    Some(NodeEdge::Start(node)) => return Some(node),
244                    Some(NodeEdge::End(_)) => {}
245                    None => return None,
246                }
247            }
248        }
249    };
250}
251
252impl Iterator for Descendants {
253    type Item = NodeRef;
254    descendants_next!(next);
255}
256
257impl DoubleEndedIterator for Descendants {
258    descendants_next!(next_back);
259}
260
261/// Marks either the start or the end of a node.
262#[derive(Debug, Copy, Clone, PartialEq, Eq)]
263pub enum NodeEdge<T> {
264    /// Indicates that start of a node that has children.
265    /// Yielded by `Traverse::next` before the node’s descendants.
266    /// In HTML or XML, this corresponds to an opening tag like `<div>`
267    Start(T),
268
269    /// Indicates that end of a node that has children.
270    /// Yielded by `Traverse::next` after the node’s descendants.
271    /// In HTML or XML, this corresponds to a closing tag like `</div>`
272    End(T),
273}
274
275/// An iterator of the start and end edges of the nodes in a given subtree.
276#[derive(Debug, Clone)]
277pub struct Traverse(Option<State<NodeEdge<NodeRef>>>);
278
279macro_rules! traverse_next {
280    ($next: ident, $next_back: ident, $first_child: ident, $next_sibling: ident, $Start: ident, $End: ident) => {
281        fn $next(&mut self) -> Option<NodeEdge<NodeRef>> {
282            #![allow(non_shorthand_field_patterns)]
283            self.0.take().map(
284                |State {
285                     $next: next,
286                     $next_back: next_back,
287                 }| {
288                    if next != next_back {
289                        self.0 = match next {
290                            NodeEdge::$Start(ref node) => match node.$first_child() {
291                                Some(child) => Some(State {
292                                    $next: NodeEdge::$Start(child),
293                                    $next_back: next_back,
294                                }),
295                                None => Some(State {
296                                    $next: NodeEdge::$End(node.clone()),
297                                    $next_back: next_back,
298                                }),
299                            },
300                            NodeEdge::$End(ref node) => match node.$next_sibling() {
301                                Some(sibling) => Some(State {
302                                    $next: NodeEdge::$Start(sibling),
303                                    $next_back: next_back,
304                                }),
305                                None => node.parent().map(|parent| State {
306                                    $next: NodeEdge::$End(parent),
307                                    $next_back: next_back,
308                                }),
309                            },
310                        };
311                    }
312                    next
313                },
314            )
315        }
316    };
317}
318
319impl Iterator for Traverse {
320    type Item = NodeEdge<NodeRef>;
321    traverse_next!(next, next_back, first_child, next_sibling, Start, End);
322}
323
324impl DoubleEndedIterator for Traverse {
325    traverse_next!(next_back, next, last_child, previous_sibling, End, Start);
326}
327
328macro_rules! filter_map_like_iterator {
329    (#[$doc: meta] $name: ident: $f: expr, $from: ty => $to: ty) => {
330        #[$doc]
331        #[derive(Debug, Clone)]
332        pub struct $name<I>(pub I);
333
334        impl<I> Iterator for $name<I>
335        where
336            I: Iterator<Item = $from>,
337        {
338            type Item = $to;
339
340            #[inline]
341            fn next(&mut self) -> Option<$to> {
342                for x in self.0.by_ref() {
343                    if let Some(y) = ($f)(x) {
344                        return Some(y);
345                    }
346                }
347                None
348            }
349        }
350
351        impl<I> DoubleEndedIterator for $name<I>
352        where
353            I: DoubleEndedIterator<Item = $from>,
354        {
355            #[inline]
356            fn next_back(&mut self) -> Option<$to> {
357                for x in self.0.by_ref().rev() {
358                    if let Some(y) = ($f)(x) {
359                        return Some(y);
360                    }
361                }
362                None
363            }
364        }
365    };
366}
367
368filter_map_like_iterator! {
369    /// A node iterator adaptor that yields element nodes.
370    Elements: NodeRef::into_element_ref, NodeRef => NodeDataRef<ElementData>
371}
372
373filter_map_like_iterator! {
374    /// A node iterator adaptor that yields comment nodes.
375    Comments: NodeRef::into_comment_ref, NodeRef => NodeDataRef<RefCell<String>>
376}
377
378filter_map_like_iterator! {
379    /// A node iterator adaptor that yields text nodes.
380    TextNodes: NodeRef::into_text_ref, NodeRef => NodeDataRef<RefCell<String>>
381}
382
383/// An element iterator adaptor that yields elements maching given selectors.
384pub struct Select<I, S = Selectors>
385where
386    I: Iterator<Item = NodeDataRef<ElementData>>,
387    S: Borrow<Selectors>,
388{
389    /// The underlying iterator.
390    pub iter: I,
391
392    /// The selectors to be matched.
393    pub selectors: S,
394}
395
396impl<I, S> Iterator for Select<I, S>
397where
398    I: Iterator<Item = NodeDataRef<ElementData>>,
399    S: Borrow<Selectors>,
400{
401    type Item = NodeDataRef<ElementData>;
402
403    #[inline]
404    fn next(&mut self) -> Option<NodeDataRef<ElementData>> {
405        let selectors = self.selectors.borrow();
406        self.iter
407            .by_ref()
408            .find(|element| selectors.matches(element))
409    }
410}
411
412impl<I, S> DoubleEndedIterator for Select<I, S>
413where
414    I: DoubleEndedIterator<Item = NodeDataRef<ElementData>>,
415    S: Borrow<Selectors>,
416{
417    #[inline]
418    fn next_back(&mut self) -> Option<NodeDataRef<ElementData>> {
419        let selectors = self.selectors.borrow();
420        self.iter
421            .by_ref()
422            .rev()
423            .find(|element| selectors.matches(element))
424    }
425}
426
427/// Convenience methods for node iterators.
428pub trait NodeIterator: Sized + Iterator<Item = NodeRef> {
429    /// Filter this element iterator to elements.
430    #[inline]
431    fn elements(self) -> Elements<Self> {
432        Elements(self)
433    }
434
435    /// Filter this node iterator to text nodes.
436    #[inline]
437    fn text_nodes(self) -> TextNodes<Self> {
438        TextNodes(self)
439    }
440
441    /// Filter this node iterator to comment nodes.
442    #[inline]
443    fn comments(self) -> Comments<Self> {
444        Comments(self)
445    }
446
447    /// Filter this node iterator to elements maching the given selectors.
448    #[inline]
449    fn select(self, selectors: &str) -> Result<Select<Elements<Self>>, ()> {
450        self.elements().select(selectors)
451    }
452}
453
454/// Convenience methods for element iterators.
455pub trait ElementIterator: Sized + Iterator<Item = NodeDataRef<ElementData>> {
456    /// Filter this element iterator to elements maching the given selectors.
457    #[inline]
458    fn select(self, selectors: &str) -> Result<Select<Self>, ()> {
459        Selectors::compile(selectors).map(|s| Select {
460            iter: self,
461            selectors: s,
462        })
463    }
464}
465
466impl<I> NodeIterator for I where I: Iterator<Item = NodeRef> {}
467impl<I> ElementIterator for I where I: Iterator<Item = NodeDataRef<ElementData>> {}