[librsvg] macros: extend macro to deal with properties that are not enums
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg] macros: extend macro to deal with properties that are not enums
- Date: Wed, 28 Mar 2018 03:57:49 +0000 (UTC)
commit 6f73b2d38dda7928439d6e4cee23216cfcae8326
Author: Paolo Borelli <pborelli gnome org>
Date: Tue Mar 27 09:20:18 2018 +0200
macros: extend macro to deal with properties that are not enums
Also rename the macro since it is now more generic
rsvg_internals/src/property_macros.rs | 68 ++++++++++++++++++++++++++++++++---
rsvg_internals/src/state.rs | 15 +++++---
2 files changed, 73 insertions(+), 10 deletions(-)
---
diff --git a/rsvg_internals/src/property_macros.rs b/rsvg_internals/src/property_macros.rs
index 1bead060..a1d8197f 100644
--- a/rsvg_internals/src/property_macros.rs
+++ b/rsvg_internals/src/property_macros.rs
@@ -3,14 +3,14 @@ pub trait Property {
}
/// Generates a property definition that simply parses strings to enum variants
+/// or to a tuple struct of the given type.
///
-/// This can be used for properties with simple symbol-based values.
/// For example, the SVG spec defines the `stroke-linejoin` property
/// to have possible values `miter | round | bevel | inherit`, with a default
/// of `miter`. We can define the property like this:
///
/// ```
-/// make_ident_property!(
+/// make_property!(
/// StrokeLinejoin,
/// default: Miter,
///
@@ -26,10 +26,11 @@ pub trait Property {
/// `impl Parse for StrokeLinejoin`, from `parsers::Parse`, where
/// `type Data = ()` and `type Err = AttributeError`.
#[macro_export]
-macro_rules! make_ident_property {
+macro_rules! make_property {
($name: ident,
default: $default: ident,
inherits_automatically: $inherits_automatically: expr,
+ identifiers:
$($str_prop: expr => $variant: ident,)+
) => {
#[derive(Debug, Copy, Clone, PartialEq)]
@@ -62,6 +63,41 @@ macro_rules! make_ident_property {
}
}
};
+
+ ($name: ident,
+ default: $default: expr,
+ inherits_automatically: $inherits_automatically: expr,
+ newtype: $type: ty
+ ) => {
+ #[derive(Debug, Clone, PartialEq)]
+ pub struct $name(pub $type);
+
+ impl Default for $name {
+ fn default() -> $name {
+ $name($default)
+ }
+ }
+
+ impl ::property_macros::Property for $name {
+ fn inherits_automatically() -> bool {
+ $inherits_automatically
+ }
+ }
+
+ impl ::parsers::Parse for $name {
+ type Data = ();
+ type Err = ::error::AttributeError;
+
+ fn parse(s: &str, _: Self::Data) -> Result<$name, ::error::AttributeError> {
+ match s.trim().parse() {
+ Ok(val) => Ok($name(val)),
+
+ // FIXME: should this convert the string::ParseError into AttributeError?
+ _ => Err(::error::AttributeError::from(::parsers::ParseError::new("invalid value"))),
+ }
+ }
+ }
+ };
}
#[cfg(test)]
@@ -72,11 +108,12 @@ mod tests {
#[test]
fn check_generated_property() {
- make_ident_property! {
+ make_property! {
Foo,
default: Def,
inherits_automatically: true,
+ identifiers:
"def" => Def,
"bar" => Bar,
"baz" => Baz,
@@ -84,8 +121,29 @@ mod tests {
assert_eq!(<Foo as Default>::default(), Foo::Def);
assert_eq!(<Foo as Property>::inherits_automatically(), true);
-
assert!(<Foo as Parse>::parse("blargh", ()).is_err());
assert_eq!(<Foo as Parse>::parse("bar", ()), Ok(Foo::Bar));
+
+ make_property! {
+ Bar,
+ default: "bar".to_string(),
+ inherits_automatically: true,
+ newtype: String
+ }
+
+ assert_eq!(<Bar as Default>::default(), Bar("bar".to_string()));
+ assert_eq!(<Bar as Property>::inherits_automatically(), true);
+ assert_eq!(<Bar as Parse>::parse("test", ()), Ok(Bar("test".to_string())));
+
+ make_property! {
+ Baz,
+ default: 42f64,
+ inherits_automatically: true,
+ newtype: f64
+ }
+
+ assert_eq!(<Baz as Default>::default(), Baz(42f64));
+ assert_eq!(<Baz as Property>::inherits_automatically(), true);
+ assert_eq!(<Baz as Parse>::parse("42", ()), Ok(Baz(42f64)));
}
}
diff --git a/rsvg_internals/src/state.rs b/rsvg_internals/src/state.rs
index 777c8fe7..04125032 100644
--- a/rsvg_internals/src/state.rs
+++ b/rsvg_internals/src/state.rs
@@ -380,22 +380,24 @@ pub fn get_state_rust<'a>(state: *const RsvgState) -> &'a mut State {
// FillRule ----------------------------------------
-make_ident_property!(
+make_property!(
FillRule,
default: NonZero,
inherits_automatically: true,
+ identifiers:
"nonzero" => NonZero,
"evenodd" => EvenOdd,
);
// StrokeLinecap ----------------------------------------
-make_ident_property!(
+make_property!(
StrokeLinecap,
default: Butt,
inherits_automatically: true,
+ identifiers:
"butt" => Butt,
"round" => Round,
"square" => Square,
@@ -403,11 +405,12 @@ make_ident_property!(
// StrokeLineJoin ----------------------------------------
-make_ident_property!(
+make_property!(
StrokeLinejoin,
default: Miter,
inherits_automatically: true,
+ identifiers:
"miter" => Miter,
"round" => Round,
"bevel" => Bevel,
@@ -415,11 +418,12 @@ make_ident_property!(
// TextAnchor --------------------------------------
-make_ident_property!(
+make_property!(
TextAnchor,
default: Start,
inherits_automatically: true,
+ identifiers:
"start" => Start,
"middle" => Middle,
"end" => End,
@@ -427,11 +431,12 @@ make_ident_property!(
// XmlSpace ----------------------------------------
-make_ident_property!(
+make_property!(
XmlSpace,
default: Default,
inherits_automatically: true,
+ identifiers:
"default" => Default,
"preserve" => Preserve,
);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]