servo: Changed color parsing to return an option instead of defaulting to black
authorMargaret Meyerhofer <mmeyerhofer@mozilla.com>
Thu, 19 Jul 2012 13:13:05 -0700
changeset 470871 c8babdc4a7ee8b1f810184d5c0eb771e10f41f37
parent 470870 5c62c6e7a625d0539dcbdf789424967d9a81a64a
child 470872 02700e81515c011b0ff521c931eeb25aa4278ba0
push id44079
push userbmo:gps@mozilla.com
push dateSat, 04 Feb 2017 00:14:49 +0000
servo: Changed color parsing to return an option instead of defaulting to black Source-Repo: https://github.com/servo/servo Source-Revision: 830a41ad94a5d72d96cced9badebbb340784ed7b
servo/src/servo/parser/css_builder.rs
servo/src/servo/util/color.rs
--- a/servo/src/servo/parser/css_builder.rs
+++ b/servo/src/servo/parser/css_builder.rs
@@ -152,26 +152,27 @@ impl parser_methods of parser_methods fo
         let mut desc_list : ~[StyleDeclaration]= ~[];
         
         // Get the description to be applied to the selector
         loop {
             let tok = self.get();
             alt tok {
               EndDescription { break; }
               Description(prop, val) {
-                alt prop {
+                let desc = alt prop {
                   // TODO: have color parsing return an option instead of a real value
-                  ~"background-color" { push(desc_list, BackgroundColor(parse_color(val))); }
-                  ~"color" { push(desc_list, TextColor(parse_color(val))); }
-                  ~"display" { parse_display_type(val).map(|res| push(desc_list, Display(res))); }
-                  ~"font-size" { parse_font_size(val).map(|res| push(desc_list, FontSize(res))); }
-                  ~"height" { parse_size(val).map(|res| push(desc_list, Height(res))); }
-                  ~"width" { parse_size(val).map(|res| push(desc_list, Width(res))); }
-                  _ { #debug["Recieved unknown style property '%s'", val]; }
-                }
+                  ~"background-color" { parse_color(val).map(|res| BackgroundColor(res)) }
+                  ~"color" { parse_color(val).map(|res| TextColor(res)) }
+                  ~"display" { parse_display_type(val).map(|res| Display(res)) }
+                  ~"font-size" { parse_font_size(val).map(|res| FontSize(res)) }
+                  ~"height" { parse_size(val).map(|res| Height(res)) }
+                  ~"width" { parse_size(val).map(|res| Width(res)) }
+                  _ { #debug["Recieved unknown style property '%s'", val]; none }
+                };
+                desc.map(|res| push(desc_list, res));
               }
               Eof { ret none; }
               StartDescription | Descendant | Child | Sibling | Comma | Element(_) | Attr(_)  {
                 fail #fmt["Unexpected token %? in description", tok]; 
               }
             }
         }
         
--- a/servo/src/servo/util/color.rs
+++ b/servo/src/servo/util/color.rs
@@ -61,26 +61,24 @@ impl methods for Color {
         #fmt["rgba(%u,%u,%u,%f)", self.red as uint, self.green as uint,
              self.blue as uint, self.alpha]
     }
 }
 
 mod parsing {
     export parse_color;
 
-    // TODO, fail by ignoring the rule instead of setting the
-    // color to black
-    fn fail_unrecognized(col : ~str) -> Color {
+    fn fail_unrecognized(col : ~str) -> option<Color> {
         #warn["Unrecognized color %s", col];
-        ret  black();
+        ret none;
     }
 
     #[doc="Match an exact color keyword."]
-    fn parse_by_name(color : ~str) -> Color {
-        alt color.to_lower() {
+    fn parse_by_name(color : ~str) -> option<Color> {
+        let col = alt color.to_lower() {
           ~"black"   { black()   }
           ~"silver"  { silver()  }
           ~"gray"    { gray()    }
           ~"grey"    { gray()    }
           ~"white"   { white()   }
           ~"maroon"  { maroon()  }
           ~"red"     { red()     }
           ~"purple"  { purple()  }
@@ -88,152 +86,158 @@ mod parsing {
           ~"green"   { green()   }
           ~"lime"    { lime()    }
           ~"olive"   { olive()   }
           ~"yellow"  { yellow()  }
           ~"navy"    { navy()    }
           ~"blue"    { blue()    }
           ~"teal"    { teal()    }
           ~"aqua"    { aqua()    }
-          _         { fail_unrecognized(color) }
-        }
+          _          { ret fail_unrecognized(color) }
+        };
+
+        ret some(col);
     }
     
     #[doc="Parses a color specification in the form rgb(foo,bar,baz)"]
-    fn parse_rgb(color : ~str) -> Color {
+    fn parse_rgb(color : ~str) -> option<Color> {
         // Shave off the rgb( and the )
         let only_colors = color.substr(4u, color.len() - 5u);
 
         // split up r, g, and b
         let cols = only_colors.split_char(',');
         if cols.len() != 3u { ret fail_unrecognized(color); } 
 
         alt (u8::from_str(cols[0]), u8::from_str(cols[1]), 
              u8::from_str(cols[2])) {
-          (some(r), some(g), some(b)) { rgb(r, g, b) }
-          _               { fail_unrecognized(color) }
+          (some(r), some(g), some(b)) { some(rgb(r, g, b)) }
+          _ { fail_unrecognized(color) }
         }
     }
 
     #[doc="Parses a color specification in the form rgba(foo,bar,baz,qux)"]
-    fn parse_rgba(color : ~str) -> Color {
+    fn parse_rgba(color : ~str) -> option<Color> {
         // Shave off the rgba( and the )
         let only_vals = color.substr(5u, color.len() - 6u);
 
         // split up r, g, and b
         let cols = only_vals.split_char(',');
         if cols.len() != 4u { ret fail_unrecognized(color); } 
 
         alt (u8::from_str(cols[0]), u8::from_str(cols[1]), 
              u8::from_str(cols[2]), float::from_str(cols[3])) {
-          (some(r), some(g), some(b), some(a)) { rgba(r, g, b, a) }
+          (some(r), some(g), some(b), some(a)) { some(rgba(r, g, b, a)) }
           _ { fail_unrecognized(color) }
         }
     }
 
     #[doc="Parses a color specification in the form hsl(foo,bar,baz)"]
-    fn parse_hsl(color : ~str) -> Color {
+    fn parse_hsl(color : ~str) -> option<Color> {
         // Shave off the hsl( and the )
         let only_vals = color.substr(4u, color.len() - 5u);
 
         // split up h, s, and l
         let vals = only_vals.split_char(',');
         if vals.len() != 3u { ret fail_unrecognized(color); } 
 
         alt (float::from_str(vals[0]), float::from_str(vals[1]), 
              float::from_str(vals[2])) {
-          (some(h), some(s), some(l)) { hsl(h, s, l) }
-          _               { fail_unrecognized(color) }
+          (some(h), some(s), some(l)) { some(hsl(h, s, l)) }
+          _ { fail_unrecognized(color) }
         }
     }
 
     #[doc="Parses a color specification in the form hsla(foo,bar,baz,qux)"]
-    fn parse_hsla(color : ~str) -> Color {
+    fn parse_hsla(color : ~str) -> option<Color> {
         // Shave off the hsla( and the )
         let only_vals = color.substr(5u, color.len() - 6u);
 
         let vals = only_vals.split_char(',');
         if vals.len() != 4u { ret fail_unrecognized(color); } 
 
         alt (float::from_str(vals[0]), float::from_str(vals[1]), 
              float::from_str(vals[2]), float::from_str(vals[3])) {
-          (some(h), some(s), some(l), some(a)) { hsla(h, s, l, a) }
+          (some(h), some(s), some(l), some(a)) { some(hsla(h, s, l, a)) }
           _ { fail_unrecognized(color) }
         }
     }
 
     // Currently colors are supported in rgb(a,b,c) form and also by
     // keywords for several common colors.
     // TODO: extend this
-    fn parse_color(color : ~str) -> Color {
+    fn parse_color(color : ~str) -> option<Color> {
         alt color {
           c if c.starts_with(~"rgb(")  { parse_rgb(c) }
           c if c.starts_with(~"rgba(") { parse_rgba(c) }
           c if c.starts_with(~"hsl(")  { parse_hsl(c) }
           c if c.starts_with(~"hsla(") { parse_hsla(c) }
-          c                           { parse_by_name(c) }
+          c                            { parse_by_name(c) }
         }
     }
 }
 
 #[cfg(test)]
 mod test {
     import css_colors::*;
+    import option::unwrap;
     import parsing::parse_color;
 
     #[test]
     fn test_parse_by_name() {
-        assert red().eq(parse_color(~"red"));
-        assert lime().eq(parse_color(~"Lime"));
-        assert blue().eq(parse_color(~"BLUE"));
-        assert green().eq(parse_color(~"GreEN"));
-        assert white().eq(parse_color(~"white"));
-        assert black().eq(parse_color(~"Black"));
-        assert gray().eq(parse_color(~"Gray"));
-        assert silver().eq(parse_color(~"SiLvEr"));
-        assert maroon().eq(parse_color(~"maroon"));
-        assert purple().eq(parse_color(~"PURPLE"));
-        assert fuchsia().eq(parse_color(~"FUCHSIA"));
-        assert olive().eq(parse_color(~"oLiVe"));
-        assert yellow().eq(parse_color(~"yellow"));
-        assert navy().eq(parse_color(~"NAVY"));
-        assert teal().eq(parse_color(~"Teal"));
-        assert aqua().eq(parse_color(~"Aqua"));
+        assert red().eq(unwrap(parse_color(~"red")));
+        assert lime().eq(unwrap(parse_color(~"Lime")));
+        assert blue().eq(unwrap(parse_color(~"BLUE")));
+        assert green().eq(unwrap(parse_color(~"GreEN")));
+        assert white().eq(unwrap(parse_color(~"white")));
+        assert black().eq(unwrap(parse_color(~"Black")));
+        assert gray().eq(unwrap(parse_color(~"Gray")));
+        assert silver().eq(unwrap(parse_color(~"SiLvEr")));
+        assert maroon().eq(unwrap(parse_color(~"maroon")));
+        assert purple().eq(unwrap(parse_color(~"PURPLE")));
+        assert fuchsia().eq(unwrap(parse_color(~"FUCHSIA")));
+        assert olive().eq(unwrap(parse_color(~"oLiVe")));
+        assert yellow().eq(unwrap(parse_color(~"yellow")));
+        assert navy().eq(unwrap(parse_color(~"NAVY")));
+        assert teal().eq(unwrap(parse_color(~"Teal")));
+        assert aqua().eq(unwrap(parse_color(~"Aqua")));
+        assert none == parse_color(~"foobarbaz");
     }
 
     #[test]
     fn test_parsing_rgb() {
-        assert red().eq(parse_color(~"rgb(255,0,0)"));
-        assert red().eq(parse_color(~"rgba(255,0,0,1.0)"));
-        assert red().eq(parse_color(~"rgba(255,0,0,1)"));
-        assert lime().eq(parse_color(~"rgba(0,255,0,1.00)"));
-        assert rgb(1u8,2u8,3u8).eq(parse_color(~"rgb(1,2,03)"));
-        assert rgba(15u8,250u8,3u8,0.5).eq(parse_color(~"rgba(15,250,3,.5)"));
-        assert rgba(15u8,250u8,3u8,0.5).eq(parse_color(~"rgba(15,250,3,0.5)"));
+        assert red().eq(unwrap(parse_color(~"rgb(255,0,0)")));
+        assert red().eq(unwrap(parse_color(~"rgba(255,0,0,1.0)")));
+        assert red().eq(unwrap(parse_color(~"rgba(255,0,0,1)")));
+        assert lime().eq(unwrap(parse_color(~"rgba(0,255,0,1.00)")));
+        assert rgb(1u8,2u8,3u8).eq(unwrap(parse_color(~"rgb(1,2,03)")));
+        assert rgba(15u8,250u8,3u8,0.5).eq(unwrap(parse_color(~"rgba(15,250,3,.5)")));
+        assert rgba(15u8,250u8,3u8,0.5).eq(unwrap(parse_color(~"rgba(15,250,3,0.5)")));
+        assert none == parse_color(~"rbga(1,2,3)");
     }
 
     #[test]
     fn test_parsing_hsl() {
-        assert red().eq(parse_color(~"hsl(0,1,.5)"));
-        assert lime().eq(parse_color(~"hsl(120.0,1.0,.5)"));
-        assert blue().eq(parse_color(~"hsl(240.0,1.0,.5)"));
-        assert green().eq(parse_color(~"hsl(120.0,1.0,.25)"));
-        assert white().eq(parse_color(~"hsl(1.0,1.,1.0)"));
-        assert white().eq(parse_color(~"hsl(129.0,0.3,1.0)"));
-        assert black().eq(parse_color(~"hsl(231.2,0.75,0.0)"));
-        assert black().eq(parse_color(~"hsl(11.2,0.0,0.0)"));
-        assert gray().eq(parse_color(~"hsl(0.0,0.0,0.5)"));
-        assert maroon().eq(parse_color(~"hsl(0.0,1.0,0.25)"));
-        assert purple().eq(parse_color(~"hsl(300.0,1.0,0.25)"));
-        assert fuchsia().eq(parse_color(~"hsl(300,1.0,0.5)"));
-        assert olive().eq(parse_color(~"hsl(60.,1.0,0.25)"));
-        assert yellow().eq(parse_color(~"hsl(60.,1.0,0.5)"));
-        assert navy().eq(parse_color(~"hsl(240.0,1.0,.25)"));
-        assert teal().eq(parse_color(~"hsl(180.0,1.0,.25)"));
-        assert aqua().eq(parse_color(~"hsl(180.0,1.0,.5)"));
+        assert red().eq(unwrap(parse_color(~"hsl(0,1,.5)")));
+        assert lime().eq(unwrap(parse_color(~"hsl(120.0,1.0,.5)")));
+        assert blue().eq(unwrap(parse_color(~"hsl(240.0,1.0,.5)")));
+        assert green().eq(unwrap(parse_color(~"hsl(120.0,1.0,.25)")));
+        assert white().eq(unwrap(parse_color(~"hsl(1.0,1.,1.0)")));
+        assert white().eq(unwrap(parse_color(~"hsl(129.0,0.3,1.0)")));
+        assert black().eq(unwrap(parse_color(~"hsl(231.2,0.75,0.0)")));
+        assert black().eq(unwrap(parse_color(~"hsl(11.2,0.0,0.0)")));
+        assert gray().eq(unwrap(parse_color(~"hsl(0.0,0.0,0.5)")));
+        assert maroon().eq(unwrap(parse_color(~"hsl(0.0,1.0,0.25)")));
+        assert purple().eq(unwrap(parse_color(~"hsl(300.0,1.0,0.25)")));
+        assert fuchsia().eq(unwrap(parse_color(~"hsl(300,1.0,0.5)")));
+        assert olive().eq(unwrap(parse_color(~"hsl(60.,1.0,0.25)")));
+        assert yellow().eq(unwrap(parse_color(~"hsl(60.,1.0,0.5)")));
+        assert navy().eq(unwrap(parse_color(~"hsl(240.0,1.0,.25)")));
+        assert teal().eq(unwrap(parse_color(~"hsl(180.0,1.0,.25)")));
+        assert aqua().eq(unwrap(parse_color(~"hsl(180.0,1.0,.5)")));
+        assert none == parse_color(~"hsl(1,2,3,.4)");
     }
 }
 
 
 #[doc="Define the colors specified by css"]
 mod css_colors {
     // The 16 basic css colors
     fn black() -> Color {