kuchikiki/
iter.rs

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