1
1
use super :: {
2
2
document:: Document ,
3
3
element:: Element ,
4
- node:: NodeId ,
4
+ node:: { Node , NodeData , NodeId } ,
5
5
selectors:: { ParseError , Selectors } ,
6
6
Specificity ,
7
7
} ;
8
+ use std:: iter:: { Enumerate , Skip } ;
8
9
9
10
/// Compile selectors from a string and create an element iterator that yields elements matching these selectors.
10
11
#[ inline]
@@ -13,32 +14,31 @@ pub(crate) fn select<'a, 'b>(
13
14
selectors : & ' b str ,
14
15
) -> Result < Select < ' a > , ParseError < ' b > > {
15
16
Selectors :: compile ( selectors) . map ( |selectors| Select {
16
- traverse : Traverse {
17
+ elements : Elements {
17
18
document,
18
- current : NodeId :: document_id ( ) ,
19
+ // Skip the dummy & document nodes
20
+ iter : document. nodes . iter ( ) . enumerate ( ) . skip ( 2 ) ,
19
21
} ,
20
22
selectors,
21
23
} )
22
24
}
23
25
24
26
/// An internal iterator that traverses a document.
25
- struct Traverse < ' a > {
27
+ struct Elements < ' a > {
26
28
document : & ' a Document ,
27
- // Current node being processed
28
- current : NodeId ,
29
+ iter : Skip < Enumerate < std:: slice:: Iter < ' a , Node > > > ,
29
30
}
30
31
31
- impl < ' a > Iterator for Traverse < ' a > {
32
+ impl < ' a > Iterator for Elements < ' a > {
32
33
type Item = Element < ' a > ;
33
34
34
35
fn next ( & mut self ) -> Option < Self :: Item > {
35
36
// Loop until we either run out of nodes or find an element node
36
37
loop {
37
- if let Some ( next) = self . document . next_node_id ( self . current ) {
38
- self . current = next;
38
+ if let Some ( ( id, node) ) = self . iter . next ( ) {
39
39
// If the current node is an element node, return it, else continue with the loop
40
- if let Some ( element) = self . document . as_element ( next ) {
41
- return Some ( element) ;
40
+ if let NodeData :: Element { element, .. } = & node . data {
41
+ return Some ( Element :: new ( self . document , NodeId :: new ( id ) , element) ) ;
42
42
}
43
43
} else {
44
44
// No more elements in the document
@@ -50,7 +50,7 @@ impl<'a> Iterator for Traverse<'a> {
50
50
51
51
/// An element iterator adaptor that yields elements matching given selectors.
52
52
pub ( crate ) struct Select < ' a > {
53
- traverse : Traverse < ' a > ,
53
+ elements : Elements < ' a > ,
54
54
/// The selectors to be matched.
55
55
selectors : Selectors ,
56
56
}
@@ -69,7 +69,7 @@ impl<'a> Iterator for Select<'a> {
69
69
#[ inline]
70
70
fn next ( & mut self ) -> Option < Element < ' a > > {
71
71
// Filter the underlying iterator to only return elements that match any of the selectors
72
- self . traverse
72
+ self . elements
73
73
. by_ref ( )
74
74
. find ( |element| self . selectors . iter ( ) . any ( |s| element. matches ( s) ) )
75
75
}
0 commit comments