@@ -18,7 +18,7 @@ pub enum ParseError {
18
18
UnexpectedPipe ,
19
19
InvalidCustomIdent ,
20
20
InvalidNameStart ,
21
- EmptyName ,
21
+ InvalidName ,
22
22
UnclosedDataTypeName ,
23
23
UnknownDataTypeName ,
24
24
}
@@ -63,22 +63,21 @@ impl Component {
63
63
}
64
64
65
65
#[ derive( Clone , Debug , PartialEq ) ]
66
- pub struct CustomIdent ( Box < [ u8 ] > ) ;
66
+ pub struct CustomIdent ( Box < str > ) ;
67
67
68
68
impl CustomIdent {
69
- fn from_bytes ( ident : & [ u8 ] ) -> Result < Self , ParseError > {
70
- if ident. eq_ignore_ascii_case ( b "inherit") ||
71
- ident. eq_ignore_ascii_case ( b "reset") ||
72
- ident. eq_ignore_ascii_case ( b "revert") ||
73
- ident. eq_ignore_ascii_case ( b "unset") ||
74
- ident. eq_ignore_ascii_case ( b "default") {
75
- return Err ( ParseError :: InvalidCustomIdent ) ;
69
+ fn from_ident ( ident : & str ) -> Result < Self , ( ) > {
70
+ if ident. eq_ignore_ascii_case ( "inherit" ) ||
71
+ ident. eq_ignore_ascii_case ( "reset" ) ||
72
+ ident. eq_ignore_ascii_case ( "revert" ) ||
73
+ ident. eq_ignore_ascii_case ( "unset" ) ||
74
+ ident. eq_ignore_ascii_case ( "default" ) {
75
+ return Err ( ( ) ) ;
76
76
}
77
- Ok ( CustomIdent ( ident. to_vec ( ) . into_boxed_slice ( ) ) )
77
+ Ok ( CustomIdent ( ident. to_owned ( ) . into_boxed_str ( ) ) )
78
78
}
79
79
}
80
80
81
-
82
81
#[ derive( Clone , Debug , PartialEq ) ]
83
82
pub enum ComponentName {
84
83
DataType ( DataType ) ,
@@ -153,7 +152,6 @@ impl DataType {
153
152
154
153
/// Parse a syntax descriptor or universal syntax descriptor.
155
154
pub fn parse_descriptor ( input : & str ) -> Result < Descriptor , ParseError > {
156
- let input = input. as_bytes ( ) ;
157
155
// 1. Strip leading and trailing ASCII whitespace from string.
158
156
let input = ascii:: trim_ascii_whitespace ( input) ;
159
157
@@ -164,7 +162,7 @@ pub fn parse_descriptor(input: &str) -> Result<Descriptor, ParseError> {
164
162
165
163
// 3. If string's length is 1, and the only code point in string is U+002A
166
164
// ASTERISK (*), return the universal syntax descriptor.
167
- if input. len ( ) == 1 && input[ 0 ] == b'*' {
165
+ if input. len ( ) == 1 && input. as_bytes ( ) [ 0 ] == b'*' {
168
166
return Ok ( Descriptor :: universal ( ) ) ;
169
167
}
170
168
@@ -184,7 +182,7 @@ pub fn parse_descriptor(input: &str) -> Result<Descriptor, ParseError> {
184
182
}
185
183
186
184
struct Parser < ' a , ' b > {
187
- input : & ' a [ u8 ] ,
185
+ input : & ' a str ,
188
186
position : usize ,
189
187
output : & ' b mut Vec < Component > ,
190
188
}
@@ -211,26 +209,13 @@ fn is_non_ascii(byte: u8) -> bool {
211
209
byte >= 0x80
212
210
}
213
211
214
- /// https://drafts.csswg.org/css-syntax-3/#digit
215
- fn is_digit ( byte : u8 ) -> bool {
216
- match byte {
217
- b'0' ...b'9' => true ,
218
- _ => false ,
219
- }
220
- }
221
-
222
212
/// https://drafts.csswg.org/css-syntax-3/#name-start-code-point
223
213
fn is_name_start ( byte : u8 ) -> bool {
224
214
is_letter ( byte) || is_non_ascii ( byte) || byte == b'_'
225
215
}
226
216
227
- /// https://drafts.csswg.org/css-syntax-3/#name-code-point
228
- fn is_name ( byte : u8 ) -> bool {
229
- is_name_start ( byte) || is_digit ( byte) || byte == b'-'
230
- }
231
-
232
217
impl < ' a , ' b > Parser < ' a , ' b > {
233
- fn new ( input : & ' a [ u8 ] , output : & ' b mut Vec < Component > ) -> Self {
218
+ fn new ( input : & ' a str , output : & ' b mut Vec < Component > ) -> Self {
234
219
Self {
235
220
input,
236
221
position : 0 ,
@@ -239,7 +224,7 @@ impl<'a, 'b> Parser<'a, 'b> {
239
224
}
240
225
241
226
fn peek ( & self ) -> Option < u8 > {
242
- self . input . get ( self . position ) . cloned ( )
227
+ self . input . as_bytes ( ) . get ( self . position ) . cloned ( )
243
228
}
244
229
245
230
fn parse ( & mut self ) -> Result < ( ) , ParseError > {
@@ -298,9 +283,10 @@ impl<'a, 'b> Parser<'a, 'b> {
298
283
None => return Err ( ParseError :: UnclosedDataTypeName ) ,
299
284
} ;
300
285
if byte != b'>' {
286
+ self . position += 1 ;
301
287
continue ;
302
288
}
303
- let ty = match DataType :: from_bytes ( & self . input [ start..self . position ] ) {
289
+ let ty = match DataType :: from_bytes ( & self . input . as_bytes ( ) [ start..self . position ] ) {
304
290
Some ( ty) => ty,
305
291
None => return Err ( ParseError :: UnknownDataTypeName ) ,
306
292
} ;
@@ -309,27 +295,6 @@ impl<'a, 'b> Parser<'a, 'b> {
309
295
}
310
296
}
311
297
312
- /// https://drafts.csswg.org/css-syntax-3/#consume-a-name
313
- /// FIXME(emilio): This should actually use cssparser's consume_name
314
- /// to handle correctly escaping and nulls.
315
- fn consume_name ( & mut self ) -> & ' a [ u8 ] {
316
- let start = self . position ;
317
-
318
- loop {
319
- let byte = match self . peek ( ) {
320
- None => return & self . input [ start..] ,
321
- Some ( b) => b,
322
- } ;
323
-
324
- if !is_name ( byte) {
325
- break ;
326
- }
327
- self . position += 1 ;
328
- }
329
-
330
- & self . input [ start..self . position ]
331
- }
332
-
333
298
fn parse_name ( & mut self ) -> Result < ComponentName , ParseError > {
334
299
let b = match self . peek ( ) {
335
300
Some ( b) => b,
@@ -345,11 +310,19 @@ impl<'a, 'b> Parser<'a, 'b> {
345
310
return Err ( ParseError :: InvalidNameStart ) ;
346
311
}
347
312
348
- let name = self . consume_name ( ) ;
349
- if name. is_empty ( ) {
350
- return Err ( ParseError :: EmptyName ) ;
351
- }
352
- return Ok ( ComponentName :: Ident ( CustomIdent :: from_bytes ( name) ?) )
313
+ let input = & self . input [ self . position ..] ;
314
+ let mut input = cssparser:: ParserInput :: new ( input) ;
315
+ let mut input = cssparser:: Parser :: new ( & mut input) ;
316
+ let name = input
317
+ . expect_ident ( )
318
+ . map_err ( |_| ( ) )
319
+ . and_then ( |name| CustomIdent :: from_ident ( name. as_ref ( ) ) ) ;
320
+ let name = match name {
321
+ Ok ( name) => name,
322
+ Err ( ..) => return Err ( ParseError :: InvalidName ) ,
323
+ } ;
324
+ self . position += input. position ( ) . byte_index ( ) ;
325
+ return Ok ( ComponentName :: Ident ( name) )
353
326
}
354
327
355
328
fn parse_multiplier ( & mut self ) -> Option < Multiplier > {
@@ -382,3 +355,22 @@ fn universal() {
382
355
assert_eq ! ( parse_descriptor( syntax) , Ok ( Descriptor :: universal( ) ) ) ;
383
356
}
384
357
}
358
+
359
+ #[ test]
360
+ fn simple_length ( ) {
361
+ macro_rules! ident {
362
+ ( $str: expr) => {
363
+ ComponentName :: Ident ( CustomIdent :: from_ident( $str) . unwrap( ) )
364
+ }
365
+ }
366
+ assert_eq ! ( parse_descriptor( "foo <length>#" ) , Ok ( Descriptor ( Box :: new( [
367
+ Component {
368
+ name: ident!( "foo" ) ,
369
+ multiplier: None ,
370
+ } ,
371
+ Component {
372
+ name: ComponentName :: DataType ( DataType :: Length ) ,
373
+ multiplier: Some ( Multiplier :: Comma ) ,
374
+ } ,
375
+ ] ) ) ) )
376
+ }
0 commit comments