Skip to content

Commit 0ead1b5

Browse files
committed
Use the enum discriminant trick for match_ignore_ascii_case too
1 parent 8c2f499 commit 0ead1b5

File tree

2 files changed

+22
-51
lines changed

2 files changed

+22
-51
lines changed

macros/lib.rs

Lines changed: 14 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -9,32 +9,27 @@ extern crate syn;
99

1010
use std::ascii::AsciiExt;
1111

12-
/// Find a `#[cssparser__assert_ascii_lowercase__data(string = "…", string = "…")]` attribute,
13-
/// and panic if any string contains ASCII uppercase letters.
14-
#[proc_macro_derive(cssparser__assert_ascii_lowercase,
15-
attributes(cssparser__assert_ascii_lowercase__data))]
12+
/// Panic if any string contains ASCII uppercase letters.
13+
#[proc_macro_derive(cssparser__assert_ascii_lowercase)]
1614
pub fn assert_ascii_lowercase(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
1715
let input = syn::parse_macro_input(&input.to_string()).unwrap();
18-
let data = list_attr(&input, "cssparser__assert_ascii_lowercase__data");
1916

20-
for sub_attr in data {
21-
let string = sub_attr_value(sub_attr, "string");
17+
for token in find_smuggled_tokens(&input) {
18+
let string = string_literal(token);
2219
assert_eq!(*string, string.to_ascii_lowercase(),
23-
"the expected strings must be given in ASCII lowercase");
20+
"the string patterns must be given in ASCII lowercase");
2421
}
2522

2623
"".parse().unwrap()
2724
}
2825

29-
/// Find a `#[cssparser__max_len__data(string = "…", string = "…")]` attribute,
3026
/// and emit a `MAX_LENGTH` constant with the length of the longest string.
31-
#[proc_macro_derive(cssparser__max_len,
32-
attributes(cssparser__max_len__data))]
27+
#[proc_macro_derive(cssparser__max_len)]
3328
pub fn max_len(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
3429
let input = syn::parse_macro_input(&input.to_string()).unwrap();
35-
let data = list_attr(&input, "cssparser__max_len__data");
3630

37-
let lengths = data.iter().map(|sub_attr| sub_attr_value(sub_attr, "string").len());
31+
let token_trees = find_smuggled_tokens(&input);
32+
let lengths = token_trees.iter().map(|tt| string_literal(tt).len());
3833
let max_length = lengths.max().expect("expected at least one string");
3934

4035
let tokens = quote! {
@@ -55,13 +50,11 @@ pub fn max_len(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
5550
pub fn phf_map(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
5651
let input = syn::parse_macro_input(&input.to_string()).unwrap();
5752
let name = &input.ident;
53+
5854
let token_trees = find_smuggled_tokens(&input);
5955
let value_type = &token_trees[0];
6056
let pairs: Vec<_> = token_trees[1..].chunks(2).map(|chunk| {
61-
let key = match chunk[0] {
62-
syn::TokenTree::Token(syn::Token::Literal(syn::Lit::Str(ref string, _))) => string,
63-
_ => panic!("expected string literal, got {:?}", chunk[0])
64-
};
57+
let key = string_literal(&chunk[0]);
6558
let value = &chunk[1];
6659
(key.to_ascii_lowercase(), quote!(#value).to_string())
6760
}).collect();
@@ -125,33 +118,9 @@ fn find_smuggled_tokens(input: &syn::DeriveInput) -> &[syn::TokenTree] {
125118
}
126119
}
127120

128-
/// Panic if the first attribute isn’t `#[foo(…)]` with the given name,
129-
/// or return the parameters.
130-
fn list_attr<'a>(input: &'a syn::DeriveInput, expected_name: &str) -> &'a [syn::NestedMetaItem] {
131-
for attr in &input.attrs {
132-
match attr.value {
133-
syn::MetaItem::List(ref name, ref nested) if name == expected_name => {
134-
return nested
135-
}
136-
_ => {}
137-
}
138-
}
139-
panic!("expected a {} attribute", expected_name)
140-
}
141-
142-
/// Panic if `sub_attr` is not a name-value like `foo = "…"` with the given name,
143-
/// or return the value.
144-
fn sub_attr_value<'a>(sub_attr: &'a syn::NestedMetaItem, expected_name: &str) -> &'a str {
145-
match *sub_attr {
146-
syn::NestedMetaItem::MetaItem(
147-
syn::MetaItem::NameValue(ref name, syn::Lit::Str(ref value, _))
148-
)
149-
if name == expected_name => {
150-
value
151-
}
152-
_ => {
153-
panic!("expected a `{} = \"\"` parameter to the attribute, got {:?}",
154-
expected_name, sub_attr)
155-
}
121+
fn string_literal(token: &syn::TokenTree) -> &str {
122+
match *token {
123+
syn::TokenTree::Token(syn::Token::Literal(syn::Lit::Str(ref string, _))) => string,
124+
_ => panic!("expected string literal, got {:?}", token)
156125
}
157126
}

src/lib.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -135,9 +135,10 @@ macro_rules! match_ignore_ascii_case {
135135
(@inner $value:expr, () -> ($(($string:expr => $result:expr))*) $fallback:expr ) => {
136136
{
137137
#[derive(cssparser__assert_ascii_lowercase)]
138-
#[cssparser__assert_ascii_lowercase__data($(string = $string),+)]
139-
#[allow(dead_code)]
140-
struct Dummy;
138+
#[allow(unused)]
139+
enum Dummy {
140+
Input = (0, stringify!( $( $string )+ )).0
141+
}
141142

142143
_cssparser_internal__to_lowercase!($value => lowercase, $($string),+);
143144
match lowercase {
@@ -216,9 +217,10 @@ macro_rules! ascii_case_insensitive_phf_map {
216217
macro_rules! _cssparser_internal__to_lowercase {
217218
($input: expr => $output: ident, $($string: expr),+) => {
218219
#[derive(cssparser__max_len)]
219-
#[cssparser__max_len__data($(string = $string),+)]
220-
#[allow(dead_code)]
221-
struct Dummy2;
220+
#[allow(unused)]
221+
enum Dummy2 {
222+
Input = (0, stringify!( $( $string )+ )).0
223+
}
222224

223225
// mem::uninitialized() is ok because `buffer` is only used in `_internal__to_lowercase`,
224226
// which initializes with `copy_from_slice` the part of the buffer it uses,

0 commit comments

Comments
 (0)