11use crate :: utils:: parse_value;
22use crate :: utils:: remap;
3+ use crate :: utils:: ParamParser ;
34use crate :: { Color , ParseColorError } ;
45
56#[ cfg( feature = "named-colors" ) ]
@@ -46,23 +47,26 @@ pub fn parse(s: &str) -> Result<Color, ParseColorError> {
4647 Err ( e) => e,
4748 } ;
4849
49- if !s. is_ascii ( ) {
50- return Err ( err) ;
51- }
52-
5350 if let ( Some ( idx) , Some ( s) ) = ( s. find ( '(' ) , s. strip_suffix ( ')' ) ) {
54- let mut params = split_by_space ( & s[ idx + 1 ..] ) ;
51+ if !s. is_ascii ( ) {
52+ return Err ( err) ;
53+ }
54+
55+ let mut pp = ParamParser :: new ( & s[ idx + 1 ..] ) ;
56+ pp. space ( ) ;
5557
56- if let Some ( s) = params . next ( ) {
58+ if let Some ( s) = pp . value ( ) {
5759 if !s. eq_ignore_ascii_case ( "from" ) {
5860 return Err ( err) ;
5961 }
6062 } else {
6163 return Err ( err) ;
6264 } ;
6365
66+ pp. space ( ) ;
67+
6468 // parse next value as color
65- let color = if let Some ( s) = params . next ( ) {
69+ let color = if let Some ( s) = pp . value ( ) {
6670 if let Ok ( color) = parse ( s) {
6771 color
6872 } else {
@@ -72,21 +76,26 @@ pub fn parse(s: &str) -> Result<Color, ParseColorError> {
7276 return Err ( err) ;
7377 } ;
7478
75- let ( Some ( val1) , Some ( val2) , Some ( val3) ) = ( params. next ( ) , params. next ( ) , params. next ( ) )
79+ pp. space ( ) ;
80+
81+ let ( Some ( val1) , true , Some ( val2) , true , Some ( val3) ) =
82+ ( pp. value ( ) , pp. space ( ) , pp. value ( ) , pp. space ( ) , pp. value ( ) )
7683 else {
7784 return Err ( err) ;
7885 } ;
7986
80- let val4 = match params. next ( ) {
81- Some ( "/" ) => {
82- if let ( Some ( alpha) , None ) = ( params. next ( ) , params. next ( ) ) {
83- alpha
84- } else {
85- return Err ( err) ;
86- }
87+ pp. space ( ) ;
88+
89+ let val4 = if pp. is_end ( ) {
90+ "alpha"
91+ } else if let ( true , Some ( alpha) ) = ( pp. slash ( ) , pp. value ( ) ) {
92+ pp. space ( ) ;
93+ if !pp. is_end ( ) {
94+ return Err ( err) ;
8795 }
88- Some ( _) => return Err ( err) ,
89- None => "alpha" ,
96+ alpha
97+ } else {
98+ return Err ( err) ;
9099 } ;
91100
92101 match err {
@@ -252,9 +261,6 @@ fn parse_abs(s: &str) -> Result<Color, ParseColorError> {
252261
253262 if let ( Some ( idx) , Some ( s) ) = ( s. find ( '(' ) , s. strip_suffix ( ')' ) ) {
254263 let fname = & s[ ..idx] . trim_end ( ) ;
255- let mut params = s[ idx + 1 ..]
256- . split ( & [ ',' , '/' ] )
257- . flat_map ( str:: split_ascii_whitespace) ;
258264
259265 let err = match fname {
260266 s if s. eq_ignore_ascii_case ( "rgb" ) || s. eq_ignore_ascii_case ( "rgba" ) => {
@@ -276,13 +282,32 @@ fn parse_abs(s: &str) -> Result<Color, ParseColorError> {
276282 _ => return Err ( ParseColorError :: InvalidFunction ) ,
277283 } ;
278284
279- let ( Some ( val0) , Some ( val1) , Some ( val2) ) = ( params. next ( ) , params. next ( ) , params. next ( ) )
280- else {
285+ let s = & s[ idx + 1 ..] ;
286+
287+ if !s. is_ascii ( ) {
288+ return Err ( err) ;
289+ }
290+
291+ let mut pp = ParamParser :: new ( s) ;
292+ pp. space ( ) ;
293+
294+ let ( Some ( val0) , true , Some ( val1) , true , Some ( val2) ) = (
295+ pp. value ( ) ,
296+ pp. comma_or_space ( ) ,
297+ pp. value ( ) ,
298+ pp. comma_or_space ( ) ,
299+ pp. value ( ) ,
300+ ) else {
281301 return Err ( err) ;
282302 } ;
283303
284- let alpha = if let Some ( a) = params. next ( ) {
285- if params. next ( ) . is_some ( ) {
304+ let is_space = pp. space ( ) ;
305+
306+ let alpha = if pp. is_end ( ) {
307+ 1.0
308+ } else if let ( true , Some ( a) ) = ( pp. comma_or_slash ( ) || is_space, pp. value ( ) ) {
309+ pp. space ( ) ;
310+ if !pp. is_end ( ) {
286311 return Err ( err) ;
287312 }
288313 if let Some ( ( v, _) ) = parse_percent_or_float ( a) {
@@ -291,7 +316,7 @@ fn parse_abs(s: &str) -> Result<Color, ParseColorError> {
291316 return Err ( err) ;
292317 }
293318 } else {
294- 1.0
319+ return Err ( err ) ;
295320 } ;
296321
297322 match err {
@@ -508,62 +533,6 @@ fn parse_hex(s: &str) -> Result<Color, ParseColorError> {
508533 }
509534}
510535
511- struct SplitBySpace < ' a > {
512- s : & ' a str ,
513- pos : usize ,
514- inside : usize ,
515- }
516-
517- impl < ' a > Iterator for SplitBySpace < ' a > {
518- type Item = & ' a str ;
519-
520- fn next ( & mut self ) -> Option < Self :: Item > {
521- if self . pos >= self . s . len ( ) {
522- return None ;
523- }
524-
525- let start = self . pos ;
526- let mut found_value = false ;
527-
528- for ( i, c) in self . s [ self . pos ..] . chars ( ) . enumerate ( ) {
529- if c. is_whitespace ( ) && self . inside == 0 {
530- if found_value {
531- let end = self . pos + i;
532- self . pos = end + 1 ;
533- return Some ( & self . s [ start..end] ) ;
534- }
535- self . pos += 1 ;
536- return self . next ( ) ;
537- } else if c == '(' {
538- self . inside += 1 ;
539- found_value = true ;
540- } else if c == ')' {
541- if self . inside > 0 {
542- self . inside -= 1 ;
543- }
544- found_value = true ;
545- } else if !c. is_whitespace ( ) {
546- found_value = true ;
547- }
548- }
549-
550- if found_value {
551- self . pos = self . s . len ( ) ;
552- Some ( & self . s [ start..] )
553- } else {
554- None
555- }
556- }
557- }
558-
559- fn split_by_space ( s : & str ) -> SplitBySpace < ' _ > {
560- SplitBySpace {
561- s,
562- pos : 0 ,
563- inside : 0 ,
564- }
565- }
566-
567536// strip suffix ignore case
568537fn strip_suffix < ' a > ( s : & ' a str , suffix : & str ) -> Option < & ' a str > {
569538 if suffix. len ( ) > s. len ( ) {
@@ -700,53 +669,4 @@ mod t {
700669 cmp ! ( "abcdef" , "ABCDEF" ) ;
701670 cmp ! ( "Ff03E0cB" , "fF03e0Cb" ) ;
702671 }
703-
704- #[ test]
705- fn split_by_space_ ( ) {
706- let mut iter = split_by_space ( "" ) ;
707- assert_eq ! ( iter. next( ) , None ) ;
708-
709- let mut iter = split_by_space ( " " ) ;
710- assert_eq ! ( iter. next( ) , None ) ;
711-
712- let mut iter = split_by_space ( " ( ) " ) ;
713- assert_eq ! ( iter. next( ) , Some ( "( )" ) ) ;
714- assert_eq ! ( iter. next( ) , None ) ;
715-
716- let mut iter = split_by_space ( " x " ) ;
717- assert_eq ! ( iter. next( ) , Some ( "x" ) ) ;
718- assert_eq ! ( iter. next( ) , None ) ;
719-
720- let s = "pink" ;
721- let mut iter = split_by_space ( s) ;
722- assert_eq ! ( iter. next( ) , Some ( "pink" ) ) ;
723- assert_eq ! ( iter. next( ) , None ) ;
724-
725- let s = ") (ab cd) (" ;
726- let mut iter = split_by_space ( s) ;
727- assert_eq ! ( iter. next( ) , Some ( ")" ) ) ;
728- assert_eq ! ( iter. next( ) , Some ( "(ab cd)" ) ) ;
729- assert_eq ! ( iter. next( ) , Some ( "(" ) ) ;
730- assert_eq ! ( iter. next( ) , None ) ;
731-
732- let s = " plum teal f(1, 2, 3) abc " ;
733- let mut iter = split_by_space ( s) ;
734- assert_eq ! ( iter. next( ) , Some ( "plum" ) ) ;
735- assert_eq ! ( iter. next( ) , Some ( "teal" ) ) ;
736- assert_eq ! ( iter. next( ) , Some ( "f(1, 2, 3)" ) ) ;
737- assert_eq ! ( iter. next( ) , Some ( "abc" ) ) ;
738- assert_eq ! ( iter. next( ) , None ) ;
739-
740- let s = "from rgb(from red r g calc(b + 15) / 0.75) h w b / calc(alpha + 0.25) )" ;
741- let mut iter = split_by_space ( s) ;
742- assert_eq ! ( iter. next( ) , Some ( "from" ) ) ;
743- assert_eq ! ( iter. next( ) , Some ( "rgb(from red r g calc(b + 15) / 0.75)" ) ) ;
744- assert_eq ! ( iter. next( ) , Some ( "h" ) ) ;
745- assert_eq ! ( iter. next( ) , Some ( "w" ) ) ;
746- assert_eq ! ( iter. next( ) , Some ( "b" ) ) ;
747- assert_eq ! ( iter. next( ) , Some ( "/" ) ) ;
748- assert_eq ! ( iter. next( ) , Some ( "calc(alpha + 0.25)" ) ) ;
749- assert_eq ! ( iter. next( ) , Some ( ")" ) ) ;
750- assert_eq ! ( iter. next( ) , None ) ;
751- }
752672}
0 commit comments