Skip to content

Commit b4ba772

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

File tree

5 files changed

+79
-8
lines changed

5 files changed

+79
-8
lines changed

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
@@ -172,7 +172,7 @@ pub fn parse_hash_color(value: &[u8]) -> Result<(u8, u8, u8, f32), ()> {
172172
})
173173
}
174174

175-
ascii_case_insensitive_phf_map! {
175+
ascii_case_insensitive_map! {
176176
named_colors -> (u8, u8, u8) = {
177177
"black" => (0, 0, 0),
178178
"silver" => (192, 192, 192),

src/lib.rs

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

119+
// Re-exporting phf here means that the crate using the ascii_case_insensitive_phf_map macro do
120+
// do not have to depend on phf directly.
121+
#[cfg(feature = "fast_match_color")]
119122
#[doc(hidden)]
120123
pub use phf as _cssparser_internal_phf;
121124

src/macros.rs

Lines changed: 71 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ macro_rules! match_ignore_ascii_case {
7575
};
7676
}
7777

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

129-
static MAP: phf::Map<&'static str, $ValueType> = phf::phf_map! {
196+
static __MAP: phf::Map<&'static str, $ValueType> = phf::phf_map! {
130197
$(
131198
$key => $value,
132199
)*
@@ -142,12 +209,12 @@ macro_rules! ascii_case_insensitive_phf_map {
142209
impl $name {
143210
#[allow(dead_code)]
144211
fn entries() -> impl Iterator<Item = (&'static &'static str, &'static $ValueType)> {
145-
MAP.entries()
212+
__MAP.entries()
146213
}
147214

148215
fn get(input: &str) -> Option<&'static $ValueType> {
149216
$crate::_cssparser_internal_to_lowercase!(input, MAX_LENGTH => lowercase);
150-
MAP.get(lowercase?)
217+
__MAP.get(lowercase?)
151218
}
152219
}
153220
}

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
map -> () = {
10901090
" \t\n" => ()
10911091
}

0 commit comments

Comments
 (0)