@@ -6,103 +6,72 @@ extern crate proc_macro;
6
6
7
7
use proc_macro:: TokenStream ;
8
8
9
- /// Input: a `match` expression.
10
- ///
11
- /// Output: a `MAX_LENGTH` constant with the length of the longest string pattern.
12
- ///
13
- /// Panic if the arms contain non-string patterns,
14
- /// or string patterns that contains ASCII uppercase letters.
9
+ /// Implementation detail of the `match_ignore_ascii_case!` macro
15
10
#[ allow( non_snake_case) ]
16
11
#[ proc_macro]
17
- pub fn cssparser_internal__assert_ascii_lowercase__max_len ( input : TokenStream ) -> TokenStream {
18
- let expr: syn:: ExprMatch = syn:: parse_macro_input!( input) ;
19
- let strings = expr
20
- . arms
21
- . iter ( )
22
- . flat_map ( |arm| match arm. pat {
23
- syn:: Pat :: Or ( ref p) => p. cases . iter ( ) . collect ( ) ,
24
- ref p => vec ! [ p] ,
25
- } )
26
- . filter_map ( |pattern| {
27
- let expr = match pattern {
28
- syn:: Pat :: Lit ( expr) => expr,
29
- syn:: Pat :: Wild ( _) => return None ,
30
- _ => panic ! ( "expected string or wildcard pattern, got {:?}" , pattern) ,
31
- } ;
32
- match * expr. expr {
33
- syn:: Expr :: Lit ( syn:: ExprLit {
34
- lit : syn:: Lit :: Str ( ref lit) ,
35
- ..
36
- } ) => {
37
- assert_eq ! (
38
- lit. value( ) ,
39
- lit. value( ) . to_ascii_lowercase( ) ,
40
- "string patterns must be given in ASCII lowercase"
41
- ) ;
42
- Some ( lit)
43
- }
44
- _ => panic ! ( "expected string pattern, got {:?}" , expr) ,
45
- }
46
- } ) ;
47
- max_len ( strings)
48
- }
49
-
50
- /// Input: string literals with no separator
51
- ///
52
- /// Output: a `MAX_LENGTH` constant with the length of the longest string.
53
- #[ allow( non_snake_case) ]
54
- #[ proc_macro]
55
- pub fn cssparser_internal__max_len ( input : TokenStream ) -> TokenStream {
56
- struct Input ( Vec < syn:: LitStr > ) ;
12
+ pub fn cssparser_internal__match_ignore_ascii_case__support ( input : TokenStream ) -> TokenStream {
13
+ struct Input {
14
+ max_length : usize ,
15
+ }
57
16
58
17
impl syn:: parse:: Parse for Input {
59
18
fn parse ( input : syn:: parse:: ParseStream ) -> syn:: parse:: Result < Self > {
60
- let mut strings = Vec :: new ( ) ;
19
+ let mut max_length = 0 ;
61
20
while !input. is_empty ( ) {
62
- strings. push ( input. parse ( ) ?)
21
+ if input. peek ( syn:: Token ![ _] ) {
22
+ input. parse :: < syn:: Token ![ _] > ( ) . unwrap ( ) ;
23
+ continue ;
24
+ }
25
+ let lit: syn:: LitStr = input. parse ( ) ?;
26
+ let value = lit. value ( ) ;
27
+ if value. to_ascii_lowercase ( ) != value {
28
+ return Err ( syn:: Error :: new ( lit. span ( ) , "must be ASCII-lowercase" ) ) ;
29
+ }
30
+ max_length = max_length. max ( value. len ( ) ) ;
63
31
}
64
- Ok ( Self ( strings ) )
32
+ Ok ( Input { max_length } )
65
33
}
66
34
}
67
35
68
- let strings: Input = syn:: parse_macro_input!( input) ;
69
- max_len ( strings. 0 . iter ( ) )
70
- }
71
-
72
- fn max_len < ' a , I : Iterator < Item = & ' a syn:: LitStr > > ( strings : I ) -> TokenStream {
73
- let max_length = strings
74
- . map ( |s| s. value ( ) . len ( ) )
75
- . max ( )
76
- . expect ( "expected at least one string" ) ;
77
- quote:: quote!( pub ( super ) const MAX_LENGTH : usize = #max_length; ) . into ( )
36
+ let Input { max_length } = syn:: parse_macro_input!( input) ;
37
+ quote:: quote!(
38
+ pub ( super ) const MAX_LENGTH : usize = #max_length;
39
+ )
40
+ . into ( )
78
41
}
79
42
80
- /// Input: A type, followed by pairs of string literal keys and expression values. No separator.
81
- ///
82
- /// Output: a rust-phf map, with keys ASCII-lowercased:
83
- /// ```text
84
- /// static MAP: &'static ::cssparser::phf::Map<&'static str, $ValueType> = …;
85
- /// ```
43
+ /// Implementation detail of the `ascii_case_insensitive_phf_map!` macro
86
44
#[ allow( non_snake_case) ]
87
45
#[ proc_macro]
88
- pub fn cssparser_internal__phf_map ( input : TokenStream ) -> TokenStream {
46
+ pub fn cssparser_internal__ascii_case_insensitive_phf_map__support (
47
+ input : TokenStream ,
48
+ ) -> TokenStream {
89
49
struct Input {
90
50
value_type : syn:: Type ,
51
+ max_key_length : usize ,
91
52
keys : Vec < syn:: LitStr > ,
92
53
values : Vec < syn:: Expr > ,
93
54
}
94
55
95
56
impl syn:: parse:: Parse for Input {
96
57
fn parse ( input : syn:: parse:: ParseStream ) -> syn:: parse:: Result < Self > {
58
+ let value_type = input. parse ( ) ?;
59
+ let mut max_key_length = 0 ;
97
60
let mut keys = Vec :: new ( ) ;
98
61
let mut values = Vec :: new ( ) ;
99
- let value_type = input. parse ( ) ?;
100
62
while !input. is_empty ( ) {
101
- keys. push ( input. parse ( ) ?) ;
63
+ let key: syn:: LitStr = input. parse ( ) ?;
64
+ let key_value = key. value ( ) ;
65
+ max_key_length = max_key_length. max ( key_value. len ( ) ) ;
66
+ keys. push ( syn:: LitStr :: new (
67
+ & key_value. to_ascii_lowercase ( ) ,
68
+ key. span ( ) ,
69
+ ) ) ;
102
70
values. push ( input. parse ( ) ?) ;
103
71
}
104
72
Ok ( Input {
105
73
value_type,
74
+ max_key_length,
106
75
keys,
107
76
values,
108
77
} )
@@ -111,14 +80,12 @@ pub fn cssparser_internal__phf_map(input: TokenStream) -> TokenStream {
111
80
112
81
let Input {
113
82
value_type,
83
+ max_key_length,
114
84
keys,
115
85
values,
116
86
} = syn:: parse_macro_input!( input) ;
117
- let keys = keys
118
- . iter ( )
119
- . map ( |s| syn:: LitStr :: new ( & s. value ( ) . to_ascii_lowercase ( ) , s. span ( ) ) ) ;
120
-
121
87
quote:: quote!(
88
+ pub ( super ) const MAX_LENGTH : usize = #max_key_length;
122
89
pub ( super ) static MAP : Map <& ' static str , #value_type> = phf_map! {
123
90
#(
124
91
#keys => #values,
0 commit comments