[librsvg] parse_or_*() - Take an extra argument, a validation function



commit 5c9b8bb3114047da98b11b29541def1fcba1e706
Author: Federico Mena Quintero <federico gnome org>
Date:   Tue Sep 5 08:32:49 2017 -0500

    parse_or_*() - Take an extra argument, a validation function
    
    We'll use this to contain the extraction/parsing/validation of an
    attribute into a single function call, instead of making the caller
    implement the validation separately.

 rust/src/gradient.rs     |   25 +++++++++++++------------
 rust/src/marker.rs       |   20 +++++++++++---------
 rust/src/pattern.rs      |   18 +++++++++---------
 rust/src/property_bag.rs |   35 ++++++++++++++++++++++++++---------
 rust/src/shapes.rs       |   34 +++++++++++++++++-----------------
 rust/src/stop.rs         |    2 +-
 rust/src/structure.rs    |   32 ++++++++++++++++++++------------
 7 files changed, 97 insertions(+), 69 deletions(-)
---
diff --git a/rust/src/gradient.rs b/rust/src/gradient.rs
index 3150fc7..e1cc313 100644
--- a/rust/src/gradient.rs
+++ b/rust/src/gradient.rs
@@ -10,6 +10,7 @@ use cairo::MatrixTrait;
 use bbox::*;
 use drawing_ctx;
 use drawing_ctx::RsvgDrawingCtx;
+use error::*;
 use handle::RsvgHandle;
 use length::*;
 use node::*;
@@ -557,9 +558,9 @@ impl NodeTrait for NodeGradient {
 
         // Attributes common to linear and radial gradients
 
-        g.common.units    = property_bag::parse_or_none (pbag, "gradientUnits", ())?;
-        g.common.affine   = property_bag::parse_or_none (pbag, "gradientTransform", ())?;
-        g.common.spread   = property_bag::parse_or_none (pbag, "spreadMethod", ())?;
+        g.common.units    = property_bag::parse_or_none (pbag, "gradientUnits", (), None)?;
+        g.common.affine   = property_bag::parse_or_none (pbag, "gradientTransform", (), None)?;
+        g.common.spread   = property_bag::parse_or_none (pbag, "spreadMethod", (), None)?;
         g.common.fallback = property_bag::lookup (pbag, "xlink:href");
 
         // Attributes specific to each gradient type.  The defaults mandated by the spec
@@ -568,20 +569,20 @@ impl NodeTrait for NodeGradient {
         match node.get_type () {
             NodeType::LinearGradient => {
                 g.variant = GradientVariant::Linear {
-                    x1: property_bag::parse_or_none (pbag, "x1", LengthDir::Horizontal)?,
-                    y1: property_bag::parse_or_none (pbag, "y1", LengthDir::Vertical)?,
-                    x2: property_bag::parse_or_none (pbag, "x2", LengthDir::Horizontal)?,
-                    y2: property_bag::parse_or_none (pbag, "y2", LengthDir::Vertical)?
+                    x1: property_bag::parse_or_none (pbag, "x1", LengthDir::Horizontal, None)?,
+                    y1: property_bag::parse_or_none (pbag, "y1", LengthDir::Vertical, None)?,
+                    x2: property_bag::parse_or_none (pbag, "x2", LengthDir::Horizontal, None)?,
+                    y2: property_bag::parse_or_none (pbag, "y2", LengthDir::Vertical, None)?
                 };
             },
 
             NodeType::RadialGradient => {
                 g.variant = GradientVariant::Radial {
-                    cx: property_bag::parse_or_none (pbag, "cx", LengthDir::Horizontal)?,
-                    cy: property_bag::parse_or_none (pbag, "cy", LengthDir::Vertical)?,
-                    r:  property_bag::parse_or_none (pbag, "r",  LengthDir::Both)?,
-                    fx: property_bag::parse_or_none (pbag, "fx", LengthDir::Horizontal)?,
-                    fy: property_bag::parse_or_none (pbag, "fy", LengthDir::Vertical)?
+                    cx: property_bag::parse_or_none (pbag, "cx", LengthDir::Horizontal, None)?,
+                    cy: property_bag::parse_or_none (pbag, "cy", LengthDir::Vertical, None)?,
+                    r:  property_bag::parse_or_none (pbag, "r",  LengthDir::Both, None)?,
+                    fx: property_bag::parse_or_none (pbag, "fx", LengthDir::Horizontal, None)?,
+                    fy: property_bag::parse_or_none (pbag, "fy", LengthDir::Vertical, None)?
                 };
             },
 
diff --git a/rust/src/marker.rs b/rust/src/marker.rs
index f4c0164..3c82461 100644
--- a/rust/src/marker.rs
+++ b/rust/src/marker.rs
@@ -192,27 +192,29 @@ 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", (), None)?);
 
-        self.ref_x.set (property_bag::parse_or_default (pbag, "refX", LengthDir::Horizontal)?);
-        self.ref_y.set (property_bag::parse_or_default (pbag, "refY", LengthDir::Vertical)?);
+        self.ref_x.set (property_bag::parse_or_default (pbag, "refX", LengthDir::Horizontal, None)?);
+        self.ref_y.set (property_bag::parse_or_default (pbag, "refY", LengthDir::Vertical, None)?);
 
         self.width.set (property_bag::parse_or_value (pbag, "markerWidth",
                                                       LengthDir::Horizontal,
-                                                      NodeMarker::get_default_size (LengthDir::Horizontal))?
+                                                      NodeMarker::get_default_size (LengthDir::Horizontal),
+                                                      None)?
                         .check_nonnegative ()
                         .map_err (|e| NodeError::attribute_error ("markerWidth", e))?);
 
         self.height.set (property_bag::parse_or_value (pbag, "markerHeight",
                                                        LengthDir::Vertical,
-                                                       NodeMarker::get_default_size (LengthDir::Vertical))?
+                                                       NodeMarker::get_default_size (LengthDir::Vertical),
+                                                       None)?
                          .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", (), None)?);
+        self.aspect.set (property_bag::parse_or_default (pbag, "preserveAspectRatio", (), None)?);
+        self.vbox.set   (property_bag::parse_or_none (pbag, "viewBox", (), None)?);
+        self.aspect.set (property_bag::parse_or_default (pbag, "preserveAspectRatio", (), None)?);
 
         Ok (())
     }
diff --git a/rust/src/pattern.rs b/rust/src/pattern.rs
index fdf7dce..c601edf 100644
--- a/rust/src/pattern.rs
+++ b/rust/src/pattern.rs
@@ -199,20 +199,20 @@ 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", (), None)?;
+        p.content_units = property_bag::parse_or_none (pbag, "patternContentUnits", (), None)?;
+        p.vbox          = property_bag::parse_or_none (pbag, "viewBox", (), None)?.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", (), None)?;
 
-        p.affine = property_bag::parse_or_none (pbag, "patternTransform", ())?;
+        p.affine = property_bag::parse_or_none (pbag, "patternTransform", (), None)?;
 
         p.fallback = property_bag::lookup (pbag, "xlink:href");
 
-        p.x      = property_bag::parse_or_none (pbag, "x", LengthDir::Horizontal)?;
-        p.y      = property_bag::parse_or_none (pbag, "y", LengthDir::Vertical)?;
-        p.width  = property_bag::parse_or_none (pbag, "width", LengthDir::Horizontal)?;
-        p.height = property_bag::parse_or_none (pbag, "height", LengthDir::Vertical)?;
+        p.x      = property_bag::parse_or_none (pbag, "x", LengthDir::Horizontal, None)?;
+        p.y      = property_bag::parse_or_none (pbag, "y", LengthDir::Vertical, None)?;
+        p.width  = property_bag::parse_or_none (pbag, "width", LengthDir::Horizontal, None)?;
+        p.height = property_bag::parse_or_none (pbag, "height", LengthDir::Vertical, None)?;
 
         Ok (())
     }
diff --git a/rust/src/property_bag.rs b/rust/src/property_bag.rs
index 90d06f7..0d32b3b 100644
--- a/rust/src/property_bag.rs
+++ b/rust/src/property_bag.rs
@@ -32,31 +32,48 @@ pub fn free (pbag: *mut RsvgPropertyBag) {
     }
 }
 
-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>
+pub fn parse_or_none<T> (pbag: *const RsvgPropertyBag,
+                         key: &'static str,
+                         data: <T as Parse>::Data,
+                         validate: Option<fn(T) -> Result<T, AttributeError>>) -> Result <Option<T>, 
NodeError>
+    where T: Parse<Err = AttributeError> + Copy
 {
     let value = lookup (pbag, key);
 
     match value {
         Some (v) => {
-            T::parse (&v, data).map (|v| Some (v))
+            T::parse (&v, data)
+                .and_then (|v|
+                           if let Some(validate) = validate {
+                               validate(v)
+                                   .map(|v| Some(v))
+                           } else {
+                               Ok(Some(v))
+                           })
                 .map_err (|e| NodeError::attribute_error (key, e))
         },
 
-        None => Ok (None)
+        None => Ok(None)
     }
 }
 
-pub fn parse_or_default<T> (pbag: *const RsvgPropertyBag, key: &'static str, data: <T as Parse>::Data) -> 
Result <T, NodeError>
+pub fn parse_or_default<T> (pbag: *const RsvgPropertyBag,
+                            key: &'static str,
+                            data: <T as Parse>::Data,
+                            validate: Option<fn(T) -> Result<T, AttributeError>>) -> Result <T, NodeError>
     where T: Default + Parse<Err = AttributeError> + Copy
 {
-    parse_or_value (pbag, key, data, T::default ())
+    parse_or_value (pbag, key, data, T::default (), validate)
 }
 
-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
+pub fn parse_or_value<T> (pbag: *const RsvgPropertyBag,
+                          key: &'static str,
+                          data: <T as Parse>::Data,
+                          value: T,
+                          validate: Option<fn(T) -> Result<T, AttributeError>>) -> Result <T, NodeError>
+    where T: Parse<Err = AttributeError> + Copy
 {
-    let r = parse_or_none::<T> (pbag, key, data);
+    let r = parse_or_none (pbag, key, data, validate);
 
     match r {
         Ok (Some (v)) => Ok (v),
diff --git a/rust/src/shapes.rs b/rust/src/shapes.rs
index 360e886..6705d75 100644
--- a/rust/src/shapes.rs
+++ b/rust/src/shapes.rs
@@ -201,10 +201,10 @@ impl NodeLine {
 
 impl NodeTrait for NodeLine {
     fn set_atts (&self, _: &RsvgNode, _: *const RsvgHandle, pbag: *const RsvgPropertyBag) -> NodeResult {
-        self.x1.set (property_bag::parse_or_default (pbag, "x1", LengthDir::Horizontal)?);
-        self.y1.set (property_bag::parse_or_default (pbag, "y1", LengthDir::Vertical)?);
-        self.x2.set (property_bag::parse_or_default (pbag, "x2", LengthDir::Horizontal)?);
-        self.y2.set (property_bag::parse_or_default (pbag, "y2", LengthDir::Vertical)?);
+        self.x1.set (property_bag::parse_or_default (pbag, "x1", LengthDir::Horizontal, None)?);
+        self.y1.set (property_bag::parse_or_default (pbag, "y1", LengthDir::Vertical, None)?);
+        self.x2.set (property_bag::parse_or_default (pbag, "x2", LengthDir::Horizontal, None)?);
+        self.y2.set (property_bag::parse_or_default (pbag, "y2", LengthDir::Vertical, None)?);
 
         Ok (())
     }
@@ -258,13 +258,13 @@ impl NodeRect {
 
 impl NodeTrait for NodeRect {
     fn set_atts (&self, _: &RsvgNode, _: *const RsvgHandle, pbag: *const RsvgPropertyBag) -> NodeResult {
-        self.x.set (property_bag::parse_or_default (pbag, "x", LengthDir::Horizontal)?);
-        self.y.set (property_bag::parse_or_default (pbag, "y", LengthDir::Vertical)?);
-        self.w.set (property_bag::parse_or_default (pbag, "width", LengthDir::Horizontal)?);
-        self.h.set (property_bag::parse_or_default (pbag, "height", LengthDir::Vertical)?);
+        self.x.set (property_bag::parse_or_default (pbag, "x", LengthDir::Horizontal, None)?);
+        self.y.set (property_bag::parse_or_default (pbag, "y", LengthDir::Vertical, None)?);
+        self.w.set (property_bag::parse_or_default (pbag, "width", LengthDir::Horizontal, None)?);
+        self.h.set (property_bag::parse_or_default (pbag, "height", LengthDir::Vertical, None)?);
 
-        self.rx.set (property_bag::parse_or_none (pbag, "rx", LengthDir::Horizontal)?);
-        self.ry.set (property_bag::parse_or_none (pbag, "ry", LengthDir::Vertical)?);
+        self.rx.set (property_bag::parse_or_none (pbag, "rx", LengthDir::Horizontal, None)?);
+        self.ry.set (property_bag::parse_or_none (pbag, "ry", LengthDir::Vertical, None)?);
 
         Ok (())
     }
@@ -433,10 +433,10 @@ impl NodeCircle {
 
 impl NodeTrait for NodeCircle {
     fn set_atts (&self, _: &RsvgNode, _: *const RsvgHandle, pbag: *const RsvgPropertyBag) -> NodeResult {
-        self.cx.set (property_bag::parse_or_default (pbag, "cx", LengthDir::Horizontal)?);
-        self.cy.set (property_bag::parse_or_default (pbag, "cy", LengthDir::Vertical)?);
+        self.cx.set (property_bag::parse_or_default (pbag, "cx", LengthDir::Horizontal, None)?);
+        self.cy.set (property_bag::parse_or_default (pbag, "cy", LengthDir::Vertical, None)?);
 
-        self.r.set  (property_bag::parse_or_default (pbag, "r", LengthDir::Both)
+        self.r.set  (property_bag::parse_or_default (pbag, "r", LengthDir::Both, None)
                      .and_then (|l: RsvgLength| l.check_nonnegative ()
                                 .map_err (|e| NodeError::attribute_error ("r", e)))?);
 
@@ -478,14 +478,14 @@ impl NodeEllipse {
 
 impl NodeTrait for NodeEllipse {
     fn set_atts (&self, _: &RsvgNode, _: *const RsvgHandle, pbag: *const RsvgPropertyBag) -> NodeResult {
-        self.cx.set (property_bag::parse_or_default (pbag, "cx", LengthDir::Horizontal)?);
-        self.cy.set (property_bag::parse_or_default (pbag, "cy", LengthDir::Vertical)?);
+        self.cx.set (property_bag::parse_or_default (pbag, "cx", LengthDir::Horizontal, None)?);
+        self.cy.set (property_bag::parse_or_default (pbag, "cy", LengthDir::Vertical, None)?);
 
-        self.rx.set (property_bag::parse_or_default (pbag, "rx", LengthDir::Horizontal)
+        self.rx.set (property_bag::parse_or_default (pbag, "rx", LengthDir::Horizontal, None)
                      .and_then (|l: RsvgLength| l.check_nonnegative ()
                                 .map_err (|e| NodeError::attribute_error ("rx", e)))?);
 
-        self.ry.set (property_bag::parse_or_default (pbag, "ry", LengthDir::Vertical)
+        self.ry.set (property_bag::parse_or_default (pbag, "ry", LengthDir::Vertical, None)
                      .and_then (|l: RsvgLength| l.check_nonnegative ()
                                 .map_err (|e| NodeError::attribute_error ("ry", e)))?);
 
diff --git a/rust/src/stop.rs b/rust/src/stop.rs
index 780b8ea..fd51511 100644
--- a/rust/src/stop.rs
+++ b/rust/src/stop.rs
@@ -40,7 +40,7 @@ impl NodeStop {
 
 impl NodeTrait for NodeStop {
     fn set_atts (&self, node: &RsvgNode, handle: *const RsvgHandle, pbag: *const RsvgPropertyBag) -> 
NodeResult {
-        let offset_length: RsvgLength = property_bag::parse_or_default (pbag, "offset", LengthDir::Both)?;
+        let offset_length: RsvgLength = property_bag::parse_or_default (pbag, "offset", LengthDir::Both, 
None)?;
         match offset_length.unit {
             LengthUnit::Default |
             LengthUnit::Percent => {
diff --git a/rust/src/structure.rs b/rust/src/structure.rs
index fea1e41..c9edbb3 100644
--- a/rust/src/structure.rs
+++ b/rust/src/structure.rs
@@ -136,24 +136,32 @@ 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", (), 
None)?);
 
         // x & y attributes have no effect on outermost svg
         // http://www.w3.org/TR/SVG/struct.html#SVGElement
         if node.get_parent ().is_some () {
-            self.x.set (property_bag::parse_or_default (pbag, "x", LengthDir::Horizontal)?);
-            self.y.set (property_bag::parse_or_default (pbag, "y", LengthDir::Vertical)?);
+            self.x.set (property_bag::parse_or_default (pbag, "x", LengthDir::Horizontal, None)?);
+            self.y.set (property_bag::parse_or_default (pbag, "y", LengthDir::Vertical, None)?);
         }
 
-        self.w.set (property_bag::parse_or_value (pbag, "width", LengthDir::Horizontal, RsvgLength::parse 
("100%", LengthDir::Horizontal).unwrap ())
+        self.w.set (property_bag::parse_or_value (pbag,
+                                                  "width",
+                                                  LengthDir::Horizontal,
+                                                  RsvgLength::parse ("100%", LengthDir::Horizontal).unwrap 
(),
+                                                  None)
                     .and_then (|l| l.check_nonnegative ()
                                .map_err (|e| NodeError::attribute_error ("width", e)))?);
 
-        self.h.set (property_bag::parse_or_value (pbag, "height", LengthDir::Vertical, RsvgLength::parse 
("100%", LengthDir::Vertical).unwrap ())
+        self.h.set (property_bag::parse_or_value (pbag,
+                                                  "height",
+                                                  LengthDir::Vertical,
+                                                  RsvgLength::parse ("100%", LengthDir::Vertical).unwrap (),
+                                                  None)
                     .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", (), None)?);
 
         // The "style" sub-element is not loaded yet here, so we need
         // to store other attributes to be applied later.
@@ -265,10 +273,10 @@ impl NodeTrait for NodeUse {
     fn set_atts (&self, _: &RsvgNode, _: *const RsvgHandle, pbag: *const RsvgPropertyBag) -> NodeResult {
         *self.link.borrow_mut () = property_bag::lookup (pbag, "xlink:href");
 
-        self.x.set (property_bag::parse_or_default (pbag, "x", LengthDir::Horizontal)?);
-        self.y.set (property_bag::parse_or_default (pbag, "y", LengthDir::Vertical)?);
+        self.x.set (property_bag::parse_or_default (pbag, "x", LengthDir::Horizontal, None)?);
+        self.y.set (property_bag::parse_or_default (pbag, "y", LengthDir::Vertical, None)?);
 
-        let opt_w: Option<RsvgLength> = property_bag::parse_or_none (pbag, "width", LengthDir::Horizontal)?;
+        let opt_w: Option<RsvgLength> = property_bag::parse_or_none (pbag, "width", LengthDir::Horizontal, 
None)?;
         self.w.set (match opt_w {
             Some (w) => {
                 Some (w.check_nonnegative ().map_err (|e| NodeError::attribute_error ("width", e))?)
@@ -279,7 +287,7 @@ impl NodeTrait for NodeUse {
             }
         });
 
-        let opt_h: Option<RsvgLength> = property_bag::parse_or_none (pbag, "height", LengthDir::Vertical)?;
+        let opt_h: Option<RsvgLength> = property_bag::parse_or_none (pbag, "height", LengthDir::Vertical, 
None)?;
         let h = match opt_h {
             Some (h) => {
                 Some (h.check_nonnegative ().map_err (|e| NodeError::attribute_error ("height", e))?)
@@ -420,8 +428,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", (), 
None)?);
+        self.vbox.set (property_bag::parse_or_none (pbag, "viewBox", (), None)?);
 
         Ok (())
     }


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