Skip to content

Commit 3eb3d1a

Browse files
committed
perf: Iterate over nodes slice directly
1 parent 15fdf44 commit 3eb3d1a

File tree

3 files changed

+14
-23
lines changed

3 files changed

+14
-23
lines changed

css-inline/src/html/document.rs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ use std::{io, io::Write, iter::successors};
3636
/// relationship with its descendants.
3737
#[derive(Debug)]
3838
pub(crate) struct Document {
39-
nodes: Vec<Node>,
39+
pub(crate) nodes: Vec<Node>,
4040
/// Ids of `style` nodes.
4141
styles: Vec<NodeId>,
4242
/// Ids of `link` nodes, specifically those with the `rel` attribute value set as `stylesheet`.
@@ -61,11 +61,6 @@ impl Document {
6161
}
6262
}
6363

64-
#[inline]
65-
pub(super) fn next_node_id(&self, node_id: NodeId) -> Option<NodeId> {
66-
node_id.next().filter(|&next| next.get() < self.nodes.len())
67-
}
68-
6964
#[inline]
7065
pub(super) fn as_element(&self, node_id: NodeId) -> Option<Element<'_>> {
7166
if let NodeData::Element { element, .. } = &self[node_id].data {

css-inline/src/html/iter.rs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
use super::{
22
document::Document,
33
element::Element,
4-
node::NodeId,
4+
node::{Node, NodeData, NodeId},
55
selectors::{ParseError, Selectors},
66
Specificity,
77
};
8+
use std::iter::{Enumerate, Skip};
89

910
/// Compile selectors from a string and create an element iterator that yields elements matching these selectors.
1011
#[inline]
@@ -13,32 +14,31 @@ pub(crate) fn select<'a, 'b>(
1314
selectors: &'b str,
1415
) -> Result<Select<'a>, ParseError<'b>> {
1516
Selectors::compile(selectors).map(|selectors| Select {
16-
traverse: Traverse {
17+
elements: Elements {
1718
document,
18-
current: NodeId::document_id(),
19+
// Skip the dummy & document nodes
20+
iter: document.nodes.iter().enumerate().skip(2),
1921
},
2022
selectors,
2123
})
2224
}
2325

2426
/// An internal iterator that traverses a document.
25-
struct Traverse<'a> {
27+
struct Elements<'a> {
2628
document: &'a Document,
27-
// Current node being processed
28-
current: NodeId,
29+
iter: Skip<Enumerate<std::slice::Iter<'a, Node>>>,
2930
}
3031

31-
impl<'a> Iterator for Traverse<'a> {
32+
impl<'a> Iterator for Elements<'a> {
3233
type Item = Element<'a>;
3334

3435
fn next(&mut self) -> Option<Self::Item> {
3536
// Loop until we either run out of nodes or find an element node
3637
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() {
3939
// 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));
4242
}
4343
} else {
4444
// No more elements in the document
@@ -50,7 +50,7 @@ impl<'a> Iterator for Traverse<'a> {
5050

5151
/// An element iterator adaptor that yields elements matching given selectors.
5252
pub(crate) struct Select<'a> {
53-
traverse: Traverse<'a>,
53+
elements: Elements<'a>,
5454
/// The selectors to be matched.
5555
selectors: Selectors,
5656
}
@@ -69,7 +69,7 @@ impl<'a> Iterator for Select<'a> {
6969
#[inline]
7070
fn next(&mut self) -> Option<Element<'a>> {
7171
// Filter the underlying iterator to only return elements that match any of the selectors
72-
self.traverse
72+
self.elements
7373
.by_ref()
7474
.find(|element| self.selectors.iter().any(|s| element.matches(s)))
7575
}

css-inline/src/html/node.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,6 @@ impl NodeId {
6969
pub(super) fn get(self) -> usize {
7070
self.0.get()
7171
}
72-
#[inline]
73-
pub(super) fn next(self) -> Option<NodeId> {
74-
self.get().checked_add(1).map(NodeId::new)
75-
}
7672
}
7773

7874
/// Data associated with a `Node`.

0 commit comments

Comments
 (0)