5
5
use std:: fmt;
6
6
use std:: f32:: consts:: PI ;
7
7
8
- use super :: { Token , Parser , ToCss } ;
8
+ use super :: { Token , Parser , ToCss , ParseError } ;
9
9
use tokenizer:: NumericValue ;
10
10
11
11
#[ cfg( feature = "serde" ) ]
@@ -141,29 +141,30 @@ impl Color {
141
141
/// Parse a <color> value, per CSS Color Module Level 3.
142
142
///
143
143
/// FIXME(#2) Deprecated CSS2 System Colors are not supported yet.
144
- pub fn parse ( input : & mut Parser ) -> Result < Color , ( ) > {
145
- match try!( input. next ( ) ) {
146
- Token :: Hash ( value) | Token :: IDHash ( value) => parse_color_hash ( & * value) ,
147
- Token :: Ident ( value) => parse_color_keyword ( & * value) ,
148
- Token :: Function ( name) => {
149
- input. parse_nested_block ( |arguments| {
144
+ pub fn parse < ' i , ' t > ( input : & mut Parser < ' i , ' t > ) -> Result < Color , ParseError < ' i > > {
145
+ let token = try!( input. next ( ) ) ;
146
+ match token {
147
+ Token :: Hash ( ref value) | Token :: IDHash ( ref value) => parse_color_hash ( & * value) ,
148
+ Token :: Ident ( ref value) => parse_color_keyword ( & * value) ,
149
+ Token :: Function ( ref name) => {
150
+ return input. parse_nested_block ( |arguments| {
150
151
parse_color_function ( & * name, arguments)
151
- } )
152
+ } ) ;
152
153
}
153
154
_ => Err ( ( ) )
154
- }
155
+ } . map_err ( | ( ) | ParseError :: UnexpectedToken ( token ) )
155
156
}
156
157
}
157
158
158
159
159
160
#[ inline]
160
- fn rgb ( red : u8 , green : u8 , blue : u8 ) -> Result < Color , ( ) > {
161
+ fn rgb ( red : u8 , green : u8 , blue : u8 ) -> Color {
161
162
rgba ( red, green, blue, 255 )
162
163
}
163
164
164
165
#[ inline]
165
- fn rgba ( red : u8 , green : u8 , blue : u8 , alpha : u8 ) -> Result < Color , ( ) > {
166
- Ok ( Color :: RGBA ( RGBA :: new ( red, green, blue, alpha) ) )
166
+ fn rgba ( red : u8 , green : u8 , blue : u8 , alpha : u8 ) -> Color {
167
+ Color :: RGBA ( RGBA :: new ( red, green, blue, alpha) )
167
168
}
168
169
169
170
@@ -359,29 +360,29 @@ fn from_hex(c: u8) -> Result<u8, ()> {
359
360
fn parse_color_hash ( value : & str ) -> Result < Color , ( ) > {
360
361
let value = value. as_bytes ( ) ;
361
362
match value. len ( ) {
362
- 8 => rgba (
363
+ 8 => Ok ( rgba (
363
364
try!( from_hex ( value[ 0 ] ) ) * 16 + try!( from_hex ( value[ 1 ] ) ) ,
364
365
try!( from_hex ( value[ 2 ] ) ) * 16 + try!( from_hex ( value[ 3 ] ) ) ,
365
366
try!( from_hex ( value[ 4 ] ) ) * 16 + try!( from_hex ( value[ 5 ] ) ) ,
366
367
try!( from_hex ( value[ 6 ] ) ) * 16 + try!( from_hex ( value[ 7 ] ) ) ,
367
- ) ,
368
- 6 => rgb (
368
+ ) ) ,
369
+ 6 => Ok ( rgb (
369
370
try!( from_hex ( value[ 0 ] ) ) * 16 + try!( from_hex ( value[ 1 ] ) ) ,
370
371
try!( from_hex ( value[ 2 ] ) ) * 16 + try!( from_hex ( value[ 3 ] ) ) ,
371
372
try!( from_hex ( value[ 4 ] ) ) * 16 + try!( from_hex ( value[ 5 ] ) ) ,
372
- ) ,
373
- 4 => rgba (
373
+ ) ) ,
374
+ 4 => Ok ( rgba (
374
375
try!( from_hex ( value[ 0 ] ) ) * 17 ,
375
376
try!( from_hex ( value[ 1 ] ) ) * 17 ,
376
377
try!( from_hex ( value[ 2 ] ) ) * 17 ,
377
378
try!( from_hex ( value[ 3 ] ) ) * 17 ,
378
- ) ,
379
- 3 => rgb (
379
+ ) ) ,
380
+ 3 => Ok ( rgb (
380
381
try!( from_hex ( value[ 0 ] ) ) * 17 ,
381
382
try!( from_hex ( value[ 1 ] ) ) * 17 ,
382
383
try!( from_hex ( value[ 2 ] ) ) * 17 ,
383
- ) ,
384
- _ => Err ( ( ) )
384
+ ) ) ,
385
+ _ => Err ( ( ) ) ,
385
386
}
386
387
}
387
388
@@ -401,11 +402,11 @@ fn clamp_256_f32(val: f32) -> u8 {
401
402
}
402
403
403
404
#[ inline]
404
- fn parse_color_function ( name : & str , arguments : & mut Parser ) -> Result < Color , ( ) > {
405
+ fn parse_color_function < ' i , ' t > ( name : & str , arguments : & mut Parser < ' i , ' t > ) -> Result < Color , ParseError < ' i > > {
405
406
let ( red, green, blue, uses_commas) = match_ignore_ascii_case ! { name,
406
407
"rgb" | "rgba" => parse_rgb_components_rgb( arguments) ?,
407
408
"hsl" | "hsla" => parse_rgb_components_hsl( arguments) ?,
408
- _ => return Err ( ( ) )
409
+ _ => return Err ( ParseError :: UnexpectedToken ( Token :: Ident ( name . to_owned ( ) . into ( ) ) ) ) ,
409
410
} ;
410
411
411
412
let alpha = if !arguments. is_exhausted ( ) {
@@ -414,7 +415,7 @@ fn parse_color_function(name: &str, arguments: &mut Parser) -> Result<Color, ()>
414
415
} else {
415
416
match try!( arguments. next ( ) ) {
416
417
Token :: Delim ( '/' ) => { } ,
417
- _ => return Err ( ( ) )
418
+ t => return Err ( ParseError :: UnexpectedToken ( t ) ) ,
418
419
} ;
419
420
} ;
420
421
let token = try!( arguments. next ( ) ) ;
@@ -425,21 +426,21 @@ fn parse_color_function(name: &str, arguments: &mut Parser) -> Result<Color, ()>
425
426
Token :: Percentage ( ref v) => {
426
427
clamp_unit_f32 ( v. unit_value )
427
428
}
428
- _ => {
429
- return Err ( ( ) )
429
+ t => {
430
+ return Err ( ParseError :: UnexpectedToken ( t ) )
430
431
}
431
432
}
432
433
} else {
433
434
255
434
435
} ;
435
436
436
437
try!( arguments. expect_exhausted ( ) ) ;
437
- rgba ( red, green, blue, alpha)
438
+ Ok ( rgba ( red, green, blue, alpha) )
438
439
}
439
440
440
441
441
442
#[ inline]
442
- fn parse_rgb_components_rgb ( arguments : & mut Parser ) -> Result < ( u8 , u8 , u8 , bool ) , ( ) > {
443
+ fn parse_rgb_components_rgb < ' i , ' t > ( arguments : & mut Parser < ' i , ' t > ) -> Result < ( u8 , u8 , u8 , bool ) , ParseError < ' i > > {
443
444
let red: u8 ;
444
445
let green: u8 ;
445
446
let blue: u8 ;
@@ -456,7 +457,7 @@ fn parse_rgb_components_rgb(arguments: &mut Parser) -> Result<(u8, u8, u8, bool)
456
457
uses_commas = true ;
457
458
try!( arguments. expect_number ( ) )
458
459
}
459
- _ => return Err ( ( ) )
460
+ t => return Err ( ParseError :: UnexpectedToken ( t ) )
460
461
} ) ;
461
462
if uses_commas {
462
463
try!( arguments. expect_comma ( ) ) ;
@@ -471,36 +472,38 @@ fn parse_rgb_components_rgb(arguments: &mut Parser) -> Result<(u8, u8, u8, bool)
471
472
uses_commas = true ;
472
473
try!( arguments. expect_percentage ( ) )
473
474
}
474
- _ => return Err ( ( ) )
475
+ t => return Err ( ParseError :: UnexpectedToken ( t ) )
475
476
} ) ;
476
477
if uses_commas {
477
478
try!( arguments. expect_comma ( ) ) ;
478
479
}
479
480
blue = clamp_unit_f32 ( try!( arguments. expect_percentage ( ) ) ) ;
480
481
}
481
- _ => return Err ( ( ) )
482
+ t => return Err ( ParseError :: UnexpectedToken ( t ) )
482
483
} ;
483
484
return Ok ( ( red, green, blue, uses_commas) ) ;
484
485
}
485
486
486
487
#[ inline]
487
- fn parse_rgb_components_hsl ( arguments : & mut Parser ) -> Result < ( u8 , u8 , u8 , bool ) , ( ) > {
488
+ fn parse_rgb_components_hsl < ' i , ' t > ( arguments : & mut Parser < ' i , ' t > ) -> Result < ( u8 , u8 , u8 , bool ) , ParseError < ' i > > {
488
489
let mut uses_commas = false ;
489
490
// Hue given as an angle
490
491
// https://drafts.csswg.org/css-values/#angles
491
- let hue_degrees = match try!( arguments. next ( ) ) {
492
- Token :: Number ( NumericValue { value : v, .. } ) => v,
493
- Token :: Dimension ( NumericValue { value : v, .. } , unit) => {
492
+ let token = try!( arguments. next ( ) ) ;
493
+ let hue_degrees = match token {
494
+ Token :: Number ( NumericValue { value : v, .. } ) => Ok ( v) ,
495
+ Token :: Dimension ( NumericValue { value : v, .. } , ref unit) => {
494
496
match_ignore_ascii_case ! { & * unit,
495
- "deg" => v ,
496
- "grad" => v * 360. / 400. ,
497
- "rad" => v * 360. / ( 2. * PI ) ,
498
- "turn" => v * 360. ,
499
- _ => return Err ( ( ) )
497
+ "deg" => Ok ( v ) ,
498
+ "grad" => Ok ( v * 360. / 400. ) ,
499
+ "rad" => Ok ( v * 360. / ( 2. * PI ) ) ,
500
+ "turn" => Ok ( v * 360. ) ,
501
+ _ => Err ( ( ) ) ,
500
502
}
501
503
}
502
- _ => return Err ( ( ) )
504
+ t => return Err ( ParseError :: UnexpectedToken ( t ) )
503
505
} ;
506
+ let hue_degrees = try!( hue_degrees. map_err ( |( ) | ParseError :: UnexpectedToken ( token) ) ) ;
504
507
// Subtract an integer before rounding, to avoid some rounding errors:
505
508
let hue_normalized_degrees = hue_degrees - 360. * ( hue_degrees / 360. ) . floor ( ) ;
506
509
let hue = hue_normalized_degrees / 360. ;
@@ -513,7 +516,7 @@ fn parse_rgb_components_hsl(arguments: &mut Parser) -> Result<(u8, u8, u8, bool)
513
516
uses_commas = true ;
514
517
try!( arguments. expect_percentage ( ) )
515
518
}
516
- _ => return Err ( ( ) )
519
+ t => return Err ( ParseError :: UnexpectedToken ( t ) )
517
520
} ;
518
521
let saturation = saturation. max ( 0. ) . min ( 1. ) ;
519
522
0 commit comments