Skip to main content

tl/queryselector/
iter.rs

1use core::marker::PhantomData;
2
3use crate::{NodeHandle, Parser};
4
5use super::{Selector, iterable::QueryIterable};
6
7/// A query selector iterator that yields matching HTML nodes
8pub struct QuerySelectorIterator<
9    'a,
10    'b,
11    Q: QueryIterable<'a, MAX_NODES, MAX_STACK, MAX_ROOTS, MAX_IDS, MAX_CLASSES, MAX_SELECTOR_NODES>,
12    const MAX_NODES: usize = 0,
13    const MAX_STACK: usize = 0,
14    const MAX_ROOTS: usize = 0,
15    const MAX_IDS: usize = 0,
16    const MAX_CLASSES: usize = 0,
17    const MAX_SELECTOR_NODES: usize = 0,
18> {
19    selector: Selector<'b, MAX_SELECTOR_NODES>,
20    collection: &'b Q,
21    parser:
22        &'b Parser<'a, MAX_NODES, MAX_STACK, MAX_ROOTS, MAX_IDS, MAX_CLASSES, MAX_SELECTOR_NODES>,
23    index: usize,
24    len: usize,
25    _a: PhantomData<&'a ()>,
26}
27
28impl<
29    'a,
30    'b,
31    Q: QueryIterable<'a, MAX_NODES, MAX_STACK, MAX_ROOTS, MAX_IDS, MAX_CLASSES, MAX_SELECTOR_NODES>,
32    const MAX_NODES: usize,
33    const MAX_STACK: usize,
34    const MAX_ROOTS: usize,
35    const MAX_IDS: usize,
36    const MAX_CLASSES: usize,
37    const MAX_SELECTOR_NODES: usize,
38> Clone
39    for QuerySelectorIterator<
40        'a,
41        'b,
42        Q,
43        MAX_NODES,
44        MAX_STACK,
45        MAX_ROOTS,
46        MAX_IDS,
47        MAX_CLASSES,
48        MAX_SELECTOR_NODES,
49    >
50{
51    fn clone(&self) -> Self {
52        Self {
53            selector: self.selector.clone(),
54            collection: self.collection,
55            parser: self.parser,
56            index: self.index,
57            len: self.len,
58            _a: PhantomData,
59        }
60    }
61}
62
63impl<
64    'a,
65    'b,
66    Q: QueryIterable<'a, MAX_NODES, MAX_STACK, MAX_ROOTS, MAX_IDS, MAX_CLASSES, MAX_SELECTOR_NODES>,
67    const MAX_NODES: usize,
68    const MAX_STACK: usize,
69    const MAX_ROOTS: usize,
70    const MAX_IDS: usize,
71    const MAX_CLASSES: usize,
72    const MAX_SELECTOR_NODES: usize,
73>
74    QuerySelectorIterator<
75        'a,
76        'b,
77        Q,
78        MAX_NODES,
79        MAX_STACK,
80        MAX_ROOTS,
81        MAX_IDS,
82        MAX_CLASSES,
83        MAX_SELECTOR_NODES,
84    >
85{
86    /// Creates a new query selector iterator
87    pub fn new(
88        selector: Selector<'b, MAX_SELECTOR_NODES>,
89        parser: &'b Parser<
90            'a,
91            MAX_NODES,
92            MAX_STACK,
93            MAX_ROOTS,
94            MAX_IDS,
95            MAX_CLASSES,
96            MAX_SELECTOR_NODES,
97        >,
98        collection: &'b Q,
99    ) -> Self {
100        Self {
101            selector,
102            collection,
103            index: 0,
104            len: collection.len(parser),
105            parser,
106            _a: PhantomData,
107        }
108    }
109}
110
111impl<
112    'a,
113    'b,
114    Q: QueryIterable<'a, MAX_NODES, MAX_STACK, MAX_ROOTS, MAX_IDS, MAX_CLASSES, MAX_SELECTOR_NODES>,
115    const MAX_NODES: usize,
116    const MAX_STACK: usize,
117    const MAX_ROOTS: usize,
118    const MAX_IDS: usize,
119    const MAX_CLASSES: usize,
120    const MAX_SELECTOR_NODES: usize,
121> Iterator
122    for QuerySelectorIterator<
123        'a,
124        'b,
125        Q,
126        MAX_NODES,
127        MAX_STACK,
128        MAX_ROOTS,
129        MAX_IDS,
130        MAX_CLASSES,
131        MAX_SELECTOR_NODES,
132    >
133{
134    type Item = NodeHandle;
135
136    fn next(&mut self) -> Option<Self::Item> {
137        while self.index < self.len {
138            let node = self.collection.get(self.parser, self.index);
139            self.index += 1;
140            if let Some((node, id)) = node {
141                let matches = self.selector.matches(node);
142
143                if matches {
144                    return Some(id);
145                }
146            }
147        }
148
149        None
150    }
151}