Skip to content

Commit

Permalink
Lazily initialize set of classes and reduce its API surface to be abl…
Browse files Browse the repository at this point in the history
…e to use a simpler collection type.
  • Loading branch information
adamreichold committed Mar 3, 2023
1 parent 5970af6 commit bdd1c1e
Showing 1 changed file with 24 additions and 17 deletions.
41 changes: 24 additions & 17 deletions src/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@

#[cfg(not(feature = "deterministic"))]
use ahash::AHashMap as HashMap;
use ahash::AHashSet as HashSet;
#[cfg(not(feature = "deterministic"))]
use std::collections::hash_map;
use std::collections::hash_set;
use std::fmt;
use std::ops::Deref;
use std::slice::Iter as SliceIter;

use crate::{CaseSensitivity, StrTendril};
use html5ever::{Attribute, LocalName, QualName};
Expand Down Expand Up @@ -228,33 +227,27 @@ pub struct Element {
/// The element name.
pub name: QualName,

/// The element classes.
pub classes: HashSet<LocalName>,

/// The element attributes.
pub attrs: Attributes,

id: OnceCell<Option<StrTendril>>,

classes: OnceCell<Vec<LocalName>>,
}

impl Element {
#[doc(hidden)]
pub fn new(name: QualName, attributes: Vec<Attribute>) -> Self {
let mut classes: HashSet<LocalName> = HashSet::new();
let mut attrs = Attributes::with_capacity(attributes.len());

for a in attributes {
if a.name.local.deref() == "class" {
classes.extend(a.value.deref().split_whitespace().map(LocalName::from));
}
attrs.insert(a.name, crate::tendril_util::make(a.value));
}
let attrs = attributes
.into_iter()
.map(|a| (a.name, crate::tendril_util::make(a.value)))
.collect();

Element {
attrs,
name,
id: OnceCell::new(),
classes,
classes: OnceCell::new(),
}
}

Expand Down Expand Up @@ -283,8 +276,22 @@ impl Element {

/// Returns an iterator over the element's classes.
pub fn classes(&self) -> Classes {
let classes = self.classes.get_or_init(|| {
let mut classes: Vec<LocalName> = self
.attrs
.iter()
.filter(|(name, _)| name.local.as_ref() == "class")
.flat_map(|(_, value)| value.split_whitespace().map(LocalName::from))
.collect();

classes.sort_unstable();
classes.dedup();

classes
});

Classes {
inner: self.classes.iter(),
inner: classes.iter(),
}
}

Expand All @@ -306,7 +313,7 @@ impl Element {
#[allow(missing_debug_implementations)]
#[derive(Clone)]
pub struct Classes<'a> {
inner: hash_set::Iter<'a, LocalName>,
inner: SliceIter<'a, LocalName>,
}

impl<'a> Iterator for Classes<'a> {
Expand Down

0 comments on commit bdd1c1e

Please sign in to comment.