[librsvg] color.rs: Implement the new version of rsvg_css_parse_color() in Rust
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg] color.rs: Implement the new version of rsvg_css_parse_color() in Rust
- Date: Sat, 20 May 2017 03:48:31 +0000 (UTC)
commit c45dd9f2519cc56fc8f57746605a881f2f939336
Author: Federico Mena Quintero <federico gnome org>
Date: Fri May 19 21:47:07 2017 -0500
color.rs: Implement the new version of rsvg_css_parse_color() in Rust
The prototype is different from what it was in C. We'll change it
so that instead of just returning a guint32 argb and the inherit
flag (... which is used backwards, anyway), it will return an actual
struct with all the possible cases.
rust/src/color.rs | 123 +++++++++++++++++++++++++++++++++++++++++++++++++---
rust/src/lib.rs | 8 +++
2 files changed, 123 insertions(+), 8 deletions(-)
---
diff --git a/rust/src/color.rs b/rust/src/color.rs
index ab358f6..56cf10f 100644
--- a/rust/src/color.rs
+++ b/rust/src/color.rs
@@ -1,8 +1,27 @@
use ::cssparser;
+use ::libc;
+
+use ::glib::translate::*;
+
+use parsers::ParseError;
+use error::*;
+
+// There are two quirks here:
+//
+// First, we need to expose the Color algebraic type *and* a parse
+// error to C, but we can't repr(C) them plainly. So, we define a
+// ColorKind enum and a ColorSpec struct that can both be represented
+// in C.
+//
+// Second, the C code in librsvg expects ARGB colors passed around as
+// guint32. However, in Rust we'd prefer to use cssparser's RGBA
+// structure, which has explicit fields for red/green/blue/alpha.
+// We'll do those conversions here, for the benefit of the C code, and
+// then just wait until the C code gradually disappears.
// Keep this in sync with rsvg-css.h:RsvgCssColorKind
#[repr(C)]
-#[derive(Clone, Copy, PartialEq, Eq, Debug)]
+#[derive(Clone, Copy, PartialEq, Debug)]
pub enum ColorKind {
Inherit,
CurrentColor,
@@ -12,22 +31,87 @@ pub enum ColorKind {
// Keep this in sync with rsvg-css.h:RsvgCssColorSpec
#[repr(C)]
-#[derive(Clone, Copy, PartialEq, Eq, Debug)]
+#[derive(Clone, Copy, PartialEq, Debug)]
pub struct ColorSpec {
kind: ColorKind,
argb: u32
}
-impl<'i> From<Result<cssparser::Color, cssparser::BasicParseError<'i>>> for ColorSpec {
- fn from (result: Result<cssparser::Color, cssparser::BasicParseError<'i>>) -> ColorSpec {
+// Keep in sync with rsvg-css.h:AllowInherit
+#[repr(C)]
+#[derive(PartialEq, Debug)]
+pub enum AllowInherit {
+ No,
+ Yes
+}
+
+// Keep in sync with rsvg-css.h:AllowCurrentColor
+#[repr(C)]
+#[derive(PartialEq, Debug)]
+pub enum AllowCurrentColor {
+ No,
+ Yes
+}
+
+// This is the Rust version of the above
+#[derive(Clone, Copy, PartialEq, Debug)]
+pub enum Color {
+ Inherit,
+ CurrentColor,
+ RGBA (cssparser::RGBA)
+}
+
+impl Color {
+ pub fn parse (s: &str, allow_inherit: AllowInherit, allow_current_color: AllowCurrentColor) ->
Result<Color, AttributeError> {
+ if s == "inherit" {
+ if allow_inherit == AllowInherit::Yes {
+ Ok (Color::Inherit)
+ } else {
+ Err (AttributeError::Value ("inherit is not allowed here".to_string ()))
+ }
+ } else {
+ match cssparser::Color::parse (&mut cssparser::Parser::new (s)) {
+ Ok (cssparser::Color::CurrentColor) => {
+ if allow_current_color == AllowCurrentColor::Yes {
+ Ok (Color::CurrentColor)
+ } else {
+ Err (AttributeError::Value ("currentColor is not allowed here".to_string ()))
+ }
+ },
+
+ Ok (csscolor) => Ok (Color::from (csscolor)),
+
+ _ => Err (AttributeError::Parse (ParseError::new ("invalid syntax for color")))
+ }
+ }
+ }
+}
+
+impl From<cssparser::Color> for Color {
+ fn from (c: cssparser::Color) -> Color {
+ match c {
+ cssparser::Color::CurrentColor => Color::CurrentColor,
+ cssparser::Color::RGBA (rgba) => Color::RGBA (rgba)
+ }
+ }
+}
+
+impl From<Result<Color, AttributeError>> for ColorSpec {
+ fn from (result: Result<Color, AttributeError>) -> ColorSpec {
match result {
- Ok (cssparser::Color::CurrentColor) =>
+ Ok (Color::Inherit) =>
+ ColorSpec {
+ kind: ColorKind::Inherit,
+ argb: 0
+ },
+
+ Ok (Color::CurrentColor) =>
ColorSpec {
kind: ColorKind::CurrentColor,
argb: 0
},
- Ok (cssparser::Color::RGBA (rgba)) =>
+ Ok (Color::RGBA (rgba)) =>
ColorSpec {
kind: ColorKind::ARGB,
argb: ((rgba.alpha as u32) << 24 |
@@ -45,13 +129,22 @@ impl<'i> From<Result<cssparser::Color, cssparser::BasicParseError<'i>>> for Colo
}
}
+#[no_mangle]
+pub extern fn rsvg_css_parse_color (string: *const libc::c_char,
+ allow_inherit: AllowInherit,
+ allow_current_color: AllowCurrentColor) -> ColorSpec {
+ let s = unsafe { String::from_glib_none (string) };
+
+ ColorSpec::from (Color::parse (&s, allow_inherit, allow_current_color))
+}
+
#[cfg(test)]
mod tests {
use super::*;
- use std::str::FromStr;
fn parse (s: &str) -> ColorSpec {
- ColorSpec::from (cssparser::Color::parse (&mut cssparser::Parser::new (s)))
+ // ColorSpec::from (Color::parse (s, AllowInherit::Yes, AllowCurrentColor::Yes))
+ rsvg_css_parse_color (s.to_glib_none ().0, AllowInherit::Yes, AllowCurrentColor::Yes)
}
#[test]
@@ -99,5 +192,19 @@ mod tests {
fn invalid_colors_yield_error () {
assert_eq! (parse (""), make_error ());
assert_eq! (parse ("foo"), make_error ());
+ assert_eq! (parse ("rgb(chilaquil)"), make_error ());
+ assert_eq! (parse ("rgb(1, 2, 3, 4, 5)"), make_error ());
+ }
+
+ #[test]
+ fn yields_error_on_disallowed_current_color () {
+ assert_eq! (ColorSpec::from (Color::parse ("currentColor", AllowInherit::Yes,
AllowCurrentColor::No)),
+ make_error ());
+ }
+
+ #[test]
+ fn yields_error_on_disallowed_inherit () {
+ assert_eq! (ColorSpec::from (Color::parse ("inherit", AllowInherit::No, AllowCurrentColor::Yes)),
+ make_error ());
}
}
diff --git a/rust/src/lib.rs b/rust/src/lib.rs
index b9abb49..1662759 100644
--- a/rust/src/lib.rs
+++ b/rust/src/lib.rs
@@ -1,3 +1,6 @@
+extern crate libc;
+extern crate glib;
+
#[macro_use]
extern crate bitflags;
@@ -27,6 +30,11 @@ pub use cnode::{
};
pub use color::{
+ AllowCurrentColor,
+ AllowInherit,
+ ColorKind,
+ ColorSpec,
+ rsvg_css_parse_color
};
pub use gradient::{
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]