@@ -89,202 +89,13 @@ pub use serializer::{ToCss, CssStringWriter, serialize_identifier, serialize_str
89
89
pub use parser:: { Parser , Delimiter , Delimiters , SourcePosition } ;
90
90
pub use unicode_range:: UnicodeRange ;
91
91
92
- /// Expands to an expression equivalent to a `match` with string patterns,
93
- /// but matching is case-insensitive in the ASCII range.
94
- ///
95
- /// Requirements:
96
- ///
97
- /// * The `cssparser_macros` crate must also be imported at the crate root
98
- /// * The patterns must not contain ASCII upper case letters. (They must be already be lower-cased.)
99
- ///
100
- /// # Example
101
- ///
102
- /// ```rust
103
- /// #[macro_use] extern crate cssparser;
104
- /// #[macro_use] extern crate cssparser_macros;
105
- ///
106
- /// # fn main() {} // Make doctest not wrap everythig in its own main
107
- /// # fn dummy(function_name: &String) { let _ =
108
- /// match_ignore_ascii_case! { &function_name,
109
- /// "rgb" => parse_rgb(..),
110
- /// "rgba" => parse_rgba(..),
111
- /// "hsl" => parse_hsl(..),
112
- /// "hsla" => parse_hsla(..),
113
- /// _ => Err("unknown function")
114
- /// }
115
- /// # ;}
116
- /// # use std::ops::RangeFull;
117
- /// # fn parse_rgb(_: RangeFull) -> Result<(), &'static str> { Err("") }
118
- /// # fn parse_rgba(_: RangeFull) -> Result<(), &'static str> { Err("") }
119
- /// # fn parse_hsl(_: RangeFull) -> Result<(), &'static str> { Err("") }
120
- /// # fn parse_hsla(_: RangeFull) -> Result<(), &'static str> { Err("") }
121
- /// ```
122
- #[ macro_export]
123
- macro_rules! match_ignore_ascii_case {
124
- // parse the last case plus the fallback
125
- ( @inner $value: expr, ( $string: expr => $result: expr, _ => $fallback: expr) -> ( $( $parsed: tt) * ) ) => {
126
- match_ignore_ascii_case!( @inner $value, ( ) -> ( $( $parsed) * ( $string => $result) ) $fallback)
127
- } ;
92
+ #[ doc( hidden) ] pub use macros:: _internal__to_lowercase;
128
93
129
- // parse a case (not the last one)
130
- ( @inner $value: expr, ( $string: expr => $result: expr, $( $rest: tt) * ) -> ( $( $parsed: tt) * ) ) => {
131
- match_ignore_ascii_case!( @inner $value, ( $( $rest) * ) -> ( $( $parsed) * ( $string => $result) ) )
132
- } ;
133
-
134
- // finished parsing
135
- ( @inner $value: expr, ( ) -> ( $( ( $string: expr => $result: expr) ) * ) $fallback: expr ) => {
136
- {
137
- _cssparser_internal__pretend_proc_macro! {
138
- cssparser__assert_ascii_lowercase!( $( $string ) + )
139
- }
140
-
141
- {
142
- _cssparser_internal__to_lowercase!( $value => lowercase, $( $string) ,+) ;
143
- match lowercase {
144
- $(
145
- Some ( $string) => $result,
146
- ) +
147
- _ => $fallback
148
- }
149
- }
150
- }
151
- } ;
152
-
153
- // entry point, start parsing
154
- ( $value: expr, $( $rest: tt) * ) => {
155
- match_ignore_ascii_case!( @inner $value, ( $( $rest) * ) -> ( ) )
156
- } ;
157
- }
158
-
159
- /// Define a function `$name(&str) -> Option<&'static $ValueType>`
160
- ///
161
- /// The function finds a match for the input string
162
- /// in a [`phf` map](https://github.com/sfackler/rust-phf)
163
- /// and returns a reference to the corresponding value.
164
- /// Matching is case-insensitive in the ASCII range.
165
- ///
166
- /// The `phf` and `cssparser_macros` crates must also be imported at the crate root
167
- ///
168
- /// ## Example:
169
- ///
170
- /// ```rust
171
- /// extern crate phf;
172
- /// #[macro_use] extern crate cssparser;
173
- /// #[macro_use] extern crate cssparser_macros;
174
- ///
175
- /// # fn main() {} // Make doctest not wrap everythig in its own main
176
- ///
177
- /// fn color_rgb(input: &str) -> Option<(u8, u8, u8)> {
178
- /// ascii_case_insensitive_phf_map! {
179
- /// keyword -> (u8, u8, u8) = {
180
- /// "red" => (255, 0, 0),
181
- /// "green" => (0, 255, 0),
182
- /// "blue" => (0, 0, 255),
183
- /// }
184
- /// }
185
- /// keyword(input).cloned()
186
- /// }
187
- #[ macro_export]
188
- macro_rules! ascii_case_insensitive_phf_map {
189
- ( $name: ident -> $ValueType: ty = { $( $key: expr => $value: expr, ) * } ) => {
190
- fn $name( input: & str ) -> Option <& ' static $ValueType> {
191
- _cssparser_internal__pretend_proc_macro! {
192
- cssparser__phf_map!( ( $ValueType) $( $key ( $value) ) + )
193
- }
194
-
195
- {
196
- _cssparser_internal__to_lowercase!( input => lowercase, $( $key) ,+) ;
197
- lowercase. and_then( |s| MAP . get( s) )
198
- }
199
- }
200
- }
201
- }
202
-
203
- /// Implementation detail of match_ignore_ascii_case! and ascii_case_insensitive_phf_map! macros.
204
- ///
205
- /// **This macro is not part of the public API. It can change or be removed between any versions.**
206
- ///
207
- /// * Check at compile-time that none of the `$string`s contain ASCII uppercase letters
208
- /// * Define a local variable named `$output` to the result of calling `_internal__to_lowercase`
209
- /// with a stack-allocated buffer as long as the longest `$string`.
210
- #[ macro_export]
211
- #[ doc( hidden) ]
212
- macro_rules! _cssparser_internal__to_lowercase {
213
- ( $input: expr => $output: ident, $( $string: expr) ,+) => {
214
- _cssparser_internal__pretend_proc_macro! {
215
- cssparser__max_len!( $( $string ) + )
216
- }
217
-
218
- // mem::uninitialized() is ok because `buffer` is only used in `_internal__to_lowercase`,
219
- // which initializes with `copy_from_slice` the part of the buffer it uses,
220
- // before it uses it.
221
- #[ allow( unsafe_code) ]
222
- // MAX_LENGTH is generated by cssparser__max_len
223
- let mut buffer: [ u8 ; MAX_LENGTH ] = unsafe {
224
- :: std:: mem:: uninitialized( )
225
- } ;
226
- let input: & str = $input;
227
- let $output = $crate:: _internal__to_lowercase( & mut buffer, input) ;
228
- }
229
- }
230
-
231
- /// Implementation detail of match_ignore_ascii_case! and ascii_case_insensitive_phf_map! macros.
232
- ///
233
- /// **This macro is not part of the public API. It can change or be removed between any versions.**
234
- #[ macro_export]
235
- #[ doc( hidden) ]
236
- macro_rules! _cssparser_internal__pretend_proc_macro {
237
- ( $macro_name: ident ! ( $( $tt: tt) * ) ) => {
238
- #[ derive( $macro_name) ]
239
- #[ allow( unused) ]
240
- enum Dummy {
241
- Input = ( 0 , stringify!( $( $tt ) * ) ) . 0
242
- }
243
- }
244
- }
245
-
246
- /// Implementation detail of match_ignore_ascii_case! and ascii_case_insensitive_phf_map! macros.
247
- ///
248
- /// **This function is not part of the public API. It can change or be removed between any verisons.**
249
- ///
250
- /// Return `input`, lower-cased, unless larger than `buffer`
251
- /// which is used temporary space for lower-casing a copy of `input` if necessary.
252
- #[ doc( hidden) ]
253
- #[ allow( non_snake_case) ]
254
- pub fn _internal__to_lowercase < ' a > ( buffer : & ' a mut [ u8 ] , input : & ' a str ) -> Option < & ' a str > {
255
- if let Some ( buffer) = buffer. get_mut ( ..input. len ( ) ) {
256
- if let Some ( first_uppercase) = input. bytes ( ) . position ( |byte| matches ! ( byte, b'A' ...b'Z' ) ) {
257
- buffer. copy_from_slice ( input. as_bytes ( ) ) ;
258
- std:: ascii:: AsciiExt :: make_ascii_lowercase ( & mut buffer[ first_uppercase..] ) ;
259
- // `buffer` was initialized to a copy of `input` (which is &str so well-formed UTF-8)
260
- // then lowercased (which preserves UTF-8 well-formedness)
261
- unsafe {
262
- Some ( :: std:: str:: from_utf8_unchecked ( buffer) )
263
- }
264
- } else {
265
- // Input is already lower-case
266
- Some ( input)
267
- }
268
- } else {
269
- // Input is longer than buffer, which has the length of the longest expected string:
270
- // none of the expected strings would match.
271
- None
272
- }
273
- }
94
+ #[ macro_use]
95
+ mod macros;
274
96
275
97
mod rules_and_declarations;
276
98
277
- #[ cfg( feature = "dummy_match_byte" ) ]
278
- macro_rules! match_byte {
279
- ( $value: expr, $( $rest: tt) * ) => {
280
- match $value {
281
- $(
282
- $rest
283
- ) +
284
- }
285
- } ;
286
- }
287
-
288
99
#[ cfg( feature = "dummy_match_byte" ) ]
289
100
mod tokenizer;
290
101
0 commit comments