[librsvg] color.rs: Start a parser for color specifications



commit 8f56c9048b057081005436f34dda206e55edca84
Author: Federico Mena Quintero <federico gnome org>
Date:   Thu May 18 12:21:46 2017 -0500

    color.rs: Start a parser for color specifications
    
    We want to remove the C version of rsvg_css_parse_color().

 rust/src/color.rs |  101 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 rust/src/lib.rs   |    1 +
 2 files changed, 102 insertions(+), 0 deletions(-)
---
diff --git a/rust/src/color.rs b/rust/src/color.rs
new file mode 100644
index 0000000..62a8522
--- /dev/null
+++ b/rust/src/color.rs
@@ -0,0 +1,101 @@
+use std::str::FromStr;
+
+use parsers::ParseError;
+use error::*;
+
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
+pub struct RawColor {
+    pub argb: u32
+}
+
+impl FromStr for RawColor {
+    type Err = AttributeError;
+
+    fn from_str (s: &str) -> Result<RawColor, AttributeError> {
+        if s.starts_with ('#') {
+            return parse_hex (s[1..].as_bytes ()).or (Err (
+                AttributeError::Parse (ParseError::new ("expected one of #rrggbbaa, #rrggbb, #rgba, #rgb"))))
+        }
+
+        Err (AttributeError::Parse (ParseError::new ("invalid color specification")))
+    }
+}
+
+fn hex_digit (c: u8) -> Result<u8, ()> {
+    match c {
+        b'0'...b'9' => Ok (c - b'0'),
+        b'A'...b'F' => Ok (c - b'A' + 10),
+        b'a'...b'f' => Ok (c - b'a' + 10),
+        _ => Err (())
+    }
+}
+
+fn parse_hex (s: &[u8]) -> Result<RawColor, ()> {
+    let result: Result<u32, ()> = match s.len () {
+        8 => {
+            // #rrggbbaa -> 0xaarrggbb
+            Ok (((hex_digit (s[0])? * 16 + hex_digit (s[1])?) as u32) << 16 |
+                ((hex_digit (s[2])? * 16 + hex_digit (s[3])?) as u32) << 8  |
+                ((hex_digit (s[4])? * 16 + hex_digit (s[5])?) as u32)       |
+                ((hex_digit (s[6])? * 16 + hex_digit (s[7])?) as u32) << 24)
+        },
+
+        6 => {
+            // #rrggbb -> 0xffrrggbb
+            Ok (0xff000000 |
+                ((hex_digit (s[0])? * 16 + hex_digit (s[1])?) as u32) << 16 |
+                ((hex_digit (s[2])? * 16 + hex_digit (s[3])?) as u32) << 8  |
+                ((hex_digit (s[4])? * 16 + hex_digit (s[5])?) as u32))
+        },
+
+        4 => {
+            // #rgba -> 0xaarrggbb
+            Ok (((hex_digit (s[0])? * 0x11) as u32) << 16 |
+                ((hex_digit (s[1])? * 0x11) as u32) << 8  |
+                ((hex_digit (s[2])? * 0x11) as u32)       |
+                ((hex_digit (s[3])? * 0x11) as u32) << 24)  
+        },
+
+        3 => {
+            // #rgb -> 0xffrrggbb
+            Ok (0xff000000 |
+                ((hex_digit (s[0])? * 0x11) as u32) << 16 |
+                ((hex_digit (s[1])? * 0x11) as u32) << 8  |
+                ((hex_digit (s[2])? * 0x11) as u32))
+        }
+
+        _ => Err (())
+    };
+
+    match result {
+        Ok (argb) => Ok (RawColor { argb: argb }),
+        Err (_)   => Err (())
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use std::str::FromStr;
+
+    #[test]
+    fn parses_hash_hex_colors () {
+        assert_eq! (RawColor::from_str ("#AB10fa20").unwrap (), RawColor { argb: 0x20ab10fa });
+        assert_eq! (RawColor::from_str ("#10fa20").unwrap (),   RawColor { argb: 0xff10fa20 });
+        assert_eq! (RawColor::from_str ("#abcd").unwrap (),     RawColor { argb: 0xddaabbcc });
+        assert_eq! (RawColor::from_str ("#123").unwrap (),      RawColor { argb: 0xff112233 });
+    }
+
+    #[test]
+    fn invalid_hash_hex_colors_yield_error () {
+        assert! (RawColor::from_str ("#").is_err ());
+        assert! (RawColor::from_str ("#xyz").is_err ());
+        assert! (RawColor::from_str ("#112233gg").is_err ());
+    }
+
+    #[test]
+    fn invalid_colors_yield_error () {
+        assert! (RawColor::from_str ("").is_err ());
+        assert! (RawColor::from_str ("foo").is_err ());
+    }
+}
diff --git a/rust/src/lib.rs b/rust/src/lib.rs
index deddb52..b85c9e3 100644
--- a/rust/src/lib.rs
+++ b/rust/src/lib.rs
@@ -104,6 +104,7 @@ pub use viewbox::{
 mod aspect_ratio;
 mod bbox;
 mod cnode;
+mod color;
 mod drawing_ctx;
 mod error;
 mod handle;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]