Skip to content

Commit 7e5ee83

Browse files
committed
Make phf for color matching optional
Signed-off-by: Nico Burns <nico@nicoburns.com>
1 parent 788e81a commit 7e5ee83

5 files changed

Lines changed: 74 additions & 10 deletions

File tree

Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ encoding_rs = "0.8"
2323
cssparser-macros = { path = "./macros", version = "0.6.1", optional = true }
2424
dtoa-short = "0.3"
2525
itoa = "1.0"
26-
phf = { version = "0.13.1", features = ["macros"] }
26+
phf = { version = "0.13.1", features = ["macros"], optional = true }
2727
serde = { version = "1.0", features = ["derive"], optional = true }
2828
malloc_size_of = { version = "0.1", default-features = false, optional = true }
2929
smallvec = "1.0"
@@ -33,9 +33,10 @@ inherits = "release"
3333
debug = true
3434

3535
[features]
36-
default = ["fast_match_byte"]
36+
default = ["fast_match_byte", "fast_match_color"]
3737
bench = []
3838
fast_match_byte = ["dep:cssparser-macros"]
39+
fast_match_color = ["dep:phf"]
3940
# Useful for skipping tests when execution is slow, e.g., under miri
4041
skip_long_tests = []
4142

src/color.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ pub fn parse_hash_color(value: &[u8]) -> Result<(u8, u8, u8, f32), ()> {
173173
})
174174
}
175175

176-
ascii_case_insensitive_phf_map! {
176+
ascii_case_insensitive_map! {
177177
static NAMED_COLORS : (u8, u8, u8) = {
178178
"black" => (0, 0, 0),
179179
"silver" => (192, 192, 192),

src/lib.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -116,9 +116,6 @@ mod mac {
116116
}
117117
}
118118

119-
#[doc(hidden)]
120-
pub use phf as _cssparser_internal_phf;
121-
122119
#[macro_use]
123120
mod macros;
124121

src/macros.rs

Lines changed: 69 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ macro_rules! match_ignore_ascii_case {
7373
};
7474
}
7575

76+
#[cfg(not(feature = "fast_match_color"))]
77+
#[macro_export]
7678
/// Define a function `$name(&str) -> Option<&'static $ValueType>`
7779
///
7880
/// The function finds a match for the input string
@@ -86,7 +88,7 @@ macro_rules! match_ignore_ascii_case {
8688
/// # fn main() {} // Make doctest not wrap everything in its own main
8789
///
8890
/// fn color_rgb(input: &str) -> Option<(u8, u8, u8)> {
89-
/// cssparser::ascii_case_insensitive_phf_map! {
91+
/// cssparser::ascii_case_insensitive_map! {
9092
/// static KEYWORDS : (u8, u8, u8) = {
9193
/// "red" => (255, 0, 0),
9294
/// "green" => (0, 255, 0),
@@ -98,13 +100,77 @@ macro_rules! match_ignore_ascii_case {
98100
/// ```
99101
///
100102
/// You can also iterate over the map entries by using `keywords::entries()`.
103+
macro_rules! ascii_case_insensitive_map {
104+
(static $name:ident : $ValueType:ty = { $( $key:tt => $value:expr ),+ }) => {
105+
ascii_case_insensitive_map!(static $name : $ValueType = { $( $key => $value, )+ })
106+
};
107+
(static $name:ident : $ValueType:ty = { $( $key:tt => $value:expr, )+ }) => {
108+
109+
// While the obvious choice for this would be an inner module, it's not possible to
110+
// reference from types from there, see:
111+
// <https://github.com/rust-lang/rust/issues/114369>
112+
//
113+
// So we abuse a struct with static associated functions instead.
114+
#[allow(non_camel_case_types)]
115+
struct $name;
116+
impl $name {
117+
#[allow(dead_code)]
118+
fn entries() -> impl Iterator<Item = (&'static &'static str, &'static $ValueType)> {
119+
[ $((&$key, &$value),)* ].iter().copied()
120+
}
121+
122+
fn get(input: &str) -> Option<&'static $ValueType> {
123+
$crate::match_ignore_ascii_case!(input,
124+
$($key => Some(&$value),)*
125+
_ => None,
126+
)
127+
}
128+
}
129+
}
130+
}
131+
132+
#[cfg(feature = "fast_match_color")]
133+
#[macro_export]
134+
/// Define a function `$name(&str) -> Option<&'static $ValueType>`
135+
///
136+
/// The function finds a match for the input string
137+
/// in a [`phf` map](https://github.com/sfackler/rust-phf)
138+
/// and returns a reference to the corresponding value.
139+
/// Matching is case-insensitive in the ASCII range.
140+
///
141+
/// ## Example:
142+
///
143+
/// ```rust
144+
/// # fn main() {} // Make doctest not wrap everything in its own main
145+
///
146+
/// fn color_rgb(input: &str) -> Option<(u8, u8, u8)> {
147+
/// cssparser::ascii_case_insensitive_map! {
148+
/// static KEYWORDS : (u8, u8, u8) = {
149+
/// "red" => (255, 0, 0),
150+
/// "green" => (0, 255, 0),
151+
/// "blue" => (0, 0, 255),
152+
/// }
153+
/// }
154+
/// KEYWORDS::get(input).cloned()
155+
/// }
156+
/// ```
157+
///
158+
/// You can also iterate over the map entries by using `keywords::entries()`.
159+
macro_rules! ascii_case_insensitive_map {
160+
($($any:tt)+) => {
161+
$crate::ascii_case_insensitive_phf_map!($($any)+);
162+
};
163+
}
164+
165+
/// Fast implementation of `ascii_case_insensitive_map!` using a phf map.
166+
/// See `ascii_case_insensitive_map!` above for docs
167+
#[cfg(feature = "fast_match_color")]
101168
#[macro_export]
102169
macro_rules! ascii_case_insensitive_phf_map {
103170
(static $name:ident : $ValueType:ty = { $( $key:tt => $value:expr ),+ }) => {
104171
ascii_case_insensitive_phf_map!(static $name : $ValueType = { $( $key => $value, )+ })
105172
};
106173
(static $name:ident : $ValueType:ty = { $( $key:tt => $value:expr, )+ }) => {
107-
use $crate::_cssparser_internal_phf as phf;
108174

109175
#[inline(always)]
110176
const fn const_usize_max(a: usize, b: usize) -> usize {
@@ -124,7 +190,7 @@ macro_rules! ascii_case_insensitive_phf_map {
124190
maxlen
125191
};
126192

127-
static __MAP: phf::Map<&'static str, $ValueType> = phf::phf_map! {
193+
static __MAP: ::phf::Map<&'static str, $ValueType> = ::phf::phf_map! {
128194
$(
129195
$key => $value,
130196
)*

src/tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1085,7 +1085,7 @@ fn one_component_value_to_json(token: Token, input: &mut Parser) -> Value {
10851085
/// including in string literals.
10861086
#[test]
10871087
fn procedural_masquerade_whitespace() {
1088-
ascii_case_insensitive_phf_map! {
1088+
ascii_case_insensitive_map! {
10891089
static MAP : () = {
10901090
" \t\n" => ()
10911091
}

0 commit comments

Comments
 (0)