kuchiki/
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(|State { $next: next, $next_back: next_back }| {
186                if let Some(sibling) = next.$next_sibling() {
187                    if next != next_back {
188                        self.0 = Some(State { $next: sibling, $next_back: next_back })
189                    }
190                }
191                next
192            })
193        }
194    }
195}
196
197impl Iterator for Siblings {
198    type Item = NodeRef;
199    siblings_next!(next, next_back, next_sibling);
200}
201
202impl DoubleEndedIterator for Siblings {
203    siblings_next!(next_back, next, previous_sibling);
204}
205
206/// An iterator on ancestor nodes.
207#[derive(Debug, Clone)]
208pub struct Ancestors(Option<NodeRef>);
209
210impl Iterator for Ancestors {
211    type Item = NodeRef;
212
213    #[inline]
214    fn next(&mut self) -> Option<NodeRef> {
215        self.0.take().map(|node| {
216            self.0 = node.parent();
217            node
218        })
219    }
220}
221
222/// An iterator of references to a given node and its descendants, in tree order.
223#[derive(Debug, Clone)]
224pub struct Descendants(Traverse);
225
226macro_rules! descendants_next {
227    ($next: ident) => {
228        #[inline]
229        fn $next(&mut self) -> Option<NodeRef> {
230            loop {
231                match (self.0).$next() {
232                    Some(NodeEdge::Start(node)) => return Some(node),
233                    Some(NodeEdge::End(_)) => {}
234                    None => return None
235                }
236            }
237        }
238    }
239}
240
241impl Iterator for Descendants {
242    type Item = NodeRef;
243    descendants_next!(next);
244}
245
246impl DoubleEndedIterator for Descendants {
247    descendants_next!(next_back);
248}
249
250/// Marks either the start or the end of a node.
251#[derive(Debug, Copy, Clone, PartialEq, Eq)]
252pub enum NodeEdge<T> {
253    /// Indicates that start of a node that has children.
254    /// Yielded by `Traverse::next` before the node’s descendants.
255    /// In HTML or XML, this corresponds to an opening tag like `<div>`
256    Start(T),
257
258    /// Indicates that end of a node that has children.
259    /// Yielded by `Traverse::next` after the node’s descendants.
260    /// In HTML or XML, this corresponds to a closing tag like `</div>`
261    End(T),
262}
263
264/// An iterator of the start and end edges of the nodes in a given subtree.
265#[derive(Debug, Clone)]
266pub struct Traverse(Option<State<NodeEdge<NodeRef>>>);
267
268macro_rules! traverse_next {
269    ($next: ident, $next_back: ident, $first_child: ident, $next_sibling: ident, $Start: ident, $End: ident) => {
270        fn $next(&mut self) -> Option<NodeEdge<NodeRef>> {
271            #![allow(non_shorthand_field_patterns)]
272            self.0.take().map(|State { $next: next, $next_back: next_back }| {
273                if next != next_back {
274                    self.0 = match next {
275                        NodeEdge::$Start(ref node) => {
276                            match node.$first_child() {
277                                Some(child) => {
278                                    Some(State { $next: NodeEdge::$Start(child), $next_back: next_back })
279                                }
280                                None => Some(State { $next: NodeEdge::$End(node.clone()), $next_back: next_back })
281                            }
282                        }
283                        NodeEdge::$End(ref node) => {
284                            match node.$next_sibling() {
285                                Some(sibling) => {
286                                    Some(State { $next: NodeEdge::$Start(sibling), $next_back: next_back })
287                                }
288                                None => node.parent().map(|parent| {
289                                    State { $next: NodeEdge::$End(parent), $next_back: next_back }
290                                })
291                            }
292                        }
293                    };
294                }
295                next
296            })
297        }
298    }
299}
300
301impl Iterator for Traverse {
302    type Item = NodeEdge<NodeRef>;
303    traverse_next!(next, next_back, first_child, next_sibling, Start, End);
304}
305
306impl DoubleEndedIterator for Traverse {
307    traverse_next!(next_back, next, last_child, previous_sibling, End, Start);
308}
309
310macro_rules! filter_map_like_iterator {
311    (#[$doc: meta] $name: ident: $f: expr, $from: ty => $to: ty) => {
312        #[$doc]
313        #[derive(Debug, Clone)]
314        pub struct $name<I>(pub I);
315
316        impl<I> Iterator for $name<I>
317        where
318            I: Iterator<Item = $from>,
319        {
320            type Item = $to;
321
322            #[inline]
323            fn next(&mut self) -> Option<$to> {
324                for x in self.0.by_ref() {
325                    if let Some(y) = ($f)(x) {
326                        return Some(y);
327                    }
328                }
329                None
330            }
331        }
332
333        impl<I> DoubleEndedIterator for $name<I>
334        where
335            I: DoubleEndedIterator<Item = $from>,
336        {
337            #[inline]
338            fn next_back(&mut self) -> Option<$to> {
339                for x in self.0.by_ref().rev() {
340                    if let Some(y) = ($f)(x) {
341                        return Some(y);
342                    }
343                }
344                None
345            }
346        }
347    };
348}
349
350filter_map_like_iterator! {
351    /// A node iterator adaptor that yields element nodes.
352    Elements: NodeRef::into_element_ref, NodeRef => NodeDataRef<ElementData>
353}
354
355filter_map_like_iterator! {
356    /// A node iterator adaptor that yields comment nodes.
357    Comments: NodeRef::into_comment_ref, NodeRef => NodeDataRef<RefCell<String>>
358}
359
360filter_map_like_iterator! {
361    /// A node iterator adaptor that yields text nodes.
362    TextNodes: NodeRef::into_text_ref, NodeRef => NodeDataRef<RefCell<String>>
363}
364
365/// An element iterator adaptor that yields elements maching given selectors.
366pub struct Select<I, S = Selectors>
367where
368    I: Iterator<Item = NodeDataRef<ElementData>>,
369    S: Borrow<Selectors>,
370{
371    /// The underlying iterator.
372    pub iter: I,
373
374    /// The selectors to be matched.
375    pub selectors: S,
376}
377
378impl<I, S> Iterator for Select<I, S>
379where
380    I: Iterator<Item = NodeDataRef<ElementData>>,
381    S: Borrow<Selectors>,
382{
383    type Item = NodeDataRef<ElementData>;
384
385    #[inline]
386    fn next(&mut self) -> Option<NodeDataRef<ElementData>> {
387        for element in self.iter.by_ref() {
388            if self.selectors.borrow().matches(&element) {
389                return Some(element);
390            }
391        }
392        None
393    }
394}
395
396impl<I, S> DoubleEndedIterator for Select<I, S>
397where
398    I: DoubleEndedIterator<Item = NodeDataRef<ElementData>>,
399    S: Borrow<Selectors>,
400{
401    #[inline]
402    fn next_back(&mut self) -> Option<NodeDataRef<ElementData>> {
403        for element in self.iter.by_ref().rev() {
404            if self.selectors.borrow().matches(&element) {
405                return Some(element);
406            }
407        }
408        None
409    }
410}
411
412/// Convenience methods for node iterators.
413pub trait NodeIterator: Sized + Iterator<Item = NodeRef> {
414    /// Filter this element iterator to elements.
415    #[inline]
416    fn elements(self) -> Elements<Self> {
417        Elements(self)
418    }
419
420    /// Filter this node iterator to text nodes.
421    #[inline]
422    fn text_nodes(self) -> TextNodes<Self> {
423        TextNodes(self)
424    }
425
426    /// Filter this node iterator to comment nodes.
427    #[inline]
428    fn comments(self) -> Comments<Self> {
429        Comments(self)
430    }
431
432    /// Filter this node iterator to elements maching the given selectors.
433    #[inline]
434    fn select(self, selectors: &str) -> Result<Select<Elements<Self>>, ()> {
435        self.elements().select(selectors)
436    }
437}
438
439/// Convenience methods for element iterators.
440pub trait ElementIterator: Sized + Iterator<Item = NodeDataRef<ElementData>> {
441    /// Filter this element iterator to elements maching the given selectors.
442    #[inline]
443    fn select(self, selectors: &str) -> Result<Select<Self>, ()> {
444        Selectors::compile(selectors).map(|s| Select {
445            iter: self,
446            selectors: s,
447        })
448    }
449}
450
451impl<I> NodeIterator for I where I: Iterator<Item = NodeRef> {}
452impl<I> ElementIterator for I where I: Iterator<Item = NodeDataRef<ElementData>> {}