@@ -10,7 +10,15 @@ pub(crate) struct Class {
1010 pub ( crate ) cache : Cache ,
1111}
1212
13- static SELECTOR_WHITESPACE : & [ char ] = & [ ' ' , '\t' , '\n' , '\r' , '\x0C' ] ;
13+ /// Bit-packed lookup for CSS selector whitespace: ' ', '\t', '\n', '\r', '\x0C'
14+ /// All whitespace chars are <= 32, so we pack them into a single u64.
15+ const WHITESPACE_MASK : u64 =
16+ ( 1 << b' ' ) | ( 1 << b'\t' ) | ( 1 << b'\n' ) | ( 1 << b'\r' ) | ( 1 << 0x0Cu8 ) ;
17+
18+ #[ inline]
19+ fn is_selector_whitespace ( b : u8 ) -> bool {
20+ b <= 32 && ( WHITESPACE_MASK >> b) & 1 != 0
21+ }
1422
1523/// This Bloom filter has 64 bits of storage and two hash functions which gives a decent false
1624/// positive rate given that most of the time an element has a very few number of classes.
@@ -61,7 +69,10 @@ impl Class {
6169 pub ( crate ) fn new ( value : StrTendril ) -> Class {
6270 // Build a Bloom filter for all element's classes
6371 let mut cache = BloomFilter :: new ( ) ;
64- let mut classes = value. split ( SELECTOR_WHITESPACE ) . filter ( |s| !s. is_empty ( ) ) ;
72+ let bytes = value. as_bytes ( ) ;
73+ let mut classes = bytes
74+ . split ( |& b| is_selector_whitespace ( b) )
75+ . filter ( |s| !s. is_empty ( ) ) ;
6576 if let Some ( class) = classes. next ( ) {
6677 // If the first class we split is the same as the input value, then we have just
6778 // a single class and a Bloom filter is not needed.
@@ -71,12 +82,10 @@ impl Class {
7182 cache : Cache :: Single ,
7283 } ;
7384 }
74- let hash = hash_class_name ( class. as_bytes ( ) ) ;
75- cache. insert_hash ( hash) ;
85+ cache. insert_hash ( hash_class_name ( class) ) ;
7686 }
7787 for class in classes {
78- let hash = hash_class_name ( class. as_bytes ( ) ) ;
79- cache. insert_hash ( hash) ;
88+ cache. insert_hash ( hash_class_name ( class) ) ;
8089 }
8190 Class {
8291 value,
@@ -87,8 +96,8 @@ impl Class {
8796 /// Manually check whether the class attribute value contains the given class.
8897 #[ inline]
8998 fn has_class_impl ( & self , name : & [ u8 ] , case_sensitivity : CaseSensitivity ) -> bool {
90- for class in self . value . split ( SELECTOR_WHITESPACE ) {
91- if case_sensitivity. eq ( class. as_bytes ( ) , name) {
99+ for class in self . value . as_bytes ( ) . split ( | & b| is_selector_whitespace ( b ) ) {
100+ if case_sensitivity. eq ( class, name) {
92101 return true ;
93102 }
94103 }
0 commit comments