[librsvg: 59/95] PropertyBag: make iteration return (key, attr, value) tuples



commit ce1911826638337ec487955c78eb73811cbec742
Author: Federico Mena Quintero <federico gnome org>
Date:   Wed Feb 21 08:59:25 2018 -0600

    PropertyBag: make iteration return (key, attr, value) tuples
    
    This is so that callers don't have to convert the key to an Attribute
    themselves.
    
    This also means that pbag.iter() now *only* yields elements whose
    attributes are known in the PHF mapping in build.rs.  The rest of the
    code won't know how to process unknown attributes, anyway.

 rust/src/clip_path.rs    |  13 ++---
 rust/src/gradient.rs     |  49 ++++++++---------
 rust/src/image.rs        |  73 ++++++++++++-------------
 rust/src/marker.rs       |  45 ++++++++--------
 rust/src/mask.rs         |  35 ++++++------
 rust/src/pattern.rs      |  53 +++++++++----------
 rust/src/property_bag.rs |  97 +++++++++++++++++++---------------
 rust/src/shapes.rs       | 135 +++++++++++++++++++++--------------------------
 rust/src/stop.rs         |  49 ++++++++---------
 rust/src/structure.rs    |  89 ++++++++++++++-----------------
 10 files changed, 304 insertions(+), 334 deletions(-)
---
diff --git a/rust/src/clip_path.rs b/rust/src/clip_path.rs
index 878010a4..27b58327 100644
--- a/rust/src/clip_path.rs
+++ b/rust/src/clip_path.rs
@@ -1,6 +1,5 @@
 use libc;
 use std::cell::Cell;
-use std::str::FromStr;
 
 use attributes::Attribute;
 use drawing_ctx::RsvgDrawingCtx;
@@ -26,14 +25,12 @@ impl NodeClipPath {
 
 impl NodeTrait for NodeClipPath {
     fn set_atts(&self, _: &RsvgNode, _: *const RsvgHandle, pbag: &PropertyBag) -> NodeResult {
-        for (key, value) in pbag.iter() {
-            if let Ok(attr) = Attribute::from_str(key) {
-                match attr {
-                    Attribute::ClipPathUnits =>
-                        self.units.set(parse("clipPathUnits", value, (), None)?),
+        for (_key, attr, value) in pbag.iter() {
+            match attr {
+                Attribute::ClipPathUnits =>
+                    self.units.set(parse("clipPathUnits", value, (), None)?),
 
-                    _ => (),
-                }
+                _ => (),
             }
         }
 
diff --git a/rust/src/gradient.rs b/rust/src/gradient.rs
index ba120174..89856ac5 100644
--- a/rust/src/gradient.rs
+++ b/rust/src/gradient.rs
@@ -2,7 +2,6 @@ use cairo;
 use libc;
 
 use std::cell::RefCell;
-use std::str::FromStr;
 
 use cairo::MatrixTrait;
 
@@ -599,39 +598,37 @@ impl NodeTrait for NodeGradient {
         let mut fx = None;
         let mut fy = None;
 
-        for (key, value) in pbag.iter() {
-            if let Ok(attr) = Attribute::from_str(key) {
-                match attr {
-                    // Attributes common to linear and radial gradients
+        for (_key, attr, value) in pbag.iter() {
+            match attr {
+                // Attributes common to linear and radial gradients
 
-                    Attribute::GradientUnits =>
-                        g.common.units = Some(parse("gradientUnits", value, (), None)?),
+                Attribute::GradientUnits =>
+                    g.common.units = Some(parse("gradientUnits", value, (), None)?),
 
-                    Attribute::GradientTransform =>
-                        g.common.affine = Some(parse("gradientTransform", value, (), None)?),
+                Attribute::GradientTransform =>
+                    g.common.affine = Some(parse("gradientTransform", value, (), None)?),
 
-                    Attribute::SpreadMethod =>
-                        g.common.spread = Some(parse("spreadMethod", value, (), None)?),
+                Attribute::SpreadMethod =>
+                    g.common.spread = Some(parse("spreadMethod", value, (), None)?),
 
-                    Attribute::XlinkHref =>
-                        g.common.fallback = Some(value.to_owned()),
+                Attribute::XlinkHref =>
+                    g.common.fallback = Some(value.to_owned()),
 
-                    // Attributes specific to each gradient type.  The defaults mandated by the spec
-                    // are in GradientVariant::resolve_from_defaults()
+                // Attributes specific to each gradient type.  The defaults mandated by the spec
+                // are in GradientVariant::resolve_from_defaults()
 
-                    Attribute::X1 => x1 = Some(parse("x1", value, LengthDir::Horizontal, None)?),
-                    Attribute::Y1 => y1 = Some(parse("y1", value, LengthDir::Vertical, None)?),
-                    Attribute::X2 => x2 = Some(parse("x2", value, LengthDir::Horizontal, None)?),
-                    Attribute::Y2 => y2 = Some(parse("y2", value, LengthDir::Vertical, None)?),
+                Attribute::X1 => x1 = Some(parse("x1", value, LengthDir::Horizontal, None)?),
+                Attribute::Y1 => y1 = Some(parse("y1", value, LengthDir::Vertical, None)?),
+                Attribute::X2 => x2 = Some(parse("x2", value, LengthDir::Horizontal, None)?),
+                Attribute::Y2 => y2 = Some(parse("y2", value, LengthDir::Vertical, None)?),
 
-                    Attribute::Cx => cx = Some(parse("cx", value, LengthDir::Horizontal, None)?),
-                    Attribute::Cy => cy = Some(parse("cy", value, LengthDir::Vertical, None)?),
-                    Attribute::R  => r  = Some(parse("r",  value, LengthDir::Both, None)?),
-                    Attribute::Fx => fx = Some(parse("fx", value, LengthDir::Horizontal, None)?),
-                    Attribute::Fy => fy = Some(parse("fy", value, LengthDir::Vertical, None)?),
+                Attribute::Cx => cx = Some(parse("cx", value, LengthDir::Horizontal, None)?),
+                Attribute::Cy => cy = Some(parse("cy", value, LengthDir::Vertical, None)?),
+                Attribute::R  => r  = Some(parse("r",  value, LengthDir::Both, None)?),
+                Attribute::Fx => fx = Some(parse("fx", value, LengthDir::Horizontal, None)?),
+                Attribute::Fy => fy = Some(parse("fy", value, LengthDir::Vertical, None)?),
 
-                    _ => (),
-                }
+                _ => (),
             }
         }
 
diff --git a/rust/src/image.rs b/rust/src/image.rs
index ec49bd51..e5f92d32 100644
--- a/rust/src/image.rs
+++ b/rust/src/image.rs
@@ -6,7 +6,6 @@ use glib::translate::*;
 use glib_sys;
 use std::cell::{Cell, RefCell};
 use std::ptr;
-use std::str::FromStr;
 
 use drawing_ctx;
 use drawing_ctx::RsvgDrawingCtx;
@@ -43,43 +42,41 @@ impl NodeImage {
 
 impl NodeTrait for NodeImage {
     fn set_atts (&self, _: &RsvgNode, handle: *const RsvgHandle, pbag: &PropertyBag) -> NodeResult {
-        for (key, value) in pbag.iter() {
-            if let Ok(attr) = Attribute::from_str(key) {
-                match attr {
-                    Attribute::X =>      self.x.set(parse("x", value, LengthDir::Horizontal, None)?),
-                    Attribute::Y =>      self.y.set(parse("y", value, LengthDir::Vertical, None)?),
-                    Attribute::Width =>  self.w.set(parse("width", value,  LengthDir::Horizontal,
-                                                         Some(RsvgLength::check_nonnegative))?),
-                    Attribute::Height => self.h.set(parse("height", value, LengthDir::Vertical,
-                                                          Some(RsvgLength::check_nonnegative))?),
-
-                    Attribute::PreserveAspectRatio =>
-                        self.aspect.set(parse("preserveAspectRatio", value, (), None)?),
-
-                    Attribute::XlinkHref |
-                    Attribute::Path => {
-                        // "path" is used by some older Adobe Illustrator versions
-
-                        extern "C" { fn rsvg_cairo_surface_new_from_href
-                                     (handle: *const RsvgHandle,
-                                      href:   *const libc::c_char,
-                                      error:  *mut *mut glib_sys::GError) -> *mut cairo_sys::cairo_surface_t;
-                        }
-
-                        let mut error = ptr::null_mut();
-
-                        let raw_surface = unsafe { rsvg_cairo_surface_new_from_href (handle,
-                                                                                     value.to_glib_none().0,
-                                                                                     &mut error) };
-                        if !raw_surface.is_null() {
-                            *self.surface.borrow_mut() = Some(unsafe { cairo::ImageSurface::from_raw_full 
(raw_surface).unwrap() });
-                        } else {
-                            let _: glib::Error = unsafe { from_glib_full(error) }; // FIXME: we should note 
that the image couldn't be loaded
-                        }
-                    },
-
-                    _ => (),
-                }
+        for (_key, attr, value) in pbag.iter() {
+            match attr {
+                Attribute::X =>      self.x.set(parse("x", value, LengthDir::Horizontal, None)?),
+                Attribute::Y =>      self.y.set(parse("y", value, LengthDir::Vertical, None)?),
+                Attribute::Width =>  self.w.set(parse("width", value,  LengthDir::Horizontal,
+                                                      Some(RsvgLength::check_nonnegative))?),
+                Attribute::Height => self.h.set(parse("height", value, LengthDir::Vertical,
+                                                      Some(RsvgLength::check_nonnegative))?),
+
+                Attribute::PreserveAspectRatio =>
+                    self.aspect.set(parse("preserveAspectRatio", value, (), None)?),
+
+                Attribute::XlinkHref |
+                Attribute::Path => {
+                    // "path" is used by some older Adobe Illustrator versions
+
+                    extern "C" { fn rsvg_cairo_surface_new_from_href
+                                 (handle: *const RsvgHandle,
+                                  href:   *const libc::c_char,
+                                  error:  *mut *mut glib_sys::GError) -> *mut cairo_sys::cairo_surface_t;
+                    }
+
+                    let mut error = ptr::null_mut();
+
+                    let raw_surface = unsafe { rsvg_cairo_surface_new_from_href (handle,
+                                                                                 value.to_glib_none().0,
+                                                                                 &mut error) };
+                    if !raw_surface.is_null() {
+                        *self.surface.borrow_mut() = Some(unsafe { cairo::ImageSurface::from_raw_full 
(raw_surface).unwrap() });
+                    } else {
+                        let _: glib::Error = unsafe { from_glib_full(error) }; // FIXME: we should note that 
the image couldn't be loaded
+                    }
+                },
+
+                _ => (),
             }
         }
 
diff --git a/rust/src/marker.rs b/rust/src/marker.rs
index 321484c3..09d8b43e 100644
--- a/rust/src/marker.rs
+++ b/rust/src/marker.rs
@@ -2,7 +2,6 @@ use libc;
 
 use std::cell::Cell;
 use std::f64::consts::*;
-use std::str::FromStr;
 
 use cairo::MatrixTrait;
 
@@ -193,37 +192,35 @@ impl NodeMarker {
 
 impl NodeTrait for NodeMarker {
     fn set_atts (&self, _: &RsvgNode, _: *const RsvgHandle, pbag: &PropertyBag) -> NodeResult {
-        for (key, value) in pbag.iter() {
-            if let Ok(attr) = Attribute::from_str(key) {
-                match attr {
-                    Attribute::MarkerUnits =>
-                        self.units.set(parse("markerUnits", value, (), None)?),
+        for (_key, attr, value) in pbag.iter() {
+            match attr {
+                Attribute::MarkerUnits =>
+                    self.units.set(parse("markerUnits", value, (), None)?),
 
-                    Attribute::RefX =>
-                        self.ref_x.set(parse("refX", value, LengthDir::Horizontal, None)?),
+                Attribute::RefX =>
+                    self.ref_x.set(parse("refX", value, LengthDir::Horizontal, None)?),
 
-                    Attribute::RefY =>
-                        self.ref_y.set(parse("refY", value, LengthDir::Vertical, None)?),
+                Attribute::RefY =>
+                    self.ref_y.set(parse("refY", value, LengthDir::Vertical, None)?),
 
-                    Attribute::MarkerWidth =>
-                        self.width.set(parse("markerWidth", value, LengthDir::Horizontal,
-                                             Some(RsvgLength::check_nonnegative))?),
+                Attribute::MarkerWidth =>
+                    self.width.set(parse("markerWidth", value, LengthDir::Horizontal,
+                                         Some(RsvgLength::check_nonnegative))?),
 
-                    Attribute::MarkerHeight =>
-                        self.height.set(parse("markerHeight", value, LengthDir::Vertical,
-                                              Some(RsvgLength::check_nonnegative))?),
+                Attribute::MarkerHeight =>
+                    self.height.set(parse("markerHeight", value, LengthDir::Vertical,
+                                          Some(RsvgLength::check_nonnegative))?),
 
-                    Attribute::Orient =>
-                        self.orient.set(parse("orient", value, (), None)?),
+                Attribute::Orient =>
+                    self.orient.set(parse("orient", value, (), None)?),
 
-                    Attribute::PreserveAspectRatio =>
-                        self.aspect.set(parse("preserveAspectRatio", value, (), None)?),
+                Attribute::PreserveAspectRatio =>
+                    self.aspect.set(parse("preserveAspectRatio", value, (), None)?),
 
-                    Attribute::ViewBox =>
-                        self.vbox.set(Some(parse("viewBox", value, (), None)?)),
+                Attribute::ViewBox =>
+                    self.vbox.set(Some(parse("viewBox", value, (), None)?)),
 
-                    _ => (),
-                }
+                _ => (),
             }
         }
 
diff --git a/rust/src/mask.rs b/rust/src/mask.rs
index 2fefcc55..81703371 100644
--- a/rust/src/mask.rs
+++ b/rust/src/mask.rs
@@ -1,6 +1,5 @@
 use libc;
 use std::cell::Cell;
-use std::str::FromStr;
 
 use attributes::Attribute;
 use coord_units::CoordUnits;
@@ -49,24 +48,22 @@ impl NodeMask {
 
 impl NodeTrait for NodeMask {
     fn set_atts(&self, _: &RsvgNode, _: *const RsvgHandle, pbag: &PropertyBag) -> NodeResult {
-        for (key, value) in pbag.iter() {
-            if let Ok(attr) = Attribute::from_str(key) {
-                match attr {
-                    Attribute::X =>      self.x.set(parse("x", value, LengthDir::Horizontal, None)?),
-                    Attribute::Y =>      self.y.set(parse("y", value, LengthDir::Vertical, None)?),
-                    Attribute::Width =>  self.width.set(parse("width", value, LengthDir::Horizontal,
-                                                              Some(RsvgLength::check_nonnegative))?),
-                    Attribute::Height => self.height.set(parse("height", value, LengthDir::Vertical,
-                                                               Some(RsvgLength::check_nonnegative))?),
-
-                    Attribute::MaskUnits =>
-                        self.units.set(parse("maskUnits", value, (), None)?),
-
-                    Attribute::MaskContentUnits =>
-                        self.content_units.set(parse("maskContentUnits", value, (), None)?),
-
-                    _ => (),
-                }
+        for (_key, attr, value) in pbag.iter() {
+            match attr {
+                Attribute::X =>      self.x.set(parse("x", value, LengthDir::Horizontal, None)?),
+                Attribute::Y =>      self.y.set(parse("y", value, LengthDir::Vertical, None)?),
+                Attribute::Width =>  self.width.set(parse("width", value, LengthDir::Horizontal,
+                                                          Some(RsvgLength::check_nonnegative))?),
+                Attribute::Height => self.height.set(parse("height", value, LengthDir::Vertical,
+                                                           Some(RsvgLength::check_nonnegative))?),
+
+                Attribute::MaskUnits =>
+                    self.units.set(parse("maskUnits", value, (), None)?),
+
+                Attribute::MaskContentUnits =>
+                    self.content_units.set(parse("maskContentUnits", value, (), None)?),
+
+                _ => (),
             }
         }
 
diff --git a/rust/src/pattern.rs b/rust/src/pattern.rs
index 03ece8a5..dbe800bc 100644
--- a/rust/src/pattern.rs
+++ b/rust/src/pattern.rs
@@ -3,7 +3,6 @@ use libc;
 
 use std::cell::RefCell;
 use std::rc::*;
-use std::str::FromStr;
 
 use cairo::MatrixTrait;
 use cairo::Pattern as CairoPattern;
@@ -175,43 +174,41 @@ impl NodeTrait for NodePattern {
 
         p.node = Some (Rc::downgrade (node));
 
-        for (key, value) in pbag.iter() {
-            if let Ok(attr) = Attribute::from_str(key) {
-                match attr {
-                    Attribute::PatternUnits =>
-                        p.units = Some(parse("patternUnits", value, (), None)?),
+        for (_key, attr, value) in pbag.iter() {
+            match attr {
+                Attribute::PatternUnits =>
+                    p.units = Some(parse("patternUnits", value, (), None)?),
 
-                    Attribute::PatternContentUnits =>
-                        p.content_units = Some(parse("patternContentUnits", value, (), None)?),
+                Attribute::PatternContentUnits =>
+                    p.content_units = Some(parse("patternContentUnits", value, (), None)?),
 
-                    Attribute::ViewBox =>
-                        p.vbox = Some(Some(parse("viewBox", value, (), None)?)),
+                Attribute::ViewBox =>
+                    p.vbox = Some(Some(parse("viewBox", value, (), None)?)),
 
-                    Attribute::PreserveAspectRatio =>
-                        p.preserve_aspect_ratio = Some(parse("preserveAspectRatio", value, (), None)?),
+                Attribute::PreserveAspectRatio =>
+                    p.preserve_aspect_ratio = Some(parse("preserveAspectRatio", value, (), None)?),
 
-                    Attribute::PatternTransform =>
-                        p.affine = Some(parse("patternTransform", value, (), None)?),
+                Attribute::PatternTransform =>
+                    p.affine = Some(parse("patternTransform", value, (), None)?),
 
-                    Attribute::XlinkHref =>
-                        p.fallback = Some(value.to_owned()),
+                Attribute::XlinkHref =>
+                    p.fallback = Some(value.to_owned()),
 
-                    Attribute::X =>
-                        p.x = Some(parse("x", value, LengthDir::Horizontal, None)?),
+                Attribute::X =>
+                    p.x = Some(parse("x", value, LengthDir::Horizontal, None)?),
 
-                    Attribute::Y =>
-                        p.y = Some(parse("y", value, LengthDir::Vertical, None)?),
+                Attribute::Y =>
+                    p.y = Some(parse("y", value, LengthDir::Vertical, None)?),
 
-                    Attribute::Width =>
-                        p.width = Some(parse("width", value, LengthDir::Horizontal,
-                                             Some(RsvgLength::check_nonnegative))?),
+                Attribute::Width =>
+                    p.width = Some(parse("width", value, LengthDir::Horizontal,
+                                         Some(RsvgLength::check_nonnegative))?),
 
-                    Attribute::Height =>
-                        p.height = Some(parse("height", value, LengthDir::Vertical,
-                                              Some(RsvgLength::check_nonnegative))?),
+                Attribute::Height =>
+                    p.height = Some(parse("height", value, LengthDir::Vertical,
+                                          Some(RsvgLength::check_nonnegative))?),
 
-                    _ => (),
-                }
+                _ => (),
             }
         }
 
diff --git a/rust/src/property_bag.rs b/rust/src/property_bag.rs
index d1cd9912..114009de 100644
--- a/rust/src/property_bag.rs
+++ b/rust/src/property_bag.rs
@@ -8,14 +8,17 @@ use std::collections::hash_map;
 use std::ffi::{CStr, CString};
 use std::ops::Deref;
 use std::ptr;
+use std::str::FromStr;
 
-pub struct PropertyBag<'a>(HashMap<&'a CStr, &'a CStr>);
+use attributes::Attribute;
 
-pub struct OwnedPropertyBag(HashMap<CString, CString>);
+pub struct PropertyBag<'a>(HashMap<&'a CStr, (Attribute, &'a CStr)>);
+
+pub struct OwnedPropertyBag(HashMap<CString, (Attribute, CString)>);
 
 pub struct PropertyBagIter<'a>(PropertyBagCStrIter<'a>);
 
-pub struct PropertyBagCStrIter<'a>(hash_map::Iter<'a, &'a CStr, &'a CStr>);
+pub struct PropertyBagCStrIter<'a>(hash_map::Iter<'a, &'a CStr, (Attribute, &'a CStr)>);
 
 impl<'a> PropertyBag<'a> {
     pub unsafe fn new_from_key_value_pairs(pairs: *const *const libc::c_char) -> PropertyBag<'a> {
@@ -32,7 +35,11 @@ impl<'a> PropertyBag<'a> {
                     let key_str = CStr::from_ptr(key);
                     let val_str = CStr::from_ptr(val);
 
-                    map.insert(key_str, val_str);
+                    // We silently drop unknown attributes.  New attributes should be added in
+                    // build.rs.
+                    if let Ok(attr) = Attribute::from_str(key_str.to_str().unwrap()) {
+                        map.insert(key_str, (attr, val_str));
+                    }
                 } else {
                     break;
                 }
@@ -47,18 +54,18 @@ impl<'a> PropertyBag<'a> {
     pub fn from_owned(owned: &OwnedPropertyBag) -> PropertyBag {
         let mut map = HashMap::new();
 
-        for (k, v) in &owned.0 {
-            map.insert(k.deref(), v.deref());
+        for (k, &(a, ref v)) in &owned.0 {
+            map.insert(k.deref(), (a, v.deref()));
         }
 
         PropertyBag(map)
     }
 
     pub fn to_owned(&self) -> OwnedPropertyBag {
-        let mut map = HashMap::<CString, CString>::new();
+        let mut map = HashMap::<CString, (Attribute, CString)>::new();
 
-        for (k, v) in &self.0 {
-            map.insert((*k).to_owned(), (*v).to_owned());
+        for (k, &(a, v)) in &self.0 {
+            map.insert((*k).to_owned(), (a, (*v).to_owned()));
         }
 
         OwnedPropertyBag(map)
@@ -72,13 +79,13 @@ impl<'a> PropertyBag<'a> {
         self.0.len()
     }
 
-    pub fn lookup_cstr(&self, key: &CStr) -> Option<&CStr> {
-        self.0.get(key).map(|v| *v)
+    pub fn lookup_cstr(&self, key: &CStr) -> Option<(Attribute, &CStr)> {
+        self.0.get(key).map(|&(a, v)| (a, v))
     }
 
-    pub fn lookup(&self, key: &str) -> Option<&str> {
+    pub fn lookup(&self, key: &str) -> Option<(Attribute, &str)> {
         let k = CString::new(key).unwrap();
-        self.lookup_cstr(&k).map(|v| v.to_str().unwrap())
+        self.lookup_cstr(&k).map(|(a, v)| (a, v.to_str().unwrap()))
     }
 
     pub fn iter(&self) -> PropertyBagIter {
@@ -91,18 +98,18 @@ impl<'a> PropertyBag<'a> {
 }
 
 impl<'a> Iterator for PropertyBagIter<'a> {
-    type Item = (&'a str, &'a str);
+    type Item = (&'a str, Attribute, &'a str);
 
     fn next(&mut self) -> Option<Self::Item> {
-        self.0.next().map(|(k, v)| (k.to_str().unwrap(), v.to_str().unwrap()))
+        self.0.next().map(|(k, a, v)| (k.to_str().unwrap(), a, v.to_str().unwrap()))
     }
 }
 
 impl<'a> Iterator for PropertyBagCStrIter<'a> {
-    type Item = (&'a CStr, &'a CStr);
+    type Item = (&'a CStr, Attribute, &'a CStr);
 
     fn next(&mut self) -> Option<Self::Item> {
-        self.0.next().map(|(k, v)| (*k, *v))
+        self.0.next().map(|(k, &(a, v))| (*k, a, v))
     }
 }
 
@@ -126,7 +133,7 @@ pub extern fn rsvg_property_bag_lookup(pbag: *const PropertyBag,
         let pbag = &*pbag;
         let key = CStr::from_ptr(raw_key);
         match pbag.lookup_cstr(key) {
-            Some(v) => v.as_ptr(),
+            Some((_, v)) => v.as_ptr(),
             None => ptr::null()
         }
     }
@@ -149,7 +156,7 @@ pub extern fn rsvg_property_bag_iter_next(iter: *mut PropertyBagCStrIter,
     assert!(!iter.is_null());
     let iter = unsafe { &mut *iter };
 
-    if let Some((key, val)) = iter.next() {
+    if let Some((key, _, val)) = iter.next() {
         unsafe {
             *out_key = key.as_ptr();
             *out_value = val.as_ptr();
@@ -186,9 +193,9 @@ mod tests {
     #[test]
     fn property_bag_lookups_and_iters() {
         let pairs = [
-            CString::new("alpha").unwrap(),
+            CString::new("rx").unwrap(),
             CString::new("1").unwrap(),
-            CString::new("beta").unwrap(),
+            CString::new("ry").unwrap(),
             CString::new("2").unwrap(),
         ];
 
@@ -202,33 +209,37 @@ mod tests {
 
         let pbag = unsafe { PropertyBag::new_from_key_value_pairs(v.as_ptr()) };
 
-        assert_eq!(pbag.lookup("alpha"), Some("1"));
-        assert_eq!(pbag.lookup("beta"), Some("2"));
-        assert_eq!(pbag.lookup("gamma"), None);
+        assert_eq!(pbag.lookup("rx"), Some((Attribute::Rx, "1")));
+        assert_eq!(pbag.lookup("ry"), Some((Attribute::Ry, "2")));
+        assert_eq!(pbag.lookup("stdDeviation"), None);
 
-        let mut had_alpha: bool = false;
-        let mut had_beta: bool = false;
+        let mut had_rx: bool = false;
+        let mut had_ry: bool = false;
 
-        for (k, v) in pbag.iter() {
-            if k == "alpha" {
+        for (k, a, v) in pbag.iter() {
+            if k == "rx" {
+                assert!(a == Attribute::Rx);
                 assert!(v == "1");
-                had_alpha = true;
-            } else if k == "beta" {
+                had_rx = true;
+            } else if k == "ry" {
+                assert!(a == Attribute::Ry);
                 assert!(v == "2");
-                had_beta = true;
+                had_ry = true;
+            } else {
+                unreachable!();
             }
         }
 
-        assert!(had_alpha);
-        assert!(had_beta);
+        assert!(had_rx);
+        assert!(had_ry);
     }
 
     #[test]
     fn property_bag_can_iterate_from_c() {
         let pairs = [
-            CString::new("alpha").unwrap(),
+            CString::new("rx").unwrap(),
             CString::new("1").unwrap(),
-            CString::new("beta").unwrap(),
+            CString::new("ry").unwrap(),
             CString::new("2").unwrap(),
         ];
 
@@ -242,8 +253,8 @@ mod tests {
 
         let pbag = unsafe { PropertyBag::new_from_key_value_pairs(v.as_ptr()) };
 
-        let mut had_alpha: bool = false;
-        let mut had_beta: bool = false;
+        let mut had_rx: bool = false;
+        let mut had_ry: bool = false;
 
         let iter = rsvg_property_bag_iter_begin(&pbag as *const PropertyBag);
 
@@ -256,18 +267,18 @@ mod tests {
             let k = unsafe { CStr::from_ptr(key).to_str().unwrap() };
             let v = unsafe { CStr::from_ptr(val).to_str().unwrap() };
 
-            if k == "alpha" {
+            if k == "rx" {
                 assert!(v == "1");
-                had_alpha = true;
-            } else if k == "beta" {
+                had_rx = true;
+            } else if k == "ry" {
                 assert!(v == "2");
-                had_beta = true;
+                had_ry = true;
             }
         }
 
         rsvg_property_bag_iter_end(iter);
 
-        assert!(had_alpha);
-        assert!(had_beta);
+        assert!(had_rx);
+        assert!(had_ry);
     }
 }
diff --git a/rust/src/shapes.rs b/rust/src/shapes.rs
index 4a001b54..c0b850b1 100644
--- a/rust/src/shapes.rs
+++ b/rust/src/shapes.rs
@@ -2,7 +2,6 @@ use libc;
 
 use std::cell::RefCell;
 use std::cell::Cell;
-use std::str::FromStr;
 
 use attributes::Attribute;
 use drawing_ctx;
@@ -90,18 +89,16 @@ impl NodePath {
 
 impl NodeTrait for NodePath {
     fn set_atts (&self, _: &RsvgNode, _: *const RsvgHandle, pbag: &PropertyBag) -> NodeResult {
-        for (key, value) in pbag.iter() {
-            if let Ok(attr) = Attribute::from_str(key) {
-                if attr == Attribute::D {
-                    let mut builder = RsvgPathBuilder::new ();
+        for (_key, attr, value) in pbag.iter() {
+            if attr == Attribute::D {
+                let mut builder = RsvgPathBuilder::new ();
 
-                    if path_parser::parse_path_into_builder (&value, &mut builder).is_err() {
-                        // FIXME: we don't propagate errors upstream, but creating a partial
-                        // path is OK per the spec
-                    }
-
-                    *self.builder.borrow_mut() = Some(builder);
+                if path_parser::parse_path_into_builder (&value, &mut builder).is_err() {
+                    // FIXME: we don't propagate errors upstream, but creating a partial
+                    // path is OK per the spec
                 }
+
+                *self.builder.borrow_mut() = Some(builder);
             }
         }
 
@@ -143,21 +140,19 @@ impl NodePoly {
 
 impl NodeTrait for NodePoly {
     fn set_atts (&self, _: &RsvgNode, _: *const RsvgHandle, pbag: &PropertyBag) -> NodeResult {
-        for (key, value) in pbag.iter() {
-            if let Ok(attr) = Attribute::from_str(key) {
-                // support for svg < 1.0 which used verts
+        for (key, attr, value) in pbag.iter() {
+            // support for svg < 1.0 which used verts
 
-                if attr == Attribute::Points || attr == Attribute::Verts {
-                    let result = parsers::list_of_points (value.trim ());
+            if attr == Attribute::Points || attr == Attribute::Verts {
+                let result = parsers::list_of_points (value.trim ());
 
-                    match result {
-                        Ok (v) => {
-                            *self.points.borrow_mut () = Some (v);
-                            break;
-                        },
+                match result {
+                    Ok (v) => {
+                        *self.points.borrow_mut () = Some (v);
+                        break;
+                    },
 
-                        Err (e) => { return Err (NodeError::parse_error (key, e)); }
-                    }
+                    Err (e) => { return Err (NodeError::parse_error (key, e)); }
                 }
             }
         }
@@ -212,15 +207,13 @@ impl NodeLine {
 
 impl NodeTrait for NodeLine {
     fn set_atts (&self, _: &RsvgNode, _: *const RsvgHandle, pbag: &PropertyBag) -> NodeResult {
-        for (key, value) in pbag.iter() {
-            if let Ok(attr) = Attribute::from_str(key) {
-                match attr {
-                    Attribute::X1 => self.x1.set(parse("x1", value, LengthDir::Horizontal, None)?),
-                    Attribute::Y1 => self.y1.set(parse("y1", value, LengthDir::Vertical, None)?),
-                    Attribute::X2 => self.x2.set(parse("x2", value, LengthDir::Horizontal, None)?),
-                    Attribute::Y2 => self.y2.set(parse("y2", value, LengthDir::Vertical, None)?),
-                    _ => ()
-                }
+        for (_key, attr, value) in pbag.iter() {
+            match attr {
+                Attribute::X1 => self.x1.set(parse("x1", value, LengthDir::Horizontal, None)?),
+                Attribute::Y1 => self.y1.set(parse("y1", value, LengthDir::Vertical, None)?),
+                Attribute::X2 => self.x2.set(parse("x2", value, LengthDir::Horizontal, None)?),
+                Attribute::Y2 => self.y2.set(parse("y2", value, LengthDir::Vertical, None)?),
+                _ => ()
             }
         }
 
@@ -276,25 +269,23 @@ impl NodeRect {
 
 impl NodeTrait for NodeRect {
     fn set_atts (&self, _: &RsvgNode, _: *const RsvgHandle, pbag: &PropertyBag) -> NodeResult {
-        for (key, value) in pbag.iter() {
-            if let Ok(attr) = Attribute::from_str(key) {
-                match attr {
-                    Attribute::X      => self.x.set (parse ("x", value, LengthDir::Horizontal, None)?),
-                    Attribute::Y      => self.y.set (parse ("y", value, LengthDir::Vertical, None)?),
-                    Attribute::Width  => self.w.set (parse ("width", value, LengthDir::Horizontal,
-                                                            Some(RsvgLength::check_nonnegative))?),
-                    Attribute::Height => self.h.set (parse ("height", value, LengthDir::Vertical,
-                                                            Some(RsvgLength::check_nonnegative))?),
-
-                    Attribute::Rx => self.rx.set (parse ("rx", value, LengthDir::Horizontal,
-                                                         Some(RsvgLength::check_nonnegative))
-                                                  .map(Some)?),
-                    Attribute::Ry => self.ry.set (parse ("ry", value, LengthDir::Vertical,
-                                                         Some(RsvgLength::check_nonnegative))
-                                                  .map(Some)?),
-
-                    _ => (),
-                }
+        for (_key, attr, value) in pbag.iter() {
+            match attr {
+                Attribute::X      => self.x.set (parse ("x", value, LengthDir::Horizontal, None)?),
+                Attribute::Y      => self.y.set (parse ("y", value, LengthDir::Vertical, None)?),
+                Attribute::Width  => self.w.set (parse ("width", value, LengthDir::Horizontal,
+                                                        Some(RsvgLength::check_nonnegative))?),
+                Attribute::Height => self.h.set (parse ("height", value, LengthDir::Vertical,
+                                                        Some(RsvgLength::check_nonnegative))?),
+
+                Attribute::Rx => self.rx.set (parse ("rx", value, LengthDir::Horizontal,
+                                                     Some(RsvgLength::check_nonnegative))
+                                              .map(Some)?),
+                Attribute::Ry => self.ry.set (parse ("ry", value, LengthDir::Vertical,
+                                                     Some(RsvgLength::check_nonnegative))
+                                              .map(Some)?),
+
+                _ => (),
             }
         }
 
@@ -465,16 +456,14 @@ impl NodeCircle {
 
 impl NodeTrait for NodeCircle {
     fn set_atts (&self, _: &RsvgNode, _: *const RsvgHandle, pbag: &PropertyBag) -> NodeResult {
-        for (key, value) in pbag.iter() {
-            if let Ok(attr) = Attribute::from_str(key) {
-                match attr {
-                    Attribute::Cx => self.cx.set(parse("cx", value, LengthDir::Horizontal, None)?),
-                    Attribute::Cy => self.cy.set(parse("cy", value, LengthDir::Vertical, None)?),
-                    Attribute::R  => self.r.set (parse("r",  value, LengthDir::Both,
-                                                       Some(RsvgLength::check_nonnegative))?),
-
-                    _ => (),
-                }
+        for (_key, attr, value) in pbag.iter() {
+            match attr {
+                Attribute::Cx => self.cx.set(parse("cx", value, LengthDir::Horizontal, None)?),
+                Attribute::Cy => self.cy.set(parse("cy", value, LengthDir::Vertical, None)?),
+                Attribute::R  => self.r.set (parse("r",  value, LengthDir::Both,
+                                                   Some(RsvgLength::check_nonnegative))?),
+
+                _ => (),
             }
         }
 
@@ -516,19 +505,17 @@ impl NodeEllipse {
 
 impl NodeTrait for NodeEllipse {
     fn set_atts (&self, _: &RsvgNode, _: *const RsvgHandle, pbag: &PropertyBag) -> NodeResult {
-        for (key, value) in pbag.iter() {
-            if let Ok(attr) = Attribute::from_str(key) {
-                match attr {
-                    Attribute::Cx => self.cx.set(parse("cx", value, LengthDir::Horizontal, None)?),
-                    Attribute::Cy => self.cy.set(parse("cy", value, LengthDir::Vertical, None)?),
-
-                    Attribute::Rx => self.rx.set(parse("rx", value, LengthDir::Horizontal,
-                                                       Some(RsvgLength::check_nonnegative))?),
-                    Attribute::Ry => self.ry.set(parse("ry", value, LengthDir::Vertical,
-                                                       Some(RsvgLength::check_nonnegative))?),
-
-                    _ => (),
-                }
+        for (_key, attr, value) in pbag.iter() {
+            match attr {
+                Attribute::Cx => self.cx.set(parse("cx", value, LengthDir::Horizontal, None)?),
+                Attribute::Cy => self.cy.set(parse("cy", value, LengthDir::Vertical, None)?),
+
+                Attribute::Rx => self.rx.set(parse("rx", value, LengthDir::Horizontal,
+                                                   Some(RsvgLength::check_nonnegative))?),
+                Attribute::Ry => self.ry.set(parse("ry", value, LengthDir::Vertical,
+                                                   Some(RsvgLength::check_nonnegative))?),
+
+                _ => (),
             }
         }
 
diff --git a/rust/src/stop.rs b/rust/src/stop.rs
index ed58d4d1..ecbc6023 100644
--- a/rust/src/stop.rs
+++ b/rust/src/stop.rs
@@ -3,7 +3,6 @@ use cssparser;
 use glib::translate::*;
 
 use std::cell::Cell;
-use std::str::FromStr;
 
 use attributes::Attribute;
 use color::*;
@@ -65,31 +64,29 @@ impl NodeTrait for NodeStop {
     fn set_atts (&self, node: &RsvgNode, _: *const RsvgHandle, pbag: &PropertyBag) -> NodeResult {
         let state = node.get_state ();
 
-        for (key, value) in pbag.iter() {
-            if let Ok(attr) = Attribute::from_str(key) {
-                match attr {
-                    Attribute::Offset => {
-                        let length = parse("offset", value, LengthDir::Both, Some(validate_offset))?;
-                        assert! (length.unit == LengthUnit::Default || length.unit == LengthUnit::Percent);
-                        self.offset.set (length.length);
-                    },
-
-                    Attribute::Style => {
-                        // FIXME: this is the only place where rsvg_parse_style() and
-                        // rsvg_parse_presentation_attributes() are called outside of the
-                        // rsvg-base.c machinery.  That one indirectly calls them via
-                        // rsvg_parse_style_attrs().
-                        //
-                        // Should we resolve the stop-color / stop-opacity at
-                        // rendering time?
-
-                        unsafe {
-                            rsvg_parse_style (state, value.to_glib_none ().0);
-                        }
-                    },
-
-                    _ => (),
-                }
+        for (_key, attr, value) in pbag.iter() {
+            match attr {
+                Attribute::Offset => {
+                    let length = parse("offset", value, LengthDir::Both, Some(validate_offset))?;
+                    assert! (length.unit == LengthUnit::Default || length.unit == LengthUnit::Percent);
+                    self.offset.set (length.length);
+                },
+
+                Attribute::Style => {
+                    // FIXME: this is the only place where rsvg_parse_style() and
+                    // rsvg_parse_presentation_attributes() are called outside of the
+                    // rsvg-base.c machinery.  That one indirectly calls them via
+                    // rsvg_parse_style_attrs().
+                    //
+                    // Should we resolve the stop-color / stop-opacity at
+                    // rendering time?
+
+                    unsafe {
+                        rsvg_parse_style (state, value.to_glib_none ().0);
+                    }
+                },
+
+                _ => (),
             }
         }
 
diff --git a/rust/src/structure.rs b/rust/src/structure.rs
index ca9c7b27..f4388930 100644
--- a/rust/src/structure.rs
+++ b/rust/src/structure.rs
@@ -3,7 +3,6 @@ use libc;
 
 use std::cell::RefCell;
 use std::cell::Cell;
-use std::str::FromStr;
 
 use cairo::MatrixTrait;
 
@@ -142,31 +141,29 @@ impl NodeTrait for NodeSvg {
         // http://www.w3.org/TR/SVG/struct.html#SVGElement
         let is_inner_svg = node.get_parent().is_some();
 
-        for (key, value) in pbag.iter() {
-            if let Ok(attr) = Attribute::from_str(key) {
-                match attr {
-                    Attribute::PreserveAspectRatio =>
-                        self.preserve_aspect_ratio.set(parse("preserveAspectRatio", value, (), None)?),
+        for (_key, attr, value) in pbag.iter() {
+            match attr {
+                Attribute::PreserveAspectRatio =>
+                    self.preserve_aspect_ratio.set(parse("preserveAspectRatio", value, (), None)?),
 
-                    Attribute::X => if is_inner_svg {
-                        self.x.set(parse("x", value, LengthDir::Horizontal, None)?);
-                    },
+                Attribute::X => if is_inner_svg {
+                    self.x.set(parse("x", value, LengthDir::Horizontal, None)?);
+                },
 
-                    Attribute::Y => if is_inner_svg {
-                        self.y.set(parse("y", value, LengthDir::Vertical, None)?);
-                    },
+                Attribute::Y => if is_inner_svg {
+                    self.y.set(parse("y", value, LengthDir::Vertical, None)?);
+                },
 
-                    Attribute::Width => self.w.set(parse("width", value, LengthDir::Horizontal,
-                                                         Some(RsvgLength::check_nonnegative))?),
+                Attribute::Width => self.w.set(parse("width", value, LengthDir::Horizontal,
+                                                     Some(RsvgLength::check_nonnegative))?),
 
-                    Attribute::Height => self.h.set(parse("height", value, LengthDir::Vertical,
-                                                          Some(RsvgLength::check_nonnegative))?),
+                Attribute::Height => self.h.set(parse("height", value, LengthDir::Vertical,
+                                                      Some(RsvgLength::check_nonnegative))?),
 
-                    Attribute::ViewBox => self.vbox.set(parse("viewBox", value, (), None)
-                                                        .map(Some)?),
+                Attribute::ViewBox => self.vbox.set(parse("viewBox", value, (), None)
+                                                    .map(Some)?),
 
-                    _ => (),
-                }
+                _ => (),
             }
         }
 
@@ -231,23 +228,21 @@ impl NodeUse {
 
 impl NodeTrait for NodeUse {
     fn set_atts (&self, _: &RsvgNode, _: *const RsvgHandle, pbag: &PropertyBag) -> NodeResult {
-        for (key, value) in pbag.iter() {
-            if let Ok(attr) = Attribute::from_str(key) {
-                match attr {
-                    Attribute::XlinkHref => *self.link.borrow_mut() = Some(value.to_owned()),
-
-                    Attribute::X         => self.x.set(parse("x", value, LengthDir::Horizontal, None)?),
-                    Attribute::Y         => self.y.set(parse("y", value, LengthDir::Vertical, None)?),
-
-                    Attribute::Width     => self.w.set(parse("width", value, LengthDir::Horizontal,
-                                                             Some(RsvgLength::check_nonnegative))
-                                                       .map(Some)?),
-                    Attribute::Height    => self.h.set(parse("height", value, LengthDir::Vertical,
-                                                             Some(RsvgLength::check_nonnegative))
-                                                       .map(Some)?),
-
-                    _ => (),
-                }
+        for (_key, attr, value) in pbag.iter() {
+            match attr {
+                Attribute::XlinkHref => *self.link.borrow_mut() = Some(value.to_owned()),
+
+                Attribute::X         => self.x.set(parse("x", value, LengthDir::Horizontal, None)?),
+                Attribute::Y         => self.y.set(parse("y", value, LengthDir::Vertical, None)?),
+
+                Attribute::Width     => self.w.set(parse("width", value, LengthDir::Horizontal,
+                                                         Some(RsvgLength::check_nonnegative))
+                                                   .map(Some)?),
+                Attribute::Height    => self.h.set(parse("height", value, LengthDir::Vertical,
+                                                         Some(RsvgLength::check_nonnegative))
+                                                   .map(Some)?),
+
+                _ => (),
             }
         }
 
@@ -357,17 +352,15 @@ impl NodeSymbol {
 
 impl NodeTrait for NodeSymbol {
     fn set_atts (&self, _: &RsvgNode, _: *const RsvgHandle, pbag: &PropertyBag) -> NodeResult {
-        for (key, value) in pbag.iter() {
-            if let Ok(attr) = Attribute::from_str(key) {
-                match attr {
-                    Attribute::PreserveAspectRatio =>
-                        self.preserve_aspect_ratio.set(parse("preserveAspectRatio", value, (), None)?),
+        for (_key, attr, value) in pbag.iter() {
+            match attr {
+                Attribute::PreserveAspectRatio =>
+                    self.preserve_aspect_ratio.set(parse("preserveAspectRatio", value, (), None)?),
 
-                    Attribute::ViewBox => self.vbox.set(parse("viewBox", value, (), None)
-                                                        .map(Some)?),
+                Attribute::ViewBox => self.vbox.set(parse("viewBox", value, (), None)
+                                                    .map(Some)?),
 
-                    _ => (),
-                }
+                _ => (),
             }
         }
 
@@ -475,8 +468,8 @@ pub extern fn rsvg_node_svg_apply_atts (raw_node: *const RsvgNode, handle: *cons
         if let Some(owned_pbag) = svg.pbag.borrow().as_ref() {
             let pbag = PropertyBag::from_owned(&owned_pbag);
 
-            let class = pbag.lookup("class");
-            let id = pbag.lookup("id");
+            let class = pbag.lookup("class").map(|(_, v)| v);
+            let id = pbag.lookup("id").map(|(_, v)| v);
 
             let c_class = class.to_glib_none ();
             let c_id = id.to_glib_none ();



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