[librsvg] parsers::Parse - new trait; we'll use this instead of std::FromStr



commit 5510e4c3f9c9c84bac4a05f6d93a09c9b4862544
Author: Federico Mena Quintero <federico gnome org>
Date:   Mon Sep 4 21:09:38 2017 -0500

    parsers::Parse - new trait; we'll use this instead of std::FromStr
    
    This has a Data associated type, which is passed to parse(&str, data) -> Result<>
    
    We'll use that Data to pass RsvgLength's auxiliary data for parsing.
    
    Hopefully this way we can have a unified way to parse attribute values
    from strings, without having exceptions just because:
    
      a) RsvgLength needs to know the direction upon parsing/construction;
    
      b) We can't impl FromStr for cairo::Matrix because they both come
      from extern traits.

 rust/src/aspect_ratio.rs |   77 ++++++++++++++++++++++-----------------------
 rust/src/gradient.rs     |    4 +-
 rust/src/marker.rs       |   48 +++++++++++++++--------------
 rust/src/paint_server.rs |   31 +++++++++---------
 rust/src/parsers.rs      |    7 ++++
 rust/src/pattern.rs      |   17 +++++-----
 rust/src/property_bag.rs |   21 ++++++------
 rust/src/structure.rs    |    8 ++--
 rust/src/viewbox.rs      |   23 ++++++-------
 9 files changed, 121 insertions(+), 115 deletions(-)
---
diff --git a/rust/src/aspect_ratio.rs b/rust/src/aspect_ratio.rs
index ebda583..63482ba 100644
--- a/rust/src/aspect_ratio.rs
+++ b/rust/src/aspect_ratio.rs
@@ -18,8 +18,7 @@
 use ::libc;
 use ::glib::translate::*;
 
-use std::str::FromStr;
-
+use parsers::Parse;
 use parsers::ParseError;
 use error::*;
 
@@ -258,10 +257,11 @@ fn make_err () -> AttributeError {
     AttributeError::Parse (ParseError::new ("expected \"[defer] <align> [meet | slice]\""))
 }
 
-impl FromStr for AspectRatio {
+impl Parse for AspectRatio {
+    type Data = ();
     type Err = AttributeError;
 
-    fn from_str(s: &str) -> Result<AspectRatio, AttributeError> {
+    fn parse(s: &str, _: ()) -> Result<AspectRatio, AttributeError> {
         let mut defer = false;
         let mut align: Align = Default::default ();
         let mut fit_mode = FitMode::Meet;
@@ -333,7 +333,7 @@ impl FromStr for AspectRatio {
 #[no_mangle]
 pub extern fn rsvg_aspect_ratio_parse (c_str: *const libc::c_char) -> u32 {
     let my_str = unsafe { &String::from_glib_none (c_str) };
-    let parsed = AspectRatio::from_str (my_str);
+    let parsed = AspectRatio::parse (my_str, ());
 
     match parsed {
         Ok (aspect_ratio) => { aspect_ratio.to_u32 () },
@@ -365,61 +365,60 @@ pub extern fn rsvg_aspect_ratio_compute (aspect: u32,
 #[cfg(test)]
 mod tests {
     use super::*;
-    use std::str::FromStr;
 
     #[test]
     fn parsing_invalid_strings_yields_error () {
-        assert! (AspectRatio::from_str ("").is_err ());
+        assert! (AspectRatio::parse ("", ()).is_err ());
 
-        assert! (AspectRatio::from_str ("defer").is_err ());
+        assert! (AspectRatio::parse ("defer", ()).is_err ());
 
-        assert! (AspectRatio::from_str ("defer foo").is_err ());
+        assert! (AspectRatio::parse ("defer foo", ()).is_err ());
 
-        assert! (AspectRatio::from_str ("defer xmidymid").is_err ());
+        assert! (AspectRatio::parse ("defer xmidymid", ()).is_err ());
 
-        assert! (AspectRatio::from_str ("defer xMidYMid foo").is_err ());
+        assert! (AspectRatio::parse ("defer xMidYMid foo", ()).is_err ());
 
-        assert! (AspectRatio::from_str ("xmidymid").is_err ());
+        assert! (AspectRatio::parse ("xmidymid", ()).is_err ());
 
-        assert! (AspectRatio::from_str ("xMidYMid foo").is_err ());
+        assert! (AspectRatio::parse ("xMidYMid foo", ()).is_err ());
 
-        assert! (AspectRatio::from_str ("defer xMidYMid meet foo").is_err ());
+        assert! (AspectRatio::parse ("defer xMidYMid meet foo", ()).is_err ());
     }
 
     #[test]
     fn parses_valid_strings () {
-        assert_eq! (AspectRatio::from_str ("defer none"),
+        assert_eq! (AspectRatio::parse ("defer none", ()),
                     Ok (AspectRatio { defer: true,
                                       align: Align::None }));
 
-        assert_eq! (AspectRatio::from_str ("xMidYMid"),
+        assert_eq! (AspectRatio::parse ("xMidYMid", ()),
                     Ok (AspectRatio { defer: false,
                                       align: Align::Aligned { align: AlignMode::XmidYmid,
                                                               fit: FitMode::Meet } }));
         
-        assert_eq! (AspectRatio::from_str ("defer xMidYMid"),
+        assert_eq! (AspectRatio::parse ("defer xMidYMid", ()),
                     Ok (AspectRatio { defer: true,
                                       align: Align::Aligned { align: AlignMode::XmidYmid,
                                                               fit: FitMode::Meet } }));
         
-        assert_eq! (AspectRatio::from_str ("defer xMinYMax"),
+        assert_eq! (AspectRatio::parse ("defer xMinYMax", ()),
                     Ok (AspectRatio { defer: true,
                                       align: Align::Aligned { align: AlignMode::XminYmax,
                                                               fit: FitMode::Meet } }));
         
-        assert_eq! (AspectRatio::from_str ("defer xMaxYMid meet"),
+        assert_eq! (AspectRatio::parse ("defer xMaxYMid meet", ()),
                     Ok (AspectRatio { defer: true,
                                       align: Align::Aligned { align: AlignMode::XmaxYmid,
                                                               fit: FitMode::Meet } }));
         
-        assert_eq! (AspectRatio::from_str ("defer xMinYMax slice"),
+        assert_eq! (AspectRatio::parse ("defer xMinYMax slice", ()),
                     Ok (AspectRatio { defer: true,
                                       align: Align::Aligned { align: AlignMode::XminYmax,
                                                               fit: FitMode::Slice } }));
     }
 
     fn test_roundtrip (s: &str) {
-        let a = AspectRatio::from_str (s).unwrap ();
+        let a = AspectRatio::parse (s, ()).unwrap ();
 
         assert_eq! (AspectRatio::from_u32 (a.to_u32 ()), a);
     }
@@ -434,31 +433,31 @@ mod tests {
 
     #[test]
     fn aligns () {
-        assert_eq! (AspectRatio::from_str ("xMinYMin meet").unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 
1.0), (0.0, 0.0, 0.1, 1.0));
-        assert_eq! (AspectRatio::from_str ("xMinYMin slice").unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 
1.0), (0.0, 0.0, 10.0, 100.0));
+        assert_eq! (AspectRatio::parse ("xMinYMin meet", ()).unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 
1.0), (0.0, 0.0, 0.1, 1.0));
+        assert_eq! (AspectRatio::parse ("xMinYMin slice", ()).unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 
1.0), (0.0, 0.0, 10.0, 100.0));
 
-        assert_eq! (AspectRatio::from_str ("xMinYMid meet").unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 
1.0), (0.0, 0.0, 0.1, 1.0));
-        assert_eq! (AspectRatio::from_str ("xMinYMid slice").unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 
1.0), (0.0, -49.5, 10.0, 100.0));
+        assert_eq! (AspectRatio::parse ("xMinYMid meet", ()).unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 
1.0), (0.0, 0.0, 0.1, 1.0));
+        assert_eq! (AspectRatio::parse ("xMinYMid slice", ()).unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 
1.0), (0.0, -49.5, 10.0, 100.0));
 
-        assert_eq! (AspectRatio::from_str ("xMinYMax meet").unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 
1.0), (0.0, 0.0, 0.1, 1.0));
-        assert_eq! (AspectRatio::from_str ("xMinYMax slice").unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 
1.0), (0.0, -99.0, 10.0, 100.0));
+        assert_eq! (AspectRatio::parse ("xMinYMax meet", ()).unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 
1.0), (0.0, 0.0, 0.1, 1.0));
+        assert_eq! (AspectRatio::parse ("xMinYMax slice", ()).unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 
1.0), (0.0, -99.0, 10.0, 100.0));
 
-        assert_eq! (AspectRatio::from_str ("xMidYMin meet").unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 
1.0), (4.95, 0.0, 0.1, 1.0));
-        assert_eq! (AspectRatio::from_str ("xMidYMin slice").unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 
1.0), (0.0, 0.0, 10.0, 100.0));
+        assert_eq! (AspectRatio::parse ("xMidYMin meet", ()).unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 
1.0), (4.95, 0.0, 0.1, 1.0));
+        assert_eq! (AspectRatio::parse ("xMidYMin slice", ()).unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 
1.0), (0.0, 0.0, 10.0, 100.0));
 
-        assert_eq! (AspectRatio::from_str ("xMidYMid meet").unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 
1.0), (4.95, 0.0, 0.1, 1.0));
-        assert_eq! (AspectRatio::from_str ("xMidYMid slice").unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 
1.0), (0.0, -49.5, 10.0, 100.0));
+        assert_eq! (AspectRatio::parse ("xMidYMid meet", ()).unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 
1.0), (4.95, 0.0, 0.1, 1.0));
+        assert_eq! (AspectRatio::parse ("xMidYMid slice", ()).unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 
1.0), (0.0, -49.5, 10.0, 100.0));
 
-        assert_eq! (AspectRatio::from_str ("xMidYMax meet").unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 
1.0), (4.95, 0.0, 0.1, 1.0));
-        assert_eq! (AspectRatio::from_str ("xMidYMax slice").unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 
1.0), (0.0, -99.0, 10.0, 100.0));
+        assert_eq! (AspectRatio::parse ("xMidYMax meet", ()).unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 
1.0), (4.95, 0.0, 0.1, 1.0));
+        assert_eq! (AspectRatio::parse ("xMidYMax slice", ()).unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 
1.0), (0.0, -99.0, 10.0, 100.0));
 
-        assert_eq! (AspectRatio::from_str ("xMaxYMin meet").unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 
1.0), (9.9, 0.0, 0.1, 1.0));
-        assert_eq! (AspectRatio::from_str ("xMaxYMin slice").unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 
1.0), (0.0, 0.0, 10.0, 100.0));
+        assert_eq! (AspectRatio::parse ("xMaxYMin meet", ()).unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 
1.0), (9.9, 0.0, 0.1, 1.0));
+        assert_eq! (AspectRatio::parse ("xMaxYMin slice", ()).unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 
1.0), (0.0, 0.0, 10.0, 100.0));
 
-        assert_eq! (AspectRatio::from_str ("xMaxYMid meet").unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 
1.0), (9.9, 0.0, 0.1, 1.0));
-        assert_eq! (AspectRatio::from_str ("xMaxYMid slice").unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 
1.0), (0.0, -49.5, 10.0, 100.0));
+        assert_eq! (AspectRatio::parse ("xMaxYMid meet", ()).unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 
1.0), (9.9, 0.0, 0.1, 1.0));
+        assert_eq! (AspectRatio::parse ("xMaxYMid slice", ()).unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 
1.0), (0.0, -49.5, 10.0, 100.0));
 
-        assert_eq! (AspectRatio::from_str ("xMaxYMax meet").unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 
1.0), (9.9, 0.0, 0.1, 1.0));
-        assert_eq! (AspectRatio::from_str ("xMaxYMax slice").unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 
1.0), (0.0, -99.0, 10.0, 100.0));
+        assert_eq! (AspectRatio::parse ("xMaxYMax meet", ()).unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 
1.0), (9.9, 0.0, 0.1, 1.0));
+        assert_eq! (AspectRatio::parse ("xMaxYMax slice", ()).unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 
1.0), (0.0, -99.0, 10.0, 100.0));
     }
 }
diff --git a/rust/src/gradient.rs b/rust/src/gradient.rs
index aac0ea2..ac2b2bf 100644
--- a/rust/src/gradient.rs
+++ b/rust/src/gradient.rs
@@ -556,9 +556,9 @@ impl NodeTrait for NodeGradient {
 
         // Attributes common to linear and radial gradients
 
-        g.common.units    = property_bag::parse_or_none (pbag, "gradientUnits")?;
+        g.common.units    = property_bag::parse_or_none (pbag, "gradientUnits", ())?;
         g.common.affine   = property_bag::transform_or_none (pbag, "gradientTransform")?;
-        g.common.spread   = property_bag::parse_or_none (pbag, "spreadMethod")?;
+        g.common.spread   = property_bag::parse_or_none (pbag, "spreadMethod", ())?;
         g.common.fallback = property_bag::lookup (pbag, "xlink:href");
 
         // Attributes specific to each gradient type.  The defaults mandated by the spec
diff --git a/rust/src/marker.rs b/rust/src/marker.rs
index 596bdbd..927455c 100644
--- a/rust/src/marker.rs
+++ b/rust/src/marker.rs
@@ -4,7 +4,6 @@ use ::libc;
 
 use std::cell::Cell;
 use std::f64::consts::*;
-use std::str::FromStr;
 
 use cairo::MatrixTrait;
 
@@ -17,6 +16,7 @@ use length::*;
 use node::*;
 use path_builder::*;
 use parsers;
+use parsers::Parse;
 use parsers::ParseError;
 use property_bag;
 use property_bag::*;
@@ -37,10 +37,11 @@ impl Default for MarkerUnits {
     }
 }
 
-impl FromStr for MarkerUnits {
+impl Parse for MarkerUnits {
+    type Data = ();
     type Err = AttributeError;
 
-    fn from_str (s: &str) -> Result <MarkerUnits, AttributeError> {
+    fn parse (s: &str, _: ()) -> Result <MarkerUnits, AttributeError> {
         match s {
             "userSpaceOnUse" => Ok (MarkerUnits::UserSpaceOnUse),
             "strokeWidth"    => Ok (MarkerUnits::StrokeWidth),
@@ -63,10 +64,11 @@ impl Default for MarkerOrient {
     }
 }
 
-impl FromStr for MarkerOrient {
+impl Parse for MarkerOrient {
+    type Data = ();
     type Err = AttributeError;
 
-    fn from_str (s: &str) -> Result <MarkerOrient, AttributeError> {
+    fn parse (s: &str, _: ()) -> Result <MarkerOrient, AttributeError> {
         match s {
             "auto" => Ok (MarkerOrient::Auto),
             _      => parsers::angle_degrees (s)
@@ -190,7 +192,7 @@ impl NodeMarker {
 
 impl NodeTrait for NodeMarker {
     fn set_atts (&self, _: &RsvgNode, _: *const RsvgHandle, pbag: *const RsvgPropertyBag) -> NodeResult {
-        self.units.set (property_bag::parse_or_default (pbag, "markerUnits")?);
+        self.units.set (property_bag::parse_or_default (pbag, "markerUnits", ())?);
 
         self.ref_x.set (property_bag::length_or_default (pbag, "refX", LengthDir::Horizontal)?);
         self.ref_y.set (property_bag::length_or_default (pbag, "refY", LengthDir::Vertical)?);
@@ -207,10 +209,10 @@ impl NodeTrait for NodeMarker {
                         .check_nonnegative ()
                         .map_err (|e| NodeError::attribute_error ("markerHeight", e))?);
 
-        self.orient.set (property_bag::parse_or_default (pbag, "orient")?);
-        self.aspect.set (property_bag::parse_or_default (pbag, "preserveAspectRatio")?);
-        self.vbox.set   (property_bag::parse_or_none (pbag, "viewBox")?);
-        self.aspect.set (property_bag::parse_or_default (pbag, "preserveAspectRatio")?);
+        self.orient.set (property_bag::parse_or_default (pbag, "orient", ())?);
+        self.aspect.set (property_bag::parse_or_default (pbag, "preserveAspectRatio", ())?);
+        self.vbox.set   (property_bag::parse_or_none (pbag, "viewBox", ())?);
+        self.aspect.set (property_bag::parse_or_default (pbag, "preserveAspectRatio", ())?);
 
         Ok (())
     }
@@ -769,32 +771,32 @@ mod parser_tests {
 
     #[test]
     fn parsing_invalid_marker_units_yields_error () {
-        assert! (is_parse_error (&MarkerUnits::from_str ("").map_err (|e| AttributeError::from (e))));
-        assert! (is_parse_error (&MarkerUnits::from_str ("foo").map_err (|e| AttributeError::from (e))));
+        assert! (is_parse_error (&MarkerUnits::parse ("", ()).map_err (|e| AttributeError::from (e))));
+        assert! (is_parse_error (&MarkerUnits::parse ("foo", ()).map_err (|e| AttributeError::from (e))));
     }
 
     #[test]
     fn parses_marker_units () {
-        assert_eq! (MarkerUnits::from_str ("userSpaceOnUse"), Ok (MarkerUnits::UserSpaceOnUse));
-        assert_eq! (MarkerUnits::from_str ("strokeWidth"),    Ok (MarkerUnits::StrokeWidth));
+        assert_eq! (MarkerUnits::parse ("userSpaceOnUse", ()), Ok (MarkerUnits::UserSpaceOnUse));
+        assert_eq! (MarkerUnits::parse ("strokeWidth", ()),    Ok (MarkerUnits::StrokeWidth));
     }
 
     #[test]
     fn parsing_invalid_marker_orient_yields_error () {
-        assert! (is_parse_error (&MarkerOrient::from_str ("").map_err (|e| AttributeError::from (e))));
-        assert! (is_parse_error (&MarkerOrient::from_str ("blah").map_err (|e| AttributeError::from (e))));
-        assert! (is_parse_error (&MarkerOrient::from_str ("45blah").map_err (|e| AttributeError::from (e))));
+        assert! (is_parse_error (&MarkerOrient::parse ("", ()).map_err (|e| AttributeError::from (e))));
+        assert! (is_parse_error (&MarkerOrient::parse ("blah", ()).map_err (|e| AttributeError::from (e))));
+        assert! (is_parse_error (&MarkerOrient::parse ("45blah", ()).map_err (|e| AttributeError::from 
(e))));
     }
 
     #[test]
     fn parses_marker_orient () {
-        assert_eq! (MarkerOrient::from_str ("auto"), Ok (MarkerOrient::Auto));
+        assert_eq! (MarkerOrient::parse ("auto", ()), Ok (MarkerOrient::Auto));
 
-        assert_eq! (MarkerOrient::from_str ("0"), Ok (MarkerOrient::Degrees (0.0)));
-        assert_eq! (MarkerOrient::from_str ("180"), Ok (MarkerOrient::Degrees (180.0)));
-        assert_eq! (MarkerOrient::from_str ("180deg"), Ok (MarkerOrient::Degrees (180.0)));
-        assert_eq! (MarkerOrient::from_str ("-400grad"), Ok (MarkerOrient::Degrees (-360.0)));
-        assert_eq! (MarkerOrient::from_str ("1rad"), Ok (MarkerOrient::Degrees (180.0 / PI)));
+        assert_eq! (MarkerOrient::parse ("0", ()), Ok (MarkerOrient::Degrees (0.0)));
+        assert_eq! (MarkerOrient::parse ("180", ()), Ok (MarkerOrient::Degrees (180.0)));
+        assert_eq! (MarkerOrient::parse ("180deg", ()), Ok (MarkerOrient::Degrees (180.0)));
+        assert_eq! (MarkerOrient::parse ("-400grad", ()), Ok (MarkerOrient::Degrees (-360.0)));
+        assert_eq! (MarkerOrient::parse ("1rad", ()), Ok (MarkerOrient::Degrees (180.0 / PI)));
     }
 }
 
diff --git a/rust/src/paint_server.rs b/rust/src/paint_server.rs
index e5f0342..3e5af59 100644
--- a/rust/src/paint_server.rs
+++ b/rust/src/paint_server.rs
@@ -1,8 +1,7 @@
 use ::cairo;
 
-use std::str::FromStr;
-
 use error::*;
+use parsers::Parse;
 use parsers::ParseError;
 
 /// Defines the units to be used for scaling paint servers, per the [svg specification].
@@ -14,10 +13,11 @@ pub enum PaintServerUnits {
     ObjectBoundingBox
 }
 
-impl FromStr for PaintServerUnits {
+impl Parse for PaintServerUnits {
+    type Data = ();
     type Err = AttributeError;
 
-    fn from_str (s: &str) -> Result<PaintServerUnits, AttributeError> {
+    fn parse (s: &str, _: ()) -> Result<PaintServerUnits, AttributeError> {
         match s {
             "userSpaceOnUse"    => Ok (PaintServerUnits::UserSpaceOnUse),
             "objectBoundingBox" => Ok (PaintServerUnits::ObjectBoundingBox),
@@ -32,14 +32,14 @@ impl Default for PaintServerUnits {
     }
 }
 
-// We define this as a newtype so we can impl FromStr on it
 #[derive(Debug, Copy, Clone, PartialEq)]
 pub struct PaintServerSpread (pub cairo::enums::Extend);
 
-impl FromStr for PaintServerSpread {
+impl Parse for PaintServerSpread {
+    type Data = ();
     type Err = AttributeError;
 
-    fn from_str (s: &str) -> Result <PaintServerSpread, AttributeError> {
+    fn parse (s: &str, _: ()) -> Result <PaintServerSpread, AttributeError> {
         match s {
             "pad"     => Ok (PaintServerSpread (cairo::enums::Extend::Pad)),
             "reflect" => Ok (PaintServerSpread (cairo::enums::Extend::Reflect)),
@@ -58,31 +58,30 @@ impl Default for PaintServerSpread {
 #[cfg(test)]
 mod tests {
     use super::*;
-    use std::str::FromStr;
 
     #[test]
     fn parsing_invalid_strings_yields_error () {
-        assert! (PaintServerUnits::from_str ("").is_err ());
-        assert! (PaintServerUnits::from_str ("foo").is_err ());
+        assert! (PaintServerUnits::parse ("", ()).is_err ());
+        assert! (PaintServerUnits::parse ("foo", ()).is_err ());
     }
 
     #[test]
     fn parses_paint_server_units () {
-        assert_eq! (PaintServerUnits::from_str ("userSpaceOnUse"), Ok (PaintServerUnits::UserSpaceOnUse));
-        assert_eq! (PaintServerUnits::from_str ("objectBoundingBox"), Ok 
(PaintServerUnits::ObjectBoundingBox));
+        assert_eq! (PaintServerUnits::parse ("userSpaceOnUse", ()), Ok (PaintServerUnits::UserSpaceOnUse));
+        assert_eq! (PaintServerUnits::parse ("objectBoundingBox", ()), Ok 
(PaintServerUnits::ObjectBoundingBox));
     }
 
     #[test]
     fn parses_spread_method () {
-        assert_eq! (PaintServerSpread::from_str ("pad"),
+        assert_eq! (PaintServerSpread::parse ("pad", ()),
                     Ok (PaintServerSpread (cairo::enums::Extend::Pad)));
 
-        assert_eq! (PaintServerSpread::from_str ("reflect"),
+        assert_eq! (PaintServerSpread::parse ("reflect", ()),
                     Ok (PaintServerSpread (cairo::enums::Extend::Reflect)));
 
-        assert_eq! (PaintServerSpread::from_str ("repeat"),
+        assert_eq! (PaintServerSpread::parse ("repeat", ()),
                     Ok (PaintServerSpread (cairo::enums::Extend::Repeat)));
 
-        assert! (PaintServerSpread::from_str ("foobar").is_err ());
+        assert! (PaintServerSpread::parse ("foobar", ()).is_err ());
     }
 }
diff --git a/rust/src/parsers.rs b/rust/src/parsers.rs
index 70d2449..4130a50 100644
--- a/rust/src/parsers.rs
+++ b/rust/src/parsers.rs
@@ -26,6 +26,13 @@ impl<'a> From<BasicParseError<'a>> for ParseError {
     }
 }
 
+pub trait Parse: Sized {
+    type Data;
+    type Err;
+
+    fn parse (s: &str, data: Self::Data) -> Result<Self, Self::Err>;
+}
+
 // angle:
 // https://www.w3.org/TR/SVG/types.html#DataTypeAngle
 //
diff --git a/rust/src/pattern.rs b/rust/src/pattern.rs
index 901cb73..a3b31e8 100644
--- a/rust/src/pattern.rs
+++ b/rust/src/pattern.rs
@@ -5,7 +5,6 @@ use ::libc;
 
 use std::cell::RefCell;
 use std::rc::*;
-use std::str::FromStr;
 
 use cairo::MatrixTrait;
 use cairo::Pattern as CairoPattern;
@@ -19,6 +18,7 @@ use handle::RsvgHandle;
 use length::*;
 use node::*;
 use paint_server::*;
+use parsers::Parse;
 use property_bag;
 use property_bag::*;
 use util::*;
@@ -83,11 +83,12 @@ impl Default for PatternContentUnits {
     }
 }
 
-impl FromStr for PatternContentUnits {
+impl Parse for PatternContentUnits {
+    type Data = ();
     type Err = AttributeError;
 
-    fn from_str (s: &str) -> Result<PatternContentUnits, AttributeError> {
-        Ok (PatternContentUnits::from (PaintServerUnits::from_str (s)?))
+    fn parse (s: &str, _: ()) -> Result<PatternContentUnits, AttributeError> {
+        Ok (PatternContentUnits::from (PaintServerUnits::parse (s, ())?))
     }
 }
 
@@ -198,11 +199,11 @@ impl NodeTrait for NodePattern {
 
         p.node = Some (Rc::downgrade (node));
 
-        p.units         = property_bag::parse_or_none (pbag, "patternUnits")?;
-        p.content_units = property_bag::parse_or_none (pbag, "patternContentUnits")?;
-        p.vbox          = property_bag::parse_or_none (pbag, "viewBox")?.map (Some).or (None);
+        p.units         = property_bag::parse_or_none (pbag, "patternUnits", ())?;
+        p.content_units = property_bag::parse_or_none (pbag, "patternContentUnits", ())?;
+        p.vbox          = property_bag::parse_or_none (pbag, "viewBox", ())?.map (Some).or (None);
 
-        p.preserve_aspect_ratio = property_bag::parse_or_none (pbag, "preserveAspectRatio")?;
+        p.preserve_aspect_ratio = property_bag::parse_or_none (pbag, "preserveAspectRatio", ())?;
 
         p.affine = property_bag::transform_or_none (pbag, "patternTransform")?;
 
diff --git a/rust/src/property_bag.rs b/rust/src/property_bag.rs
index 90b516f..271be08 100644
--- a/rust/src/property_bag.rs
+++ b/rust/src/property_bag.rs
@@ -2,11 +2,10 @@ use ::cairo;
 use ::glib::translate::*;
 use ::libc;
 
-use std::str::FromStr;
-
 use error::*;
 use length::*;
 use transform::*;
+use parsers::Parse;
 
 pub enum RsvgPropertyBag {}
 
@@ -66,14 +65,14 @@ pub fn length_or_value (pbag: *const RsvgPropertyBag, key: &'static str, length_
     }
 }
 
-pub fn parse_or_none<T> (pbag: *const RsvgPropertyBag, key: &'static str) -> Result <Option<T>, NodeError>
-    where T: FromStr<Err = AttributeError>
+pub fn parse_or_none<T> (pbag: *const RsvgPropertyBag, key: &'static str, data: <T as Parse>::Data) -> 
Result <Option<T>, NodeError>
+    where T: Parse<Err = AttributeError>
 {
     let value = lookup (pbag, key);
 
     match value {
         Some (v) => {
-            T::from_str (&v).map (|v| Some (v))
+            T::parse (&v, data).map (|v| Some (v))
                 .map_err (|e| NodeError::attribute_error (key, e))
         },
 
@@ -81,16 +80,16 @@ pub fn parse_or_none<T> (pbag: *const RsvgPropertyBag, key: &'static str) -> Res
     }
 }
 
-pub fn parse_or_default<T> (pbag: *const RsvgPropertyBag, key: &'static str) -> Result <T, NodeError>
-    where T: Default + FromStr<Err = AttributeError> + Copy
+pub fn parse_or_default<T> (pbag: *const RsvgPropertyBag, key: &'static str, data: <T as Parse>::Data) -> 
Result <T, NodeError>
+    where T: Default + Parse<Err = AttributeError> + Copy
 {
-    parse_or_value (pbag, key, T::default ())
+    parse_or_value (pbag, key, data, T::default ())
 }
 
-pub fn parse_or_value<T> (pbag: *const RsvgPropertyBag, key: &'static str, value: T) -> Result <T, NodeError>
-    where T: Default + FromStr<Err = AttributeError> + Copy
+pub fn parse_or_value<T> (pbag: *const RsvgPropertyBag, key: &'static str, data: <T as Parse>::Data, value: 
T) -> Result <T, NodeError>
+    where T: Default + Parse<Err = AttributeError> + Copy
 {
-    let r = parse_or_none::<T> (pbag, key);
+    let r = parse_or_none::<T> (pbag, key, data);
 
     match r {
         Ok (Some (v)) => Ok (v),
diff --git a/rust/src/structure.rs b/rust/src/structure.rs
index 6f3bbbb..e660b19 100644
--- a/rust/src/structure.rs
+++ b/rust/src/structure.rs
@@ -135,7 +135,7 @@ impl NodeSvg {
 
 impl NodeTrait for NodeSvg {
     fn set_atts (&self, node: &RsvgNode, _: *const RsvgHandle, pbag: *const RsvgPropertyBag) -> NodeResult {
-        self.preserve_aspect_ratio.set (property_bag::parse_or_default (pbag, "preserveAspectRatio")?);
+        self.preserve_aspect_ratio.set (property_bag::parse_or_default (pbag, "preserveAspectRatio", ())?);
 
         // x & y attributes have no effect on outermost svg
         // http://www.w3.org/TR/SVG/struct.html#SVGElement
@@ -152,7 +152,7 @@ impl NodeTrait for NodeSvg {
                     .and_then (|l| l.check_nonnegative ()
                                .map_err (|e| NodeError::attribute_error ("height", e)))?);
 
-        self.vbox.set (property_bag::parse_or_none (pbag, "viewBox")?);
+        self.vbox.set (property_bag::parse_or_none (pbag, "viewBox", ())?);
 
         // The "style" sub-element is not loaded yet here, so we need
         // to store other attributes to be applied later.
@@ -419,8 +419,8 @@ impl NodeSymbol {
 
 impl NodeTrait for NodeSymbol {
     fn set_atts (&self, _: &RsvgNode, _: *const RsvgHandle, pbag: *const RsvgPropertyBag) -> NodeResult {
-        self.preserve_aspect_ratio.set (property_bag::parse_or_default (pbag, "preserveAspectRatio")?);
-        self.vbox.set (property_bag::parse_or_none (pbag, "viewBox")?);
+        self.preserve_aspect_ratio.set (property_bag::parse_or_default (pbag, "preserveAspectRatio", ())?);
+        self.vbox.set (property_bag::parse_or_none (pbag, "viewBox", ())?);
 
         Ok (())
     }
diff --git a/rust/src/viewbox.rs b/rust/src/viewbox.rs
index 9abe7a2..1e882f7 100644
--- a/rust/src/viewbox.rs
+++ b/rust/src/viewbox.rs
@@ -2,10 +2,9 @@ use ::cairo;
 use ::glib_sys;
 use ::glib;
 
-use std::str::FromStr;
-
 use error::*;
 use parsers;
+use parsers::Parse;
 use parsers::{ListLength, ParseError};
 
 use self::glib::translate::*;
@@ -40,7 +39,8 @@ impl From<Option<ViewBox>> for RsvgViewBox {
     }
 }
 
-impl FromStr for ViewBox {
+impl Parse for ViewBox {
+    type Data = ();
     type Err = AttributeError;
 
     // Parse a viewBox attribute
@@ -51,7 +51,7 @@ impl FromStr for ViewBox {
     // x, y, w, h
     //
     // Where w and h must be nonnegative.
-    fn from_str (s: &str) -> Result<ViewBox, AttributeError> {
+    fn parse (s: &str, _: ()) -> Result<ViewBox, AttributeError> {
         let v = parsers::number_list (s, ListLength::Exact (4))
             .map_err (|_| ParseError::new ("string does not match 'x [,] y [,] w [,] h'"))?;
 
@@ -71,17 +71,16 @@ impl FromStr for ViewBox {
 #[cfg(test)]
 mod tests {
     use super::*;
-    use std::str::FromStr;
 
     #[test]
     fn parses_valid_viewboxes () {
-        assert_eq! (ViewBox::from_str ("  1 2 3 4"),
+        assert_eq! (ViewBox::parse ("  1 2 3 4", ()),
                     Ok (ViewBox (cairo::Rectangle { x: 1.0,
                                                     y: 2.0,
                                                     width: 3.0,
                                                     height: 4.0 })));
 
-        assert_eq! (ViewBox::from_str (" -1.5 -2.5e1,34,56e2  "),
+        assert_eq! (ViewBox::parse (" -1.5 -2.5e1,34,56e2  ", ()),
                     Ok (ViewBox (cairo::Rectangle { x: -1.5,
                                                     y: -25.0,
                                                     width: 34.0,
@@ -90,14 +89,14 @@ mod tests {
 
     #[test]
     fn parsing_invalid_viewboxes_yields_error () {
-        assert! (is_parse_error (&ViewBox::from_str ("")));
+        assert! (is_parse_error (&ViewBox::parse ("", ())));
 
-        assert! (is_value_error (&ViewBox::from_str (" 1,2,-3,-4 ")));
+        assert! (is_value_error (&ViewBox::parse (" 1,2,-3,-4 ", ())));
 
-        assert! (is_parse_error (&ViewBox::from_str ("qwerasdfzxcv")));
+        assert! (is_parse_error (&ViewBox::parse ("qwerasdfzxcv", ())));
 
-        assert! (is_parse_error (&ViewBox::from_str (" 1 2 3 4   5")));
+        assert! (is_parse_error (&ViewBox::parse (" 1 2 3 4   5", ())));
 
-        assert! (is_parse_error (&ViewBox::from_str (" 1 2 foo 3 4")));
+        assert! (is_parse_error (&ViewBox::parse (" 1 2 foo 3 4", ())));
     }
 }


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