[librsvg] Remove Parse's Data associated type. Yay!



commit 0532d20d92971e7346fade2c48483b06dd49762c
Author: Federico Mena Quintero <federico gnome org>
Date:   Mon Jan 21 19:45:58 2019 -0600

    Remove Parse's Data associated type.  Yay!
    
    This removes the mysterious "()" argument from practically all the
    .parse() and .parse_str() calls.
    
    I thought the Data associated type was a really clever idea to deal
    with Length's need for a direction.  But now it turns out that it's
    possible to encode that in the length types.  In any case, it made the
    parse() calls that didn't need extra data quite ugly.

 rsvg_internals/src/angle.rs                      |  22 ++-
 rsvg_internals/src/aspect_ratio.rs               |  67 +++++----
 rsvg_internals/src/clip_path.rs                  |   2 +-
 rsvg_internals/src/color.rs                      |  14 +-
 rsvg_internals/src/coord_units.rs                |  15 +--
 rsvg_internals/src/filters/color_matrix.rs       |   2 +-
 rsvg_internals/src/filters/component_transfer.rs |   2 +-
 rsvg_internals/src/filters/composite.rs          |   5 +-
 rsvg_internals/src/filters/convolve_matrix.rs    |   2 +-
 rsvg_internals/src/filters/image.rs              |   2 +-
 rsvg_internals/src/filters/mod.rs                |  32 ++---
 rsvg_internals/src/filters/node.rs               |  42 +++---
 rsvg_internals/src/font_props.rs                 |  68 ++++------
 rsvg_internals/src/gradient.rs                   |  52 ++++---
 rsvg_internals/src/image.rs                      |  24 ++--
 rsvg_internals/src/iri.rs                        |  19 ++-
 rsvg_internals/src/length.rs                     |  43 +++---
 rsvg_internals/src/marker.rs                     |  66 +++++----
 rsvg_internals/src/mask.rs                       |  32 ++---
 rsvg_internals/src/node.rs                       |   2 +-
 rsvg_internals/src/number_list.rs                |   2 +-
 rsvg_internals/src/paint_server.rs               |  27 ++--
 rsvg_internals/src/parsers.rs                    |  32 ++---
 rsvg_internals/src/pattern.rs                    |  28 ++--
 rsvg_internals/src/properties.rs                 | 165 +++++++++--------------
 rsvg_internals/src/property_macros.rs            |  23 ++--
 rsvg_internals/src/shapes.rs                     |  84 +++++-------
 rsvg_internals/src/stop.rs                       |   2 +-
 rsvg_internals/src/structure.rs                  |  48 +++----
 rsvg_internals/src/text.rs                       |  16 +--
 rsvg_internals/src/transform.rs                  |   5 +-
 rsvg_internals/src/unit_interval.rs              |  21 ++-
 rsvg_internals/src/viewbox.rs                    |  19 ++-
 33 files changed, 418 insertions(+), 567 deletions(-)
---
diff --git a/rsvg_internals/src/angle.rs b/rsvg_internals/src/angle.rs
index b020181a..8998595d 100644
--- a/rsvg_internals/src/angle.rs
+++ b/rsvg_internals/src/angle.rs
@@ -58,10 +58,9 @@ impl Angle {
 // angle ::= number ("deg" | "grad" | "rad")?
 //
 impl Parse for Angle {
-    type Data = ();
     type Err = ValueErrorKind;
 
-    fn parse(parser: &mut Parser<'_, '_>, _: ()) -> Result<Angle, ValueErrorKind> {
+    fn parse(parser: &mut Parser<'_, '_>) -> Result<Angle, ValueErrorKind> {
         let angle = {
             let token = parser
                 .next()
@@ -107,21 +106,18 @@ mod tests {
 
     #[test]
     fn parses_angle() {
-        assert_eq!(Angle::parse_str("0", ()), Ok(Angle::new(0.0)));
-        assert_eq!(Angle::parse_str("15", ()), Ok(Angle::from_degrees(15.0)));
+        assert_eq!(Angle::parse_str("0"), Ok(Angle::new(0.0)));
+        assert_eq!(Angle::parse_str("15"), Ok(Angle::from_degrees(15.0)));
+        assert_eq!(Angle::parse_str("180.5deg"), Ok(Angle::from_degrees(180.5)));
+        assert_eq!(Angle::parse_str("1rad"), Ok(Angle::new(1.0)));
         assert_eq!(
-            Angle::parse_str("180.5deg", ()),
-            Ok(Angle::from_degrees(180.5))
-        );
-        assert_eq!(Angle::parse_str("1rad", ()), Ok(Angle::new(1.0)));
-        assert_eq!(
-            Angle::parse_str("-400grad", ()),
+            Angle::parse_str("-400grad"),
             Ok(Angle::from_degrees(-360.0))
         );
 
-        assert!(Angle::parse_str("", ()).is_err());
-        assert!(Angle::parse_str("foo", ()).is_err());
-        assert!(Angle::parse_str("300foo", ()).is_err());
+        assert!(Angle::parse_str("").is_err());
+        assert!(Angle::parse_str("foo").is_err());
+        assert!(Angle::parse_str("300foo").is_err());
     }
 
     fn test_bisection_angle(
diff --git a/rsvg_internals/src/aspect_ratio.rs b/rsvg_internals/src/aspect_ratio.rs
index a3def588..0c563684 100644
--- a/rsvg_internals/src/aspect_ratio.rs
+++ b/rsvg_internals/src/aspect_ratio.rs
@@ -183,10 +183,9 @@ fn parse_fit_mode(s: &str) -> Result<FitMode, ValueErrorKind> {
 }
 
 impl Parse for AspectRatio {
-    type Data = ();
     type Err = ValueErrorKind;
 
-    fn parse(parser: &mut Parser<'_, '_>, _: ()) -> Result<AspectRatio, ValueErrorKind> {
+    fn parse(parser: &mut Parser<'_, '_>) -> Result<AspectRatio, ValueErrorKind> {
         let defer = parser.try(|p| p.expect_ident_matching("defer")).is_ok();
 
         let align_xy = parser.try(|p| {
@@ -220,20 +219,20 @@ mod tests {
 
     #[test]
     fn parsing_invalid_strings_yields_error() {
-        assert!(AspectRatio::parse_str("", ()).is_err());
-        assert!(AspectRatio::parse_str("defer", ()).is_err());
-        assert!(AspectRatio::parse_str("defer foo", ()).is_err());
-        assert!(AspectRatio::parse_str("defer xmidymid", ()).is_err());
-        assert!(AspectRatio::parse_str("defer xMidYMid foo", ()).is_err());
-        assert!(AspectRatio::parse_str("xmidymid", ()).is_err());
-        assert!(AspectRatio::parse_str("xMidYMid foo", ()).is_err());
-        assert!(AspectRatio::parse_str("defer xMidYMid meet foo", ()).is_err());
+        assert!(AspectRatio::parse_str("").is_err());
+        assert!(AspectRatio::parse_str("defer").is_err());
+        assert!(AspectRatio::parse_str("defer foo").is_err());
+        assert!(AspectRatio::parse_str("defer xmidymid").is_err());
+        assert!(AspectRatio::parse_str("defer xMidYMid foo").is_err());
+        assert!(AspectRatio::parse_str("xmidymid").is_err());
+        assert!(AspectRatio::parse_str("xMidYMid foo").is_err());
+        assert!(AspectRatio::parse_str("defer xMidYMid meet foo").is_err());
     }
 
     #[test]
     fn parses_valid_strings() {
         assert_eq!(
-            AspectRatio::parse_str("defer none", ()),
+            AspectRatio::parse_str("defer none"),
             Ok(AspectRatio {
                 defer: true,
                 align: None,
@@ -241,7 +240,7 @@ mod tests {
         );
 
         assert_eq!(
-            AspectRatio::parse_str("xMidYMid", ()),
+            AspectRatio::parse_str("xMidYMid"),
             Ok(AspectRatio {
                 defer: false,
                 align: Some(Align {
@@ -253,7 +252,7 @@ mod tests {
         );
 
         assert_eq!(
-            AspectRatio::parse_str("defer xMidYMid", ()),
+            AspectRatio::parse_str("defer xMidYMid"),
             Ok(AspectRatio {
                 defer: true,
                 align: Some(Align {
@@ -265,7 +264,7 @@ mod tests {
         );
 
         assert_eq!(
-            AspectRatio::parse_str("defer xMinYMax", ()),
+            AspectRatio::parse_str("defer xMinYMax"),
             Ok(AspectRatio {
                 defer: true,
                 align: Some(Align {
@@ -277,7 +276,7 @@ mod tests {
         );
 
         assert_eq!(
-            AspectRatio::parse_str("defer xMaxYMid meet", ()),
+            AspectRatio::parse_str("defer xMaxYMid meet"),
             Ok(AspectRatio {
                 defer: true,
                 align: Some(Align {
@@ -289,7 +288,7 @@ mod tests {
         );
 
         assert_eq!(
-            AspectRatio::parse_str("defer xMinYMax slice", ()),
+            AspectRatio::parse_str("defer xMinYMax slice"),
             Ok(AspectRatio {
                 defer: true,
                 align: Some(Align {
@@ -310,75 +309,75 @@ mod tests {
 
     #[test]
     fn aligns() {
-        let foo = AspectRatio::parse_str("xMinYMin meet", ()).unwrap();
+        let foo = AspectRatio::parse_str("xMinYMin meet").unwrap();
         let foo = foo.compute(1.0, 10.0, 0.0, 0.0, 10.0, 1.0);
         assert_quadruples_equal(&foo, &(0.0, 0.0, 0.1, 1.0));
 
-        let foo = AspectRatio::parse_str("xMinYMin slice", ()).unwrap();
+        let foo = AspectRatio::parse_str("xMinYMin slice").unwrap();
         let foo = foo.compute(1.0, 10.0, 0.0, 0.0, 10.0, 1.0);
         assert_quadruples_equal(&foo, &(0.0, 0.0, 10.0, 100.0));
 
-        let foo = AspectRatio::parse_str("xMinYMid meet", ()).unwrap();
+        let foo = AspectRatio::parse_str("xMinYMid meet").unwrap();
         let foo = foo.compute(1.0, 10.0, 0.0, 0.0, 10.0, 1.0);
         assert_quadruples_equal(&foo, &(0.0, 0.0, 0.1, 1.0));
 
-        let foo = AspectRatio::parse_str("xMinYMid slice", ()).unwrap();
+        let foo = AspectRatio::parse_str("xMinYMid slice").unwrap();
         let foo = foo.compute(1.0, 10.0, 0.0, 0.0, 10.0, 1.0);
         assert_quadruples_equal(&foo, &(0.0, -49.5, 10.0, 100.0));
 
-        let foo = AspectRatio::parse_str("xMinYMax meet", ()).unwrap();
+        let foo = AspectRatio::parse_str("xMinYMax meet").unwrap();
         let foo = foo.compute(1.0, 10.0, 0.0, 0.0, 10.0, 1.0);
         assert_quadruples_equal(&foo, &(0.0, 0.0, 0.1, 1.0));
 
-        let foo = AspectRatio::parse_str("xMinYMax slice", ()).unwrap();
+        let foo = AspectRatio::parse_str("xMinYMax slice").unwrap();
         let foo = foo.compute(1.0, 10.0, 0.0, 0.0, 10.0, 1.0);
         assert_quadruples_equal(&foo, &(0.0, -99.0, 10.0, 100.0));
 
-        let foo = AspectRatio::parse_str("xMidYMin meet", ()).unwrap();
+        let foo = AspectRatio::parse_str("xMidYMin meet").unwrap();
         let foo = foo.compute(1.0, 10.0, 0.0, 0.0, 10.0, 1.0);
         assert_quadruples_equal(&foo, &(4.95, 0.0, 0.1, 1.0));
 
-        let foo = AspectRatio::parse_str("xMidYMin slice", ()).unwrap();
+        let foo = AspectRatio::parse_str("xMidYMin slice").unwrap();
         let foo = foo.compute(1.0, 10.0, 0.0, 0.0, 10.0, 1.0);
         assert_quadruples_equal(&foo, &(0.0, 0.0, 10.0, 100.0));
 
-        let foo = AspectRatio::parse_str("xMidYMid meet", ()).unwrap();
+        let foo = AspectRatio::parse_str("xMidYMid meet").unwrap();
         let foo = foo.compute(1.0, 10.0, 0.0, 0.0, 10.0, 1.0);
         assert_quadruples_equal(&foo, &(4.95, 0.0, 0.1, 1.0));
 
-        let foo = AspectRatio::parse_str("xMidYMid slice", ()).unwrap();
+        let foo = AspectRatio::parse_str("xMidYMid slice").unwrap();
         let foo = foo.compute(1.0, 10.0, 0.0, 0.0, 10.0, 1.0);
         assert_quadruples_equal(&foo, &(0.0, -49.5, 10.0, 100.0));
 
-        let foo = AspectRatio::parse_str("xMidYMax meet", ()).unwrap();
+        let foo = AspectRatio::parse_str("xMidYMax meet").unwrap();
         let foo = foo.compute(1.0, 10.0, 0.0, 0.0, 10.0, 1.0);
         assert_quadruples_equal(&foo, &(4.95, 0.0, 0.1, 1.0));
 
-        let foo = AspectRatio::parse_str("xMidYMax slice", ()).unwrap();
+        let foo = AspectRatio::parse_str("xMidYMax slice").unwrap();
         let foo = foo.compute(1.0, 10.0, 0.0, 0.0, 10.0, 1.0);
         assert_quadruples_equal(&foo, &(0.0, -99.0, 10.0, 100.0));
 
-        let foo = AspectRatio::parse_str("xMaxYMin meet", ()).unwrap();
+        let foo = AspectRatio::parse_str("xMaxYMin meet").unwrap();
         let foo = foo.compute(1.0, 10.0, 0.0, 0.0, 10.0, 1.0);
         assert_quadruples_equal(&foo, &(9.9, 0.0, 0.1, 1.0));
 
-        let foo = AspectRatio::parse_str("xMaxYMin slice", ()).unwrap();
+        let foo = AspectRatio::parse_str("xMaxYMin slice").unwrap();
         let foo = foo.compute(1.0, 10.0, 0.0, 0.0, 10.0, 1.0);
         assert_quadruples_equal(&foo, &(0.0, 0.0, 10.0, 100.0));
 
-        let foo = AspectRatio::parse_str("xMaxYMid meet", ()).unwrap();
+        let foo = AspectRatio::parse_str("xMaxYMid meet").unwrap();
         let foo = foo.compute(1.0, 10.0, 0.0, 0.0, 10.0, 1.0);
         assert_quadruples_equal(&foo, &(9.9, 0.0, 0.1, 1.0));
 
-        let foo = AspectRatio::parse_str("xMaxYMid slice", ()).unwrap();
+        let foo = AspectRatio::parse_str("xMaxYMid slice").unwrap();
         let foo = foo.compute(1.0, 10.0, 0.0, 0.0, 10.0, 1.0);
         assert_quadruples_equal(&foo, &(0.0, -49.5, 10.0, 100.0));
 
-        let foo = AspectRatio::parse_str("xMaxYMax meet", ()).unwrap();
+        let foo = AspectRatio::parse_str("xMaxYMax meet").unwrap();
         let foo = foo.compute(1.0, 10.0, 0.0, 0.0, 10.0, 1.0);
         assert_quadruples_equal(&foo, &(9.9, 0.0, 0.1, 1.0));
 
-        let foo = AspectRatio::parse_str("xMaxYMax slice", ()).unwrap();
+        let foo = AspectRatio::parse_str("xMaxYMax slice").unwrap();
         let foo = foo.compute(1.0, 10.0, 0.0, 0.0, 10.0, 1.0);
         assert_quadruples_equal(&foo, &(0.0, -99.0, 10.0, 100.0));
     }
diff --git a/rsvg_internals/src/clip_path.rs b/rsvg_internals/src/clip_path.rs
index 78000cc2..f85543f7 100644
--- a/rsvg_internals/src/clip_path.rs
+++ b/rsvg_internals/src/clip_path.rs
@@ -81,7 +81,7 @@ impl NodeTrait for NodeClipPath {
     fn set_atts(&self, _: &RsvgNode, pbag: &PropertyBag<'_>) -> NodeResult {
         for (attr, value) in pbag.iter() {
             match attr {
-                Attribute::ClipPathUnits => self.units.set(attr.parse(value, ())?),
+                Attribute::ClipPathUnits => self.units.set(attr.parse(value)?),
                 _ => (),
             }
         }
diff --git a/rsvg_internals/src/color.rs b/rsvg_internals/src/color.rs
index c014f1e9..a9e3015c 100644
--- a/rsvg_internals/src/color.rs
+++ b/rsvg_internals/src/color.rs
@@ -9,26 +9,18 @@ use util::utf8_cstr;
 pub use cssparser::Color;
 
 impl Parse for cssparser::Color {
-    type Data = ();
     type Err = ValueErrorKind;
 
-    fn parse(
-        parser: &mut Parser<'_, '_>,
-        _: Self::Data,
-    ) -> Result<cssparser::Color, ValueErrorKind> {
+    fn parse(parser: &mut Parser<'_, '_>) -> Result<cssparser::Color, ValueErrorKind> {
         cssparser::Color::parse(parser)
             .map_err(|_| ValueErrorKind::Parse(ParseError::new("invalid syntax for color")))
     }
 }
 
 impl Parse for cssparser::RGBA {
-    type Data = ();
     type Err = ValueErrorKind;
 
-    fn parse(
-        parser: &mut Parser<'_, '_>,
-        _: Self::Data,
-    ) -> Result<cssparser::RGBA, ValueErrorKind> {
+    fn parse(parser: &mut Parser<'_, '_>) -> Result<cssparser::RGBA, ValueErrorKind> {
         match cssparser::Color::parse(parser) {
             Ok(cssparser::Color::RGBA(rgba)) => Ok(rgba),
             Ok(cssparser::Color::CurrentColor) => Err(ValueErrorKind::Value(
@@ -115,7 +107,7 @@ pub extern "C" fn rsvg_css_parse_color(string: *const libc::c_char) -> ColorSpec
             argb: 0,
         }
     } else {
-        ColorSpec::from(<Color as Parse>::parse_str(s, ()).map(|v| Some(v)))
+        ColorSpec::from(<Color as Parse>::parse_str(s).map(|v| Some(v)))
     }
 }
 
diff --git a/rsvg_internals/src/coord_units.rs b/rsvg_internals/src/coord_units.rs
index 18a61b24..2d3e733d 100644
--- a/rsvg_internals/src/coord_units.rs
+++ b/rsvg_internals/src/coord_units.rs
@@ -13,10 +13,9 @@ pub enum CoordUnits {
 }
 
 impl Parse for CoordUnits {
-    type Data = ();
     type Err = ValueErrorKind;
 
-    fn parse(parser: &mut Parser<'_, '_>, _: ()) -> Result<CoordUnits, ValueErrorKind> {
+    fn parse(parser: &mut Parser<'_, '_>) -> Result<CoordUnits, ValueErrorKind> {
         let loc = parser.current_source_location();
 
         parser
@@ -65,14 +64,12 @@ macro_rules! coord_units {
         }
 
         impl $crate::parsers::Parse for $name {
-            type Data = ();
             type Err = $crate::error::ValueErrorKind;
 
             fn parse(
                 parser: &mut ::cssparser::Parser<'_, '_>,
-                _: (),
             ) -> Result<Self, $crate::error::ValueErrorKind> {
-                Ok($name($crate::coord_units::CoordUnits::parse(parser, ())?))
+                Ok($name($crate::coord_units::CoordUnits::parse(parser)?))
             }
         }
     };
@@ -86,18 +83,18 @@ mod tests {
 
     #[test]
     fn parsing_invalid_strings_yields_error() {
-        assert!(MyUnits::parse_str("", ()).is_err());
-        assert!(MyUnits::parse_str("foo", ()).is_err());
+        assert!(MyUnits::parse_str("").is_err());
+        assert!(MyUnits::parse_str("foo").is_err());
     }
 
     #[test]
     fn parses_paint_server_units() {
         assert_eq!(
-            MyUnits::parse_str("userSpaceOnUse", ()),
+            MyUnits::parse_str("userSpaceOnUse"),
             Ok(MyUnits(CoordUnits::UserSpaceOnUse))
         );
         assert_eq!(
-            MyUnits::parse_str("objectBoundingBox", ()),
+            MyUnits::parse_str("objectBoundingBox"),
             Ok(MyUnits(CoordUnits::ObjectBoundingBox))
         );
     }
diff --git a/rsvg_internals/src/filters/color_matrix.rs b/rsvg_internals/src/filters/color_matrix.rs
index ae0b9540..746dbd32 100644
--- a/rsvg_internals/src/filters/color_matrix.rs
+++ b/rsvg_internals/src/filters/color_matrix.rs
@@ -8,7 +8,7 @@ use drawing_ctx::DrawingCtx;
 use error::NodeError;
 use node::{NodeResult, NodeTrait, RsvgNode};
 use number_list::{NumberList, NumberListError, NumberListLength};
-use parsers::{self, Parse, ParseError};
+use parsers::{self, ParseError};
 use property_bag::PropertyBag;
 use surface_utils::{
     iterators::Pixels,
diff --git a/rsvg_internals/src/filters/component_transfer.rs 
b/rsvg_internals/src/filters/component_transfer.rs
index eebfb915..61d9b3be 100644
--- a/rsvg_internals/src/filters/component_transfer.rs
+++ b/rsvg_internals/src/filters/component_transfer.rs
@@ -8,7 +8,7 @@ use drawing_ctx::DrawingCtx;
 use error::NodeError;
 use node::{NodeResult, NodeTrait, NodeType, RsvgNode};
 use number_list::{NumberList, NumberListError, NumberListLength};
-use parsers::{self, Parse, ParseError};
+use parsers::{self, ParseError};
 use property_bag::PropertyBag;
 use surface_utils::{
     iterators::Pixels,
diff --git a/rsvg_internals/src/filters/composite.rs b/rsvg_internals/src/filters/composite.rs
index 6a0f2c87..12c385df 100644
--- a/rsvg_internals/src/filters/composite.rs
+++ b/rsvg_internals/src/filters/composite.rs
@@ -69,7 +69,7 @@ impl NodeTrait for Composite {
                 Attribute::In2 => {
                     self.in2.replace(Some(Input::parse(Attribute::In2, value)?));
                 }
-                Attribute::Operator => self.operator.set(attr.parse(value, ())?),
+                Attribute::Operator => self.operator.set(attr.parse(value)?),
                 Attribute::K1 => self.k1.set(
                     parsers::number(value).map_err(|err| NodeError::attribute_error(attr, err))?,
                 ),
@@ -231,10 +231,9 @@ impl Filter for Composite {
 }
 
 impl Parse for Operator {
-    type Data = ();
     type Err = ValueErrorKind;
 
-    fn parse(parser: &mut Parser<'_, '_>, _data: Self::Data) -> Result<Self, Self::Err> {
+    fn parse(parser: &mut Parser<'_, '_>) -> Result<Self, Self::Err> {
         let loc = parser.current_source_location();
 
         parser
diff --git a/rsvg_internals/src/filters/convolve_matrix.rs b/rsvg_internals/src/filters/convolve_matrix.rs
index 7b2d785e..a62f8f45 100644
--- a/rsvg_internals/src/filters/convolve_matrix.rs
+++ b/rsvg_internals/src/filters/convolve_matrix.rs
@@ -8,7 +8,7 @@ use drawing_ctx::DrawingCtx;
 use error::NodeError;
 use node::{NodeResult, NodeTrait, RsvgNode};
 use number_list::{NumberList, NumberListError, NumberListLength};
-use parsers::{self, Parse, ParseError};
+use parsers::{self, ParseError};
 use property_bag::PropertyBag;
 use rect::IRect;
 use surface_utils::{
diff --git a/rsvg_internals/src/filters/image.rs b/rsvg_internals/src/filters/image.rs
index e604a9d5..7c41f813 100644
--- a/rsvg_internals/src/filters/image.rs
+++ b/rsvg_internals/src/filters/image.rs
@@ -173,7 +173,7 @@ impl NodeTrait for Image {
 
         for (attr, value) in pbag.iter() {
             match attr {
-                Attribute::PreserveAspectRatio => self.aspect.set(attr.parse(value, ())?),
+                Attribute::PreserveAspectRatio => self.aspect.set(attr.parse(value)?),
 
                 // "path" is used by some older Adobe Illustrator versions
                 Attribute::XlinkHref | Attribute::Path => {
diff --git a/rsvg_internals/src/filters/mod.rs b/rsvg_internals/src/filters/mod.rs
index 486fe84e..a12eee1e 100644
--- a/rsvg_internals/src/filters/mod.rs
+++ b/rsvg_internals/src/filters/mod.rs
@@ -161,26 +161,18 @@ impl NodeTrait for Primitive {
 
         for (attr, value) in pbag.iter() {
             match attr {
-                Attribute::X => self.x.set(Some(attr.parse_and_validate(
-                    value,
-                    (),
-                    check_units_horizontal,
-                )?)),
-                Attribute::Y => self.y.set(Some(attr.parse_and_validate(
-                    value,
-                    (),
-                    check_units_vertical,
-                )?)),
-                Attribute::Width => self.width.set(Some(attr.parse_and_validate(
-                    value,
-                    (),
-                    check_units_horizontal_and_ensure_nonnegative,
-                )?)),
-                Attribute::Height => self.height.set(Some(attr.parse_and_validate(
-                    value,
-                    (),
-                    check_units_vertical_and_ensure_nonnegative,
-                )?)),
+                Attribute::X => self.x.set(Some(
+                    attr.parse_and_validate(value, check_units_horizontal)?,
+                )),
+                Attribute::Y => self
+                    .y
+                    .set(Some(attr.parse_and_validate(value, check_units_vertical)?)),
+                Attribute::Width => self.width.set(Some(
+                    attr.parse_and_validate(value, check_units_horizontal_and_ensure_nonnegative)?,
+                )),
+                Attribute::Height => self.height.set(Some(
+                    attr.parse_and_validate(value, check_units_vertical_and_ensure_nonnegative)?,
+                )),
                 Attribute::Result => *self.result.borrow_mut() = Some(value.to_string()),
                 _ => (),
             }
diff --git a/rsvg_internals/src/filters/node.rs b/rsvg_internals/src/filters/node.rs
index 2889e7fa..b30e710a 100644
--- a/rsvg_internals/src/filters/node.rs
+++ b/rsvg_internals/src/filters/node.rs
@@ -24,10 +24,10 @@ impl NodeFilter {
     #[inline]
     pub fn new() -> Self {
         Self {
-            x: Cell::new(LengthHorizontal::parse_str("-10%", ()).unwrap()),
-            y: Cell::new(LengthVertical::parse_str("-10%", ()).unwrap()),
-            width: Cell::new(LengthHorizontal::parse_str("120%", ()).unwrap()),
-            height: Cell::new(LengthVertical::parse_str("120%", ()).unwrap()),
+            x: Cell::new(LengthHorizontal::parse_str("-10%").unwrap()),
+            y: Cell::new(LengthVertical::parse_str("-10%").unwrap()),
+            width: Cell::new(LengthHorizontal::parse_str("120%").unwrap()),
+            height: Cell::new(LengthVertical::parse_str("120%").unwrap()),
             filterunits: Cell::new(CoordUnits::ObjectBoundingBox),
             primitiveunits: Cell::new(CoordUnits::UserSpaceOnUse),
         }
@@ -39,7 +39,7 @@ impl NodeTrait for NodeFilter {
         // Parse filterUnits first as it affects x, y, width, height checks.
         for (attr, value) in pbag.iter() {
             match attr {
-                Attribute::FilterUnits => self.filterunits.set(attr.parse(value, ())?),
+                Attribute::FilterUnits => self.filterunits.set(attr.parse(value)?),
                 _ => (),
             }
         }
@@ -84,25 +84,19 @@ impl NodeTrait for NodeFilter {
         // Parse the rest of the attributes.
         for (attr, value) in pbag.iter() {
             match attr {
-                Attribute::X => {
-                    self.x
-                        .set(attr.parse_and_validate(value, (), check_units_horizontal)?)
-                }
-                Attribute::Y => {
-                    self.y
-                        .set(attr.parse_and_validate(value, (), check_units_vertical)?)
-                }
-                Attribute::Width => self.width.set(attr.parse_and_validate(
-                    value,
-                    (),
-                    check_units_horizontal_and_ensure_nonnegative,
-                )?),
-                Attribute::Height => self.height.set(attr.parse_and_validate(
-                    value,
-                    (),
-                    check_units_vertical_and_ensure_nonnegative,
-                )?),
-                Attribute::PrimitiveUnits => self.primitiveunits.set(attr.parse(value, ())?),
+                Attribute::X => self
+                    .x
+                    .set(attr.parse_and_validate(value, check_units_horizontal)?),
+                Attribute::Y => self
+                    .y
+                    .set(attr.parse_and_validate(value, check_units_vertical)?),
+                Attribute::Width => self.width.set(
+                    attr.parse_and_validate(value, check_units_horizontal_and_ensure_nonnegative)?,
+                ),
+                Attribute::Height => self.height.set(
+                    attr.parse_and_validate(value, check_units_vertical_and_ensure_nonnegative)?,
+                ),
+                Attribute::PrimitiveUnits => self.primitiveunits.set(attr.parse(value)?),
                 _ => (),
             }
         }
diff --git a/rsvg_internals/src/font_props.rs b/rsvg_internals/src/font_props.rs
index 534bd94f..b663fd45 100644
--- a/rsvg_internals/src/font_props.rs
+++ b/rsvg_internals/src/font_props.rs
@@ -59,16 +59,12 @@ impl FontSizeSpec {
 }
 
 impl Parse for FontSizeSpec {
-    type Data = ();
     type Err = ValueErrorKind;
 
-    fn parse(
-        parser: &mut Parser<'_, '_>,
-        _: Self::Data,
-    ) -> Result<FontSizeSpec, ::error::ValueErrorKind> {
+    fn parse(parser: &mut Parser<'_, '_>) -> Result<FontSizeSpec, ::error::ValueErrorKind> {
         let parser_state = parser.state();
 
-        LengthBoth::parse(parser, ())
+        LengthBoth::parse(parser)
             .and_then(|s| Ok(FontSizeSpec::Value(s)))
             .or_else(|e| {
                 parser.reset(&parser_state);
@@ -120,13 +116,9 @@ pub enum FontWeightSpec {
 }
 
 impl Parse for FontWeightSpec {
-    type Data = ();
     type Err = ValueErrorKind;
 
-    fn parse(
-        parser: &mut Parser<'_, '_>,
-        _: Self::Data,
-    ) -> Result<FontWeightSpec, ::error::ValueErrorKind> {
+    fn parse(parser: &mut Parser<'_, '_>) -> Result<FontWeightSpec, ::error::ValueErrorKind> {
         if let Ok(r) = parser.try(|p| {
             p.expect_ident()
                 .map_err(|_| ())
@@ -196,16 +188,12 @@ impl LetterSpacingSpec {
 }
 
 impl Parse for LetterSpacingSpec {
-    type Data = ();
     type Err = ValueErrorKind;
 
-    fn parse(
-        parser: &mut Parser<'_, '_>,
-        _: Self::Data,
-    ) -> Result<LetterSpacingSpec, ::error::ValueErrorKind> {
+    fn parse(parser: &mut Parser<'_, '_>) -> Result<LetterSpacingSpec, ::error::ValueErrorKind> {
         let parser_state = parser.state();
 
-        LengthHorizontal::parse(parser, ())
+        LengthHorizontal::parse(parser)
             .and_then(|s| Ok(LetterSpacingSpec::Value(s)))
             .or_else(|e| {
                 parser.reset(&parser_state);
@@ -235,13 +223,9 @@ impl Parse for LetterSpacingSpec {
 pub struct SingleFontFamily(pub String);
 
 impl Parse for SingleFontFamily {
-    type Data = ();
     type Err = ValueErrorKind;
 
-    fn parse(
-        parser: &mut Parser<'_, '_>,
-        _: Self::Data,
-    ) -> Result<SingleFontFamily, ValueErrorKind> {
+    fn parse(parser: &mut Parser<'_, '_>) -> Result<SingleFontFamily, ValueErrorKind> {
         parse_single_font_family(parser)
             .map_err(|_| ValueErrorKind::from(ParseError::new("expected font family")))
     }
@@ -272,41 +256,41 @@ mod tests {
 
     #[test]
     fn detects_invalid_invalid_font_size() {
-        assert!(is_parse_error(&FontSizeSpec::parse_str("furlong", ())));
+        assert!(is_parse_error(&FontSizeSpec::parse_str("furlong")));
     }
 
     #[test]
     fn parses_font_weight() {
         assert_eq!(
-            <FontWeightSpec as Parse>::parse_str("normal", ()),
+            <FontWeightSpec as Parse>::parse_str("normal"),
             Ok(FontWeightSpec::Normal)
         );
         assert_eq!(
-            <FontWeightSpec as Parse>::parse_str("bold", ()),
+            <FontWeightSpec as Parse>::parse_str("bold"),
             Ok(FontWeightSpec::Bold)
         );
         assert_eq!(
-            <FontWeightSpec as Parse>::parse_str("100", ()),
+            <FontWeightSpec as Parse>::parse_str("100"),
             Ok(FontWeightSpec::W100)
         );
     }
 
     #[test]
     fn detects_invalid_font_weight() {
-        assert!(<FontWeightSpec as Parse>::parse_str("", ()).is_err());
-        assert!(<FontWeightSpec as Parse>::parse_str("strange", ()).is_err());
-        assert!(<FontWeightSpec as Parse>::parse_str("314", ()).is_err());
-        assert!(<FontWeightSpec as Parse>::parse_str("3.14", ()).is_err());
+        assert!(<FontWeightSpec as Parse>::parse_str("").is_err());
+        assert!(<FontWeightSpec as Parse>::parse_str("strange").is_err());
+        assert!(<FontWeightSpec as Parse>::parse_str("314").is_err());
+        assert!(<FontWeightSpec as Parse>::parse_str("3.14").is_err());
     }
 
     #[test]
     fn parses_letter_spacing() {
         assert_eq!(
-            <LetterSpacingSpec as Parse>::parse_str("normal", ()),
+            <LetterSpacingSpec as Parse>::parse_str("normal"),
             Ok(LetterSpacingSpec::Normal)
         );
         assert_eq!(
-            <LetterSpacingSpec as Parse>::parse_str("10em", ()),
+            <LetterSpacingSpec as Parse>::parse_str("10em"),
             Ok(LetterSpacingSpec::Value(LengthHorizontal::new(
                 10.0,
                 LengthUnit::FontEm,
@@ -317,14 +301,14 @@ mod tests {
     #[test]
     fn computes_letter_spacing() {
         assert_eq!(
-            <LetterSpacingSpec as Parse>::parse_str("normal", ()).map(|s| s.compute()),
+            <LetterSpacingSpec as Parse>::parse_str("normal").map(|s| s.compute()),
             Ok(LetterSpacingSpec::Value(LengthHorizontal::new(
                 0.0,
                 LengthUnit::Default,
             )))
         );
         assert_eq!(
-            <LetterSpacingSpec as Parse>::parse_str("10em", ()).map(|s| s.compute()),
+            <LetterSpacingSpec as Parse>::parse_str("10em").map(|s| s.compute()),
             Ok(LetterSpacingSpec::Value(LengthHorizontal::new(
                 10.0,
                 LengthUnit::FontEm,
@@ -334,38 +318,38 @@ mod tests {
 
     #[test]
     fn detects_invalid_invalid_letter_spacing() {
-        assert!(is_parse_error(&LetterSpacingSpec::parse_str("furlong", ())));
+        assert!(is_parse_error(&LetterSpacingSpec::parse_str("furlong")));
     }
 
     #[test]
     fn parses_font_family() {
         assert_eq!(
-            <SingleFontFamily as Parse>::parse_str("'Hello world'", ()),
+            <SingleFontFamily as Parse>::parse_str("'Hello world'"),
             Ok(SingleFontFamily("Hello world".to_owned()))
         );
 
         assert_eq!(
-            <SingleFontFamily as Parse>::parse_str("\"Hello world\"", ()),
+            <SingleFontFamily as Parse>::parse_str("\"Hello world\""),
             Ok(SingleFontFamily("Hello world".to_owned()))
         );
 
         assert_eq!(
-            <SingleFontFamily as Parse>::parse_str("  Hello  world  ", ()),
+            <SingleFontFamily as Parse>::parse_str("  Hello  world  "),
             Ok(SingleFontFamily("Hello world".to_owned()))
         );
 
         assert_eq!(
-            <SingleFontFamily as Parse>::parse_str("Plonk", ()),
+            <SingleFontFamily as Parse>::parse_str("Plonk"),
             Ok(SingleFontFamily("Plonk".to_owned()))
         );
     }
 
     #[test]
     fn detects_invalid_font_family() {
-        assert!(<SingleFontFamily as Parse>::parse_str("", ()).is_err());
+        assert!(<SingleFontFamily as Parse>::parse_str("").is_err());
 
-        // assert!(<SingleFontFamily as Parse>::parse_str("''", ()).is_err());
+        // assert!(<SingleFontFamily as Parse>::parse_str("''").is_err());
 
-        assert!(<SingleFontFamily as Parse>::parse_str("42", ()).is_err());
+        assert!(<SingleFontFamily as Parse>::parse_str("42").is_err());
     }
 }
diff --git a/rsvg_internals/src/gradient.rs b/rsvg_internals/src/gradient.rs
index 4e9fc893..df27afc9 100644
--- a/rsvg_internals/src/gradient.rs
+++ b/rsvg_internals/src/gradient.rs
@@ -36,10 +36,9 @@ pub enum SpreadMethod {
 }
 
 impl Parse for SpreadMethod {
-    type Data = ();
     type Err = ValueErrorKind;
 
-    fn parse(parser: &mut Parser<'_, '_>, _: ()) -> Result<SpreadMethod, ValueErrorKind> {
+    fn parse(parser: &mut Parser<'_, '_>) -> Result<SpreadMethod, ValueErrorKind> {
         let loc = parser.current_source_location();
 
         parser
@@ -256,10 +255,10 @@ impl GradientVariant {
         // https://www.w3.org/TR/SVG/pservers.html#LinearGradients
 
         GradientVariant::Linear {
-            x1: Some(LengthHorizontal::parse_str("0%", ()).unwrap()),
-            y1: Some(LengthVertical::parse_str("0%", ()).unwrap()),
-            x2: Some(LengthHorizontal::parse_str("100%", ()).unwrap()),
-            y2: Some(LengthVertical::parse_str("0%", ()).unwrap()),
+            x1: Some(LengthHorizontal::parse_str("0%").unwrap()),
+            y1: Some(LengthVertical::parse_str("0%").unwrap()),
+            x2: Some(LengthHorizontal::parse_str("100%").unwrap()),
+            y2: Some(LengthVertical::parse_str("0%").unwrap()),
         }
     }
 
@@ -267,9 +266,9 @@ impl GradientVariant {
         // https://www.w3.org/TR/SVG/pservers.html#RadialGradients
 
         GradientVariant::Radial {
-            cx: Some(LengthHorizontal::parse_str("50%", ()).unwrap()),
-            cy: Some(LengthVertical::parse_str("50%", ()).unwrap()),
-            r: Some(LengthBoth::parse_str("50%", ()).unwrap()),
+            cx: Some(LengthHorizontal::parse_str("50%").unwrap()),
+            cy: Some(LengthVertical::parse_str("50%").unwrap()),
+            r: Some(LengthBoth::parse_str("50%").unwrap()),
 
             fx: None,
             fy: None,
@@ -674,9 +673,9 @@ impl NodeTrait for NodeGradient {
         for (attr, value) in pbag.iter() {
             match attr {
                 // Attributes common to linear and radial gradients
-                Attribute::GradientUnits => g.common.units = Some(attr.parse(value, ())?),
-                Attribute::GradientTransform => g.common.affine = Some(attr.parse(value, ())?),
-                Attribute::SpreadMethod => g.common.spread = Some(attr.parse(value, ())?),
+                Attribute::GradientUnits => g.common.units = Some(attr.parse(value)?),
+                Attribute::GradientTransform => g.common.affine = Some(attr.parse(value)?),
+                Attribute::SpreadMethod => g.common.spread = Some(attr.parse(value)?),
                 Attribute::XlinkHref => {
                     g.common.fallback =
                         Some(Fragment::parse(value).attribute(Attribute::XlinkHref)?)
@@ -684,16 +683,16 @@ impl NodeTrait for NodeGradient {
 
                 // Attributes specific to each gradient type.  The defaults mandated by the spec
                 // are in GradientVariant::resolve_from_defaults()
-                Attribute::X1 => x1 = Some(attr.parse(value, ())?),
-                Attribute::Y1 => y1 = Some(attr.parse(value, ())?),
-                Attribute::X2 => x2 = Some(attr.parse(value, ())?),
-                Attribute::Y2 => y2 = Some(attr.parse(value, ())?),
+                Attribute::X1 => x1 = Some(attr.parse(value)?),
+                Attribute::Y1 => y1 = Some(attr.parse(value)?),
+                Attribute::X2 => x2 = Some(attr.parse(value)?),
+                Attribute::Y2 => y2 = Some(attr.parse(value)?),
 
-                Attribute::Cx => cx = Some(attr.parse(value, ())?),
-                Attribute::Cy => cy = Some(attr.parse(value, ())?),
-                Attribute::R => r = Some(attr.parse(value, ())?),
-                Attribute::Fx => fx = Some(attr.parse(value, ())?),
-                Attribute::Fy => fy = Some(attr.parse(value, ())?),
+                Attribute::Cx => cx = Some(attr.parse(value)?),
+                Attribute::Cy => cy = Some(attr.parse(value)?),
+                Attribute::R => r = Some(attr.parse(value)?),
+                Attribute::Fx => fx = Some(attr.parse(value)?),
+                Attribute::Fy => fy = Some(attr.parse(value)?),
 
                 _ => (),
             }
@@ -722,16 +721,13 @@ mod tests {
 
     #[test]
     fn parses_spread_method() {
-        assert_eq!(SpreadMethod::parse_str("pad", ()), Ok(SpreadMethod::Pad));
+        assert_eq!(SpreadMethod::parse_str("pad"), Ok(SpreadMethod::Pad));
         assert_eq!(
-            SpreadMethod::parse_str("reflect", ()),
+            SpreadMethod::parse_str("reflect"),
             Ok(SpreadMethod::Reflect)
         );
-        assert_eq!(
-            SpreadMethod::parse_str("repeat", ()),
-            Ok(SpreadMethod::Repeat)
-        );
-        assert!(SpreadMethod::parse_str("foobar", ()).is_err());
+        assert_eq!(SpreadMethod::parse_str("repeat"), Ok(SpreadMethod::Repeat));
+        assert!(SpreadMethod::parse_str("foobar").is_err());
     }
 
     fn assert_tuples_equal(a: &(f64, f64), b: &(f64, f64)) {
diff --git a/rsvg_internals/src/image.rs b/rsvg_internals/src/image.rs
index 580baa7a..448caf20 100644
--- a/rsvg_internals/src/image.rs
+++ b/rsvg_internals/src/image.rs
@@ -44,20 +44,16 @@ impl NodeTrait for NodeImage {
 
         for (attr, value) in pbag.iter() {
             match attr {
-                Attribute::X => self.x.set(attr.parse(value, ())?),
-                Attribute::Y => self.y.set(attr.parse(value, ())?),
-                Attribute::Width => self.w.set(attr.parse_and_validate(
-                    value,
-                    (),
-                    LengthHorizontal::check_nonnegative,
-                )?),
-                Attribute::Height => self.h.set(attr.parse_and_validate(
-                    value,
-                    (),
-                    LengthVertical::check_nonnegative,
-                )?),
-
-                Attribute::PreserveAspectRatio => self.aspect.set(attr.parse(value, ())?),
+                Attribute::X => self.x.set(attr.parse(value)?),
+                Attribute::Y => self.y.set(attr.parse(value)?),
+                Attribute::Width => self
+                    .w
+                    .set(attr.parse_and_validate(value, LengthHorizontal::check_nonnegative)?),
+                Attribute::Height => self
+                    .h
+                    .set(attr.parse_and_validate(value, LengthVertical::check_nonnegative)?),
+
+                Attribute::PreserveAspectRatio => self.aspect.set(attr.parse(value)?),
 
                 // "path" is used by some older Adobe Illustrator versions
                 Attribute::XlinkHref | Attribute::Path => {
diff --git a/rsvg_internals/src/iri.rs b/rsvg_internals/src/iri.rs
index 45a45f9d..92ff5c97 100644
--- a/rsvg_internals/src/iri.rs
+++ b/rsvg_internals/src/iri.rs
@@ -33,10 +33,9 @@ impl IRI {
 }
 
 impl Parse for IRI {
-    type Data = ();
     type Err = ParseError;
 
-    fn parse(parser: &mut Parser<'_, '_>, _: Self::Data) -> Result<IRI, ParseError> {
+    fn parse(parser: &mut Parser<'_, '_>) -> Result<IRI, ParseError> {
         if parser.try(|i| i.expect_ident_matching("none")).is_ok() {
             Ok(IRI::None)
         } else {
@@ -62,18 +61,18 @@ mod tests {
 
     #[test]
     fn parses_none() {
-        assert_eq!(IRI::parse_str("none", ()), Ok(IRI::None));
+        assert_eq!(IRI::parse_str("none"), Ok(IRI::None));
     }
 
     #[test]
     fn parses_url() {
         assert_eq!(
-            IRI::parse_str("url(#bar)", ()),
+            IRI::parse_str("url(#bar)"),
             Ok(IRI::Resource(Fragment::new(None, "bar".to_string())))
         );
 
         assert_eq!(
-            IRI::parse_str("url(foo#bar)", ()),
+            IRI::parse_str("url(foo#bar)"),
             Ok(IRI::Resource(Fragment::new(
                 Some("foo".to_string()),
                 "bar".to_string()
@@ -82,19 +81,19 @@ mod tests {
 
         // be permissive if the closing ) is missing
         assert_eq!(
-            IRI::parse_str("url(#bar", ()),
+            IRI::parse_str("url(#bar"),
             Ok(IRI::Resource(Fragment::new(None, "bar".to_string())))
         );
         assert_eq!(
-            IRI::parse_str("url(foo#bar", ()),
+            IRI::parse_str("url(foo#bar"),
             Ok(IRI::Resource(Fragment::new(
                 Some("foo".to_string()),
                 "bar".to_string()
             )))
         );
 
-        assert!(IRI::parse_str("", ()).is_err());
-        assert!(IRI::parse_str("foo", ()).is_err());
-        assert!(IRI::parse_str("url(foo)bar", ()).is_err());
+        assert!(IRI::parse_str("").is_err());
+        assert!(IRI::parse_str("foo").is_err());
+        assert!(IRI::parse_str("url(foo)bar").is_err());
     }
 }
diff --git a/rsvg_internals/src/length.rs b/rsvg_internals/src/length.rs
index 75ed884d..f13be1c9 100644
--- a/rsvg_internals/src/length.rs
+++ b/rsvg_internals/src/length.rs
@@ -108,11 +108,10 @@ macro_rules! define_length_type {
         }
 
         impl Parse for $name {
-            type Data = ();
             type Err = ValueErrorKind;
 
-            fn parse(parser: &mut Parser<'_, '_>, _: ()) -> Result<$name, ValueErrorKind> {
-                Ok($name(Length::parse(parser, ())?))
+            fn parse(parser: &mut Parser<'_, '_>) -> Result<$name, ValueErrorKind> {
+                Ok($name(Length::parse(parser)?))
             }
         }
     };
@@ -165,10 +164,9 @@ fn make_err() -> ValueErrorKind {
 }
 
 impl Parse for Length {
-    type Data = ();
     type Err = ValueErrorKind;
 
-    fn parse(parser: &mut Parser<'_, '_>, _: ()) -> Result<Length, ValueErrorKind> {
+    fn parse(parser: &mut Parser<'_, '_>) -> Result<Length, ValueErrorKind> {
         let length = Length::from_cssparser(parser)?;
 
         parser.expect_exhausted().map_err(|_| make_err())?;
@@ -320,10 +318,9 @@ impl Default for Dasharray {
 }
 
 impl Parse for Dasharray {
-    type Data = ();
     type Err = ValueErrorKind;
 
-    fn parse(parser: &mut Parser<'_, '_>, _: Self::Data) -> Result<Dasharray, ValueErrorKind> {
+    fn parse(parser: &mut Parser<'_, '_>) -> Result<Dasharray, ValueErrorKind> {
         if parser.try(|p| p.expect_ident_matching("none")).is_ok() {
             Ok(Dasharray::None)
         } else {
@@ -358,12 +355,12 @@ mod tests {
     #[test]
     fn parses_default() {
         assert_eq!(
-            LengthHorizontal::parse_str("42", ()),
+            LengthHorizontal::parse_str("42"),
             Ok(LengthHorizontal(Length::new(42.0, LengthUnit::Default,)))
         );
 
         assert_eq!(
-            LengthHorizontal::parse_str("-42px", ()),
+            LengthHorizontal::parse_str("-42px"),
             Ok(LengthHorizontal(Length::new(-42.0, LengthUnit::Default,)))
         );
     }
@@ -371,7 +368,7 @@ mod tests {
     #[test]
     fn parses_percent() {
         assert_eq!(
-            LengthHorizontal::parse_str("50.0%", ()),
+            LengthHorizontal::parse_str("50.0%"),
             Ok(LengthHorizontal(Length::new(0.5, LengthUnit::Percent,)))
         );
     }
@@ -379,7 +376,7 @@ mod tests {
     #[test]
     fn parses_font_em() {
         assert_eq!(
-            LengthVertical::parse_str("22.5em", ()),
+            LengthVertical::parse_str("22.5em"),
             Ok(LengthVertical(Length::new(22.5, LengthUnit::FontEm,)))
         );
     }
@@ -387,7 +384,7 @@ mod tests {
     #[test]
     fn parses_font_ex() {
         assert_eq!(
-            LengthVertical::parse_str("22.5ex", ()),
+            LengthVertical::parse_str("22.5ex"),
             Ok(LengthVertical(Length::new(22.5, LengthUnit::FontEx,)))
         );
     }
@@ -395,47 +392,47 @@ mod tests {
     #[test]
     fn parses_physical_units() {
         assert_eq!(
-            LengthBoth::parse_str("72pt", ()),
+            LengthBoth::parse_str("72pt"),
             Ok(LengthBoth(Length::new(1.0, LengthUnit::Inch,)))
         );
 
         assert_eq!(
-            LengthBoth::parse_str("-22.5in", ()),
+            LengthBoth::parse_str("-22.5in"),
             Ok(LengthBoth(Length::new(-22.5, LengthUnit::Inch,)))
         );
 
         assert_eq!(
-            LengthBoth::parse_str("-254cm", ()),
+            LengthBoth::parse_str("-254cm"),
             Ok(LengthBoth(Length::new(-100.0, LengthUnit::Inch,)))
         );
 
         assert_eq!(
-            LengthBoth::parse_str("254mm", ()),
+            LengthBoth::parse_str("254mm"),
             Ok(LengthBoth(Length::new(10.0, LengthUnit::Inch,)))
         );
 
         assert_eq!(
-            LengthBoth::parse_str("60pc", ()),
+            LengthBoth::parse_str("60pc"),
             Ok(LengthBoth(Length::new(10.0, LengthUnit::Inch,)))
         );
     }
 
     #[test]
     fn empty_length_yields_error() {
-        assert!(is_parse_error(&LengthBoth::parse_str("", ())));
+        assert!(is_parse_error(&LengthBoth::parse_str("")));
     }
 
     #[test]
     fn invalid_unit_yields_error() {
-        assert!(is_parse_error(&LengthBoth::parse_str("8furlong", ())));
+        assert!(is_parse_error(&LengthBoth::parse_str("8furlong")));
     }
 
     #[test]
     fn check_nonnegative_works() {
-        assert!(LengthBoth::parse_str("0", ())
+        assert!(LengthBoth::parse_str("0")
             .and_then(|l| l.check_nonnegative())
             .is_ok());
-        assert!(LengthBoth::parse_str("-10", ())
+        assert!(LengthBoth::parse_str("-10")
             .and_then(|l| l.check_nonnegative())
             .is_err());
     }
@@ -505,13 +502,13 @@ mod tests {
     }
 
     fn parse_dash_array_str(s: &str) -> Result<Dasharray, ValueErrorKind> {
-        Dasharray::parse_str(s, ())
+        Dasharray::parse_str(s)
     }
 
     #[test]
     fn parses_dash_array() {
         // helper to cut down boilderplate
-        let length_parse = |s| LengthBoth::parse_str(s, ()).unwrap();
+        let length_parse = |s| LengthBoth::parse_str(s).unwrap();
 
         let expected = Dasharray::Array(vec![
             length_parse("1"),
diff --git a/rsvg_internals/src/marker.rs b/rsvg_internals/src/marker.rs
index 9f6843a9..310c0638 100644
--- a/rsvg_internals/src/marker.rs
+++ b/rsvg_internals/src/marker.rs
@@ -35,10 +35,9 @@ impl Default for MarkerUnits {
 }
 
 impl Parse for MarkerUnits {
-    type Data = ();
     type Err = ValueErrorKind;
 
-    fn parse(parser: &mut Parser<'_, '_>, _: ()) -> Result<MarkerUnits, ValueErrorKind> {
+    fn parse(parser: &mut Parser<'_, '_>) -> Result<MarkerUnits, ValueErrorKind> {
         let loc = parser.current_source_location();
 
         parser
@@ -74,14 +73,13 @@ impl Default for MarkerOrient {
 }
 
 impl Parse for MarkerOrient {
-    type Data = ();
     type Err = ValueErrorKind;
 
-    fn parse(parser: &mut Parser<'_, '_>, _: ()) -> Result<MarkerOrient, ValueErrorKind> {
+    fn parse(parser: &mut Parser<'_, '_>) -> Result<MarkerOrient, ValueErrorKind> {
         if parser.try(|p| p.expect_ident_matching("auto")).is_ok() {
             Ok(MarkerOrient::Auto)
         } else {
-            Angle::parse(parser, ()).map(MarkerOrient::Angle)
+            Angle::parse(parser).map(MarkerOrient::Angle)
         }
     }
 }
@@ -104,8 +102,8 @@ impl NodeMarker {
             ref_x: Cell::new(Default::default()),
             ref_y: Cell::new(Default::default()),
             // the following two are per the spec
-            width: Cell::new(LengthHorizontal::parse_str("3", ()).unwrap()),
-            height: Cell::new(LengthVertical::parse_str("3", ()).unwrap()),
+            width: Cell::new(LengthHorizontal::parse_str("3").unwrap()),
+            height: Cell::new(LengthVertical::parse_str("3").unwrap()),
             orient: Cell::new(MarkerOrient::default()),
             aspect: Cell::new(AspectRatio::default()),
             vbox: Cell::new(None),
@@ -209,29 +207,25 @@ impl NodeTrait for NodeMarker {
 
         for (attr, value) in pbag.iter() {
             match attr {
-                Attribute::MarkerUnits => self.units.set(attr.parse(value, ())?),
+                Attribute::MarkerUnits => self.units.set(attr.parse(value)?),
 
-                Attribute::RefX => self.ref_x.set(attr.parse(value, ())?),
+                Attribute::RefX => self.ref_x.set(attr.parse(value)?),
 
-                Attribute::RefY => self.ref_y.set(attr.parse(value, ())?),
+                Attribute::RefY => self.ref_y.set(attr.parse(value)?),
 
-                Attribute::MarkerWidth => self.width.set(attr.parse_and_validate(
-                    value,
-                    (),
-                    LengthHorizontal::check_nonnegative,
-                )?),
+                Attribute::MarkerWidth => self
+                    .width
+                    .set(attr.parse_and_validate(value, LengthHorizontal::check_nonnegative)?),
 
-                Attribute::MarkerHeight => self.height.set(attr.parse_and_validate(
-                    value,
-                    (),
-                    LengthVertical::check_nonnegative,
-                )?),
+                Attribute::MarkerHeight => self
+                    .height
+                    .set(attr.parse_and_validate(value, LengthVertical::check_nonnegative)?),
 
-                Attribute::Orient => self.orient.set(attr.parse(value, ())?),
+                Attribute::Orient => self.orient.set(attr.parse(value)?),
 
-                Attribute::PreserveAspectRatio => self.aspect.set(attr.parse(value, ())?),
+                Attribute::PreserveAspectRatio => self.aspect.set(attr.parse(value)?),
 
-                Attribute::ViewBox => self.vbox.set(Some(attr.parse(value, ())?)),
+                Attribute::ViewBox => self.vbox.set(Some(attr.parse(value)?)),
 
                 _ => (),
             }
@@ -833,21 +827,21 @@ mod parser_tests {
     #[test]
     fn parsing_invalid_marker_units_yields_error() {
         assert!(is_parse_error(
-            &MarkerUnits::parse_str("", ()).map_err(|e| ValueErrorKind::from(e))
+            &MarkerUnits::parse_str("").map_err(|e| ValueErrorKind::from(e))
         ));
         assert!(is_parse_error(
-            &MarkerUnits::parse_str("foo", ()).map_err(|e| ValueErrorKind::from(e))
+            &MarkerUnits::parse_str("foo").map_err(|e| ValueErrorKind::from(e))
         ));
     }
 
     #[test]
     fn parses_marker_units() {
         assert_eq!(
-            MarkerUnits::parse_str("userSpaceOnUse", ()),
+            MarkerUnits::parse_str("userSpaceOnUse"),
             Ok(MarkerUnits::UserSpaceOnUse)
         );
         assert_eq!(
-            MarkerUnits::parse_str("strokeWidth", ()),
+            MarkerUnits::parse_str("strokeWidth"),
             Ok(MarkerUnits::StrokeWidth)
         );
     }
@@ -855,38 +849,38 @@ mod parser_tests {
     #[test]
     fn parsing_invalid_marker_orient_yields_error() {
         assert!(is_parse_error(
-            &MarkerOrient::parse_str("", ()).map_err(|e| ValueErrorKind::from(e))
+            &MarkerOrient::parse_str("").map_err(|e| ValueErrorKind::from(e))
         ));
         assert!(is_parse_error(
-            &MarkerOrient::parse_str("blah", ()).map_err(|e| ValueErrorKind::from(e))
+            &MarkerOrient::parse_str("blah").map_err(|e| ValueErrorKind::from(e))
         ));
         assert!(is_parse_error(
-            &MarkerOrient::parse_str("45blah", ()).map_err(|e| ValueErrorKind::from(e))
+            &MarkerOrient::parse_str("45blah").map_err(|e| ValueErrorKind::from(e))
         ));
     }
 
     #[test]
     fn parses_marker_orient() {
-        assert_eq!(MarkerOrient::parse_str("auto", ()), Ok(MarkerOrient::Auto));
+        assert_eq!(MarkerOrient::parse_str("auto"), Ok(MarkerOrient::Auto));
 
         assert_eq!(
-            MarkerOrient::parse_str("0", ()),
+            MarkerOrient::parse_str("0"),
             Ok(MarkerOrient::Angle(Angle::new(0.0)))
         );
         assert_eq!(
-            MarkerOrient::parse_str("180", ()),
+            MarkerOrient::parse_str("180"),
             Ok(MarkerOrient::Angle(Angle::from_degrees(180.0)))
         );
         assert_eq!(
-            MarkerOrient::parse_str("180deg", ()),
+            MarkerOrient::parse_str("180deg"),
             Ok(MarkerOrient::Angle(Angle::from_degrees(180.0)))
         );
         assert_eq!(
-            MarkerOrient::parse_str("-400grad", ()),
+            MarkerOrient::parse_str("-400grad"),
             Ok(MarkerOrient::Angle(Angle::from_degrees(-360.0)))
         );
         assert_eq!(
-            MarkerOrient::parse_str("1rad", ()),
+            MarkerOrient::parse_str("1rad"),
             Ok(MarkerOrient::Angle(Angle::new(1.0)))
         );
     }
diff --git a/rsvg_internals/src/mask.rs b/rsvg_internals/src/mask.rs
index 6f6ac58d..1d00e5b0 100644
--- a/rsvg_internals/src/mask.rs
+++ b/rsvg_internals/src/mask.rs
@@ -36,11 +36,11 @@ impl NodeMask {
     pub fn new() -> NodeMask {
         NodeMask {
             // these values are per the spec
-            x: Cell::new(LengthHorizontal::parse_str("-10%", ()).unwrap()),
-            y: Cell::new(LengthVertical::parse_str("-10%", ()).unwrap()),
+            x: Cell::new(LengthHorizontal::parse_str("-10%").unwrap()),
+            y: Cell::new(LengthVertical::parse_str("-10%").unwrap()),
 
-            width: Cell::new(LengthHorizontal::parse_str("120%", ()).unwrap()),
-            height: Cell::new(LengthVertical::parse_str("120%", ()).unwrap()),
+            width: Cell::new(LengthHorizontal::parse_str("120%").unwrap()),
+            height: Cell::new(LengthVertical::parse_str("120%").unwrap()),
 
             units: Cell::new(MaskUnits::default()),
             content_units: Cell::new(MaskContentUnits::default()),
@@ -188,20 +188,16 @@ impl NodeTrait for NodeMask {
     fn set_atts(&self, _: &RsvgNode, pbag: &PropertyBag<'_>) -> NodeResult {
         for (attr, value) in pbag.iter() {
             match attr {
-                Attribute::X => self.x.set(attr.parse(value, ())?),
-                Attribute::Y => self.y.set(attr.parse(value, ())?),
-                Attribute::Width => self.width.set(attr.parse_and_validate(
-                    value,
-                    (),
-                    LengthHorizontal::check_nonnegative,
-                )?),
-                Attribute::Height => self.height.set(attr.parse_and_validate(
-                    value,
-                    (),
-                    LengthVertical::check_nonnegative,
-                )?),
-                Attribute::MaskUnits => self.units.set(attr.parse(value, ())?),
-                Attribute::MaskContentUnits => self.content_units.set(attr.parse(value, ())?),
+                Attribute::X => self.x.set(attr.parse(value)?),
+                Attribute::Y => self.y.set(attr.parse(value)?),
+                Attribute::Width => self
+                    .width
+                    .set(attr.parse_and_validate(value, LengthHorizontal::check_nonnegative)?),
+                Attribute::Height => self
+                    .height
+                    .set(attr.parse_and_validate(value, LengthVertical::check_nonnegative)?),
+                Attribute::MaskUnits => self.units.set(attr.parse(value)?),
+                Attribute::MaskContentUnits => self.content_units.set(attr.parse(value)?),
                 _ => (),
             }
         }
diff --git a/rsvg_internals/src/node.rs b/rsvg_internals/src/node.rs
index 8378cd20..296171de 100644
--- a/rsvg_internals/src/node.rs
+++ b/rsvg_internals/src/node.rs
@@ -352,7 +352,7 @@ impl Node {
     pub fn set_atts(&self, node: &RsvgNode, pbag: &PropertyBag<'_>) {
         for (attr, value) in pbag.iter() {
             match attr {
-                Attribute::Transform => match Matrix::parse_str(value, ()) {
+                Attribute::Transform => match Matrix::parse_str(value) {
                     Ok(affine) => self.data.transform.set(affine),
                     Err(e) => {
                         self.set_error(NodeError::attribute_error(Attribute::Transform, e));
diff --git a/rsvg_internals/src/number_list.rs b/rsvg_internals/src/number_list.rs
index 1fb9f2fd..56e3f36c 100644
--- a/rsvg_internals/src/number_list.rs
+++ b/rsvg_internals/src/number_list.rs
@@ -1,6 +1,6 @@
 use cssparser::{Parser, ParserInput};
 
-use parsers::{CssParserExt, Parse, ParseError};
+use parsers::{CssParserExt, ParseError};
 
 #[derive(Eq, PartialEq)]
 pub enum NumberListLength {
diff --git a/rsvg_internals/src/paint_server.rs b/rsvg_internals/src/paint_server.rs
index 63141d91..1897e55d 100644
--- a/rsvg_internals/src/paint_server.rs
+++ b/rsvg_internals/src/paint_server.rs
@@ -20,10 +20,9 @@ pub enum PaintServer {
 }
 
 impl Parse for PaintServer {
-    type Data = ();
     type Err = ValueErrorKind;
 
-    fn parse(parser: &mut Parser<'_, '_>, _: ()) -> Result<PaintServer, ValueErrorKind> {
+    fn parse(parser: &mut Parser<'_, '_>) -> Result<PaintServer, ValueErrorKind> {
         if parser.try(|i| i.expect_ident_matching("none")).is_ok() {
             Ok(PaintServer::None)
         } else if let Ok(url) = parser.try(|i| i.expect_url()) {
@@ -91,27 +90,27 @@ mod tests {
 
     #[test]
     fn catches_invalid_syntax() {
-        assert!(PaintServer::parse_str("", ()).is_err());
-        assert!(PaintServer::parse_str("42", ()).is_err());
-        assert!(PaintServer::parse_str("invalid", ()).is_err());
+        assert!(PaintServer::parse_str("").is_err());
+        assert!(PaintServer::parse_str("42").is_err());
+        assert!(PaintServer::parse_str("invalid").is_err());
     }
 
     #[test]
     fn parses_none() {
-        assert_eq!(PaintServer::parse_str("none", ()), Ok(PaintServer::None));
+        assert_eq!(PaintServer::parse_str("none"), Ok(PaintServer::None));
     }
 
     #[test]
     fn parses_solid_color() {
         assert_eq!(
-            PaintServer::parse_str("rgb(255, 128, 64, 0.5)", ()),
+            PaintServer::parse_str("rgb(255, 128, 64, 0.5)"),
             Ok(PaintServer::SolidColor(cssparser::Color::RGBA(
                 cssparser::RGBA::new(255, 128, 64, 128)
             )))
         );
 
         assert_eq!(
-            PaintServer::parse_str("currentColor", ()),
+            PaintServer::parse_str("currentColor"),
             Ok(PaintServer::SolidColor(cssparser::Color::CurrentColor))
         );
     }
@@ -119,7 +118,7 @@ mod tests {
     #[test]
     fn parses_iri() {
         assert_eq!(
-            PaintServer::parse_str("url(#link)", ()),
+            PaintServer::parse_str("url(#link)"),
             Ok(PaintServer::Iri {
                 iri: Fragment::new(None, "link".to_string()),
                 alternate: None,
@@ -127,7 +126,7 @@ mod tests {
         );
 
         assert_eq!(
-            PaintServer::parse_str("url(foo#link) none", ()),
+            PaintServer::parse_str("url(foo#link) none"),
             Ok(PaintServer::Iri {
                 iri: Fragment::new(Some("foo".to_string()), "link".to_string()),
                 alternate: None,
@@ -135,7 +134,7 @@ mod tests {
         );
 
         assert_eq!(
-            PaintServer::parse_str("url(#link) #ff8040", ()),
+            PaintServer::parse_str("url(#link) #ff8040"),
             Ok(PaintServer::Iri {
                 iri: Fragment::new(None, "link".to_string()),
                 alternate: Some(cssparser::Color::RGBA(cssparser::RGBA::new(
@@ -145,7 +144,7 @@ mod tests {
         );
 
         assert_eq!(
-            PaintServer::parse_str("url(#link) rgb(255, 128, 64, 0.5)", ()),
+            PaintServer::parse_str("url(#link) rgb(255, 128, 64, 0.5)"),
             Ok(PaintServer::Iri {
                 iri: Fragment::new(None, "link".to_string()),
                 alternate: Some(cssparser::Color::RGBA(cssparser::RGBA::new(
@@ -155,13 +154,13 @@ mod tests {
         );
 
         assert_eq!(
-            PaintServer::parse_str("url(#link) currentColor", ()),
+            PaintServer::parse_str("url(#link) currentColor"),
             Ok(PaintServer::Iri {
                 iri: Fragment::new(None, "link".to_string()),
                 alternate: Some(cssparser::Color::CurrentColor),
             },)
         );
 
-        assert!(PaintServer::parse_str("url(#link) invalid", ()).is_err());
+        assert!(PaintServer::parse_str("url(#link) invalid").is_err());
     }
 }
diff --git a/rsvg_internals/src/parsers.rs b/rsvg_internals/src/parsers.rs
index 08327a57..adc4d249 100644
--- a/rsvg_internals/src/parsers.rs
+++ b/rsvg_internals/src/parsers.rs
@@ -25,16 +25,15 @@ impl<'a> From<BasicParseError<'a>> for ParseError {
 }
 
 pub trait Parse: Sized {
-    type Data;
     type Err;
 
-    fn parse(parser: &mut Parser<'_, '_>, data: Self::Data) -> Result<Self, Self::Err>;
+    fn parse(parser: &mut Parser<'_, '_>) -> Result<Self, Self::Err>;
 
-    fn parse_str(s: &str, data: Self::Data) -> Result<Self, Self::Err> {
+    fn parse_str(s: &str) -> Result<Self, Self::Err> {
         let mut input = ParserInput::new(s);
         let mut parser = Parser::new(&mut input);
 
-        Self::parse(&mut parser, data).and_then(|r| {
+        Self::parse(&mut parser).and_then(|r| {
             // FIXME: parser.expect_exhausted()?;
             Ok(r)
         })
@@ -68,57 +67,42 @@ pub fn finite_f32(n: f32) -> Result<f32, ValueErrorKind> {
 
 pub trait ParseValue<T: Parse<Err = ValueErrorKind>> {
     /// Parses a `value` string into a type `T`.
-    ///
-    /// Some value types need some extra `data` to be parsed.  This
-    /// corresponds to the `<T as Parse>::Data` associated type.  For
-    /// example, an `Length` has an associated `type Data =
-    /// LengthDir`, so to parse a length value, you could specify
-    /// `LengthDir::Horizontal` for `data`, for example.
-    fn parse(&self, value: &str, data: <T as Parse>::Data) -> Result<T, NodeError>;
+    fn parse(&self, value: &str) -> Result<T, NodeError>;
 
     /// Parses a `value` string into a type `T` with an optional validation function.
-    ///
-    /// Some value types need some extra `data` to be parsed.  This
-    /// corresponds to the `<T as Parse>::Data` associated type.  For
-    /// example, an `Length` has an associated `type Data =
-    /// LengthDir`, so to parse a length value, you could specify
-    /// `LengthDir::Horizontal` for `data`, for example.
     fn parse_and_validate<F: FnOnce(T) -> Result<T, ValueErrorKind>>(
         &self,
         value: &str,
-        data: <T as Parse>::Data,
         validate: F,
     ) -> Result<T, NodeError>;
 }
 
 impl<T: Parse<Err = ValueErrorKind>> ParseValue<T> for Attribute {
-    fn parse(&self, value: &str, data: <T as Parse>::Data) -> Result<T, NodeError> {
+    fn parse(&self, value: &str) -> Result<T, NodeError> {
         let mut input = ParserInput::new(value);
         let mut parser = Parser::new(&mut input);
 
-        T::parse(&mut parser, data).map_err(|e| NodeError::attribute_error(*self, e))
+        T::parse(&mut parser).map_err(|e| NodeError::attribute_error(*self, e))
     }
 
     fn parse_and_validate<F: FnOnce(T) -> Result<T, ValueErrorKind>>(
         &self,
         value: &str,
-        data: <T as Parse>::Data,
         validate: F,
     ) -> Result<T, NodeError> {
         let mut input = ParserInput::new(value);
         let mut parser = Parser::new(&mut input);
 
-        T::parse(&mut parser, data)
+        T::parse(&mut parser)
             .and_then(validate)
             .map_err(|e| NodeError::attribute_error(*self, e))
     }
 }
 
 impl Parse for f64 {
-    type Data = ();
     type Err = ValueErrorKind;
 
-    fn parse(parser: &mut Parser<'_, '_>, _: ()) -> Result<f64, ValueErrorKind> {
+    fn parse(parser: &mut Parser<'_, '_>) -> Result<f64, ValueErrorKind> {
         Ok(f64::from(parser.expect_finite_number().map_err(|_| {
             ValueErrorKind::Parse(ParseError::new("expected number"))
         })?))
diff --git a/rsvg_internals/src/pattern.rs b/rsvg_internals/src/pattern.rs
index 36eb84eb..becd7fd2 100644
--- a/rsvg_internals/src/pattern.rs
+++ b/rsvg_internals/src/pattern.rs
@@ -183,40 +183,34 @@ impl NodeTrait for NodePattern {
 
         for (attr, value) in pbag.iter() {
             match attr {
-                Attribute::PatternUnits => p.units = Some(attr.parse(value, ())?),
+                Attribute::PatternUnits => p.units = Some(attr.parse(value)?),
 
-                Attribute::PatternContentUnits => p.content_units = Some(attr.parse(value, ())?),
+                Attribute::PatternContentUnits => p.content_units = Some(attr.parse(value)?),
 
-                Attribute::ViewBox => p.vbox = Some(Some(attr.parse(value, ())?)),
+                Attribute::ViewBox => p.vbox = Some(Some(attr.parse(value)?)),
 
                 Attribute::PreserveAspectRatio => {
-                    p.preserve_aspect_ratio = Some(attr.parse(value, ())?)
+                    p.preserve_aspect_ratio = Some(attr.parse(value)?)
                 }
 
-                Attribute::PatternTransform => p.affine = Some(attr.parse(value, ())?),
+                Attribute::PatternTransform => p.affine = Some(attr.parse(value)?),
 
                 Attribute::XlinkHref => {
                     p.fallback = Some(Fragment::parse(value).attribute(Attribute::XlinkHref)?);
                 }
 
-                Attribute::X => p.x = Some(attr.parse(value, ())?),
+                Attribute::X => p.x = Some(attr.parse(value)?),
 
-                Attribute::Y => p.y = Some(attr.parse(value, ())?),
+                Attribute::Y => p.y = Some(attr.parse(value)?),
 
                 Attribute::Width => {
-                    p.width = Some(attr.parse_and_validate(
-                        value,
-                        (),
-                        LengthHorizontal::check_nonnegative,
-                    )?)
+                    p.width =
+                        Some(attr.parse_and_validate(value, LengthHorizontal::check_nonnegative)?)
                 }
 
                 Attribute::Height => {
-                    p.height = Some(attr.parse_and_validate(
-                        value,
-                        (),
-                        LengthVertical::check_nonnegative,
-                    )?)
+                    p.height =
+                        Some(attr.parse_and_validate(value, LengthVertical::check_nonnegative)?)
                 }
 
                 _ => (),
diff --git a/rsvg_internals/src/properties.rs b/rsvg_internals/src/properties.rs
index baa5c3dc..08b06548 100644
--- a/rsvg_internals/src/properties.rs
+++ b/rsvg_internals/src/properties.rs
@@ -269,203 +269,203 @@ impl SpecifiedValues {
             // please keep these sorted
             match attr {
                 Attribute::BaselineShift => {
-                    self.baseline_shift = parse_property(value, ())?;
+                    self.baseline_shift = parse_property(value)?;
                 }
 
                 Attribute::ClipPath => {
-                    self.clip_path = parse_property(value, ())?;
+                    self.clip_path = parse_property(value)?;
                 }
 
                 Attribute::ClipRule => {
-                    self.clip_rule = parse_property(value, ())?;
+                    self.clip_rule = parse_property(value)?;
                 }
 
                 Attribute::Color => {
-                    self.color = parse_property(value, ())?;
+                    self.color = parse_property(value)?;
                 }
 
                 Attribute::ColorInterpolationFilters => {
-                    self.color_interpolation_filters = parse_property(value, ())?;
+                    self.color_interpolation_filters = parse_property(value)?;
                 }
 
                 Attribute::Direction => {
-                    self.direction = parse_property(value, ())?;
+                    self.direction = parse_property(value)?;
                 }
 
                 Attribute::Display => {
-                    self.display = parse_property(value, ())?;
+                    self.display = parse_property(value)?;
                 }
 
                 Attribute::EnableBackground => {
-                    self.enable_background = parse_property(value, ())?;
+                    self.enable_background = parse_property(value)?;
                 }
 
                 Attribute::Fill => {
-                    self.fill = parse_property(value, ())?;
+                    self.fill = parse_property(value)?;
                 }
 
                 Attribute::FillOpacity => {
-                    self.fill_opacity = parse_property(value, ())?;
+                    self.fill_opacity = parse_property(value)?;
                 }
 
                 Attribute::FillRule => {
-                    self.fill_rule = parse_property(value, ())?;
+                    self.fill_rule = parse_property(value)?;
                 }
 
                 Attribute::Filter => {
-                    self.filter = parse_property(value, ())?;
+                    self.filter = parse_property(value)?;
                 }
 
                 Attribute::FloodColor => {
-                    self.flood_color = parse_property(value, ())?;
+                    self.flood_color = parse_property(value)?;
                 }
 
                 Attribute::FloodOpacity => {
-                    self.flood_opacity = parse_property(value, ())?;
+                    self.flood_opacity = parse_property(value)?;
                 }
 
                 Attribute::FontFamily => {
-                    self.font_family = parse_property(value, ())?;
+                    self.font_family = parse_property(value)?;
                 }
 
                 Attribute::FontSize => {
-                    self.font_size = parse_property(value, ())?;
+                    self.font_size = parse_property(value)?;
                 }
 
                 Attribute::FontStretch => {
-                    self.font_stretch = parse_property(value, ())?;
+                    self.font_stretch = parse_property(value)?;
                 }
 
                 Attribute::FontStyle => {
-                    self.font_style = parse_property(value, ())?;
+                    self.font_style = parse_property(value)?;
                 }
 
                 Attribute::FontVariant => {
-                    self.font_variant = parse_property(value, ())?;
+                    self.font_variant = parse_property(value)?;
                 }
 
                 Attribute::FontWeight => {
-                    self.font_weight = parse_property(value, ())?;
+                    self.font_weight = parse_property(value)?;
                 }
 
                 Attribute::LetterSpacing => {
-                    self.letter_spacing = parse_property(value, ())?;
+                    self.letter_spacing = parse_property(value)?;
                 }
 
                 Attribute::LightingColor => {
-                    self.lighting_color = parse_property(value, ())?;
+                    self.lighting_color = parse_property(value)?;
                 }
 
                 Attribute::MarkerEnd => {
-                    self.marker_end = parse_property(value, ())?;
+                    self.marker_end = parse_property(value)?;
                 }
 
                 Attribute::MarkerMid => {
-                    self.marker_mid = parse_property(value, ())?;
+                    self.marker_mid = parse_property(value)?;
                 }
 
                 Attribute::MarkerStart => {
-                    self.marker_start = parse_property(value, ())?;
+                    self.marker_start = parse_property(value)?;
                 }
 
                 Attribute::Marker if accept_shorthands => {
-                    self.marker_end = parse_property(value, ())?;
-                    self.marker_mid = parse_property(value, ())?;
-                    self.marker_start = parse_property(value, ())?;
+                    self.marker_end = parse_property(value)?;
+                    self.marker_mid = parse_property(value)?;
+                    self.marker_start = parse_property(value)?;
                 }
 
                 Attribute::Mask => {
-                    self.mask = parse_property(value, ())?;
+                    self.mask = parse_property(value)?;
                 }
 
                 Attribute::Opacity => {
-                    self.opacity = parse_property(value, ())?;
+                    self.opacity = parse_property(value)?;
                 }
 
                 Attribute::Overflow => {
-                    self.overflow = parse_property(value, ())?;
+                    self.overflow = parse_property(value)?;
                 }
 
                 Attribute::ShapeRendering => {
-                    self.shape_rendering = parse_property(value, ())?;
+                    self.shape_rendering = parse_property(value)?;
                 }
 
                 Attribute::StopColor => {
-                    self.stop_color = parse_property(value, ())?;
+                    self.stop_color = parse_property(value)?;
                 }
 
                 Attribute::StopOpacity => {
-                    self.stop_opacity = parse_property(value, ())?;
+                    self.stop_opacity = parse_property(value)?;
                 }
 
                 Attribute::Stroke => {
-                    self.stroke = parse_property(value, ())?;
+                    self.stroke = parse_property(value)?;
                 }
 
                 Attribute::StrokeDasharray => {
-                    self.stroke_dasharray = parse_property(value, ())?;
+                    self.stroke_dasharray = parse_property(value)?;
                 }
 
                 Attribute::StrokeDashoffset => {
-                    self.stroke_dashoffset = parse_property(value, ())?;
+                    self.stroke_dashoffset = parse_property(value)?;
                 }
 
                 Attribute::StrokeLinecap => {
-                    self.stroke_line_cap = parse_property(value, ())?;
+                    self.stroke_line_cap = parse_property(value)?;
                 }
 
                 Attribute::StrokeLinejoin => {
-                    self.stroke_line_join = parse_property(value, ())?;
+                    self.stroke_line_join = parse_property(value)?;
                 }
 
                 Attribute::StrokeOpacity => {
-                    self.stroke_opacity = parse_property(value, ())?;
+                    self.stroke_opacity = parse_property(value)?;
                 }
 
                 Attribute::StrokeMiterlimit => {
-                    self.stroke_miterlimit = parse_property(value, ())?;
+                    self.stroke_miterlimit = parse_property(value)?;
                 }
 
                 Attribute::StrokeWidth => {
-                    self.stroke_width = parse_property(value, ())?;
+                    self.stroke_width = parse_property(value)?;
                 }
 
                 Attribute::TextAnchor => {
-                    self.text_anchor = parse_property(value, ())?;
+                    self.text_anchor = parse_property(value)?;
                 }
 
                 Attribute::TextDecoration => {
-                    self.text_decoration = parse_property(value, ())?;
+                    self.text_decoration = parse_property(value)?;
                 }
 
                 Attribute::TextRendering => {
-                    self.text_rendering = parse_property(value, ())?;
+                    self.text_rendering = parse_property(value)?;
                 }
 
                 Attribute::UnicodeBidi => {
-                    self.unicode_bidi = parse_property(value, ())?;
+                    self.unicode_bidi = parse_property(value)?;
                 }
 
                 Attribute::Visibility => {
-                    self.visibility = parse_property(value, ())?;
+                    self.visibility = parse_property(value)?;
                 }
 
                 Attribute::WritingMode => {
-                    self.writing_mode = parse_property(value, ())?;
+                    self.writing_mode = parse_property(value)?;
                 }
 
                 Attribute::XmlLang => {
                     // xml:lang is not a property; it is a non-presentation attribute and as such
                     // cannot have the "inherit" value.  So, we don't call parse_property() for it,
                     // but rather call its parser directly.
-                    self.xml_lang = SpecifiedValue::Specified(XmlLang::parse_str(value, ())?);
+                    self.xml_lang = SpecifiedValue::Specified(XmlLang::parse_str(value)?);
                 }
 
                 Attribute::XmlSpace => {
                     // xml:space is not a property; it is a non-presentation attribute and as such
                     // cannot have the "inherit" value.  So, we don't call parse_property() for it,
                     // but rather call its parser directly.
-                    self.xml_space = SpecifiedValue::Specified(XmlSpace::parse_str(value, ())?);
+                    self.xml_space = SpecifiedValue::Specified(XmlSpace::parse_str(value)?);
                 }
 
                 _ => {
@@ -575,17 +575,14 @@ impl SpecifiedValues {
 //
 // If the `value` is `inherit`, returns `Ok(None)`; otherwise returns
 // `Ok(Some(T))`.
-fn parse_property<T>(
-    value: &str,
-    data: <T as Parse>::Data,
-) -> Result<SpecifiedValue<T>, <T as Parse>::Err>
+fn parse_property<T>(value: &str) -> Result<SpecifiedValue<T>, <T as Parse>::Err>
 where
     T: Property<ComputedValues> + Clone + Default + Parse,
 {
     if value.trim() == "inherit" {
         Ok(SpecifiedValue::Inherit)
     } else {
-        Parse::parse_str(value, data).map(SpecifiedValue::Specified)
+        Parse::parse_str(value).map(SpecifiedValue::Specified)
     }
 }
 
@@ -593,7 +590,7 @@ where
 make_property!(
     ComputedValues,
     BaselineShift,
-    default: LengthBoth::parse_str("0.0", ()).unwrap(),
+    default: LengthBoth::parse_str("0.0").unwrap(),
     newtype: LengthBoth,
     property_impl: {
         impl Property<ComputedValues> for BaselineShift {
@@ -618,12 +615,11 @@ make_property!(
     },
     parse_impl: {
         impl Parse for BaselineShift {
-            type Data = ();
             type Err = ValueErrorKind;
 
             // These values come from Inkscape's SP_CSS_BASELINE_SHIFT_(SUB/SUPER/BASELINE);
             // see sp_style_merge_baseline_shift_from_parent()
-            fn parse(parser: &mut Parser<'_, '_>, _: Self::Data) -> Result<BaselineShift, 
::error::ValueErrorKind> {
+            fn parse(parser: &mut Parser<'_, '_>) -> Result<BaselineShift, ::error::ValueErrorKind> {
                 let parser_state = parser.state();
 
                 {
@@ -665,7 +661,6 @@ make_property!(
     default: IRI::None,
     inherits_automatically: false,
     newtype_parse: IRI,
-    parse_data_type: ()
 );
 
 // https://www.w3.org/TR/SVG/masking.html#ClipRuleProperty
@@ -693,7 +688,6 @@ make_property!(
     default: cssparser::RGBA::new(0, 0, 0, 0xff),
     inherits_automatically: true,
     newtype_parse: cssparser::RGBA,
-    parse_data_type: ()
 );
 
 // https://www.w3.org/TR/SVG11/painting.html#ColorInterpolationProperty
@@ -764,10 +758,9 @@ make_property!(
 make_property!(
     ComputedValues,
     Fill,
-    default: PaintServer::parse_str("#000", ()).unwrap(),
+    default: PaintServer::parse_str("#000").unwrap(),
     inherits_automatically: true,
     newtype_parse: PaintServer,
-    parse_data_type: ()
 );
 
 // https://www.w3.org/TR/SVG/painting.html#FillOpacityProperty
@@ -777,7 +770,6 @@ make_property!(
     default: UnitInterval(1.0),
     inherits_automatically: true,
     newtype_parse: UnitInterval,
-    parse_data_type: ()
 );
 
 // https://www.w3.org/TR/SVG/painting.html#FillRuleProperty
@@ -799,7 +791,6 @@ make_property!(
     default: IRI::None,
     inherits_automatically: false,
     newtype_parse: IRI,
-    parse_data_type: ()
 );
 
 // https://www.w3.org/TR/SVG/filters.html#FloodColorProperty
@@ -809,7 +800,6 @@ make_property!(
     default: cssparser::Color::RGBA(cssparser::RGBA::new(0, 0, 0, 0)),
     inherits_automatically: false,
     newtype_parse: cssparser::Color,
-    parse_data_type: ()
 );
 
 // https://www.w3.org/TR/SVG/filters.html#FloodOpacityProperty
@@ -819,7 +809,6 @@ make_property!(
     default: UnitInterval(1.0),
     inherits_automatically: false,
     newtype_parse: UnitInterval,
-    parse_data_type: ()
 );
 
 // https://www.w3.org/TR/SVG/text.html#FontFamilyProperty
@@ -829,16 +818,14 @@ make_property!(
     default: SingleFontFamily("Times New Roman".to_string()),
     inherits_automatically: true,
     newtype_parse: SingleFontFamily,
-    parse_data_type: ()
 );
 
 // https://www.w3.org/TR/SVG/text.html#FontSizeProperty
 make_property!(
     ComputedValues,
     FontSize,
-    default: FontSizeSpec::Value(LengthBoth::parse_str("12.0", ()).unwrap()),
+    default: FontSizeSpec::Value(LengthBoth::parse_str("12.0").unwrap()),
     newtype_parse: FontSizeSpec,
-    parse_data_type: (),
     property_impl: {
         impl Property<ComputedValues> for FontSize {
             fn inherits_automatically() -> bool {
@@ -905,7 +892,6 @@ make_property!(
     default: FontWeightSpec::Normal,
     inherits_automatically: true,
     newtype_parse: FontWeightSpec,
-    parse_data_type: ()
 );
 
 // https://www.w3.org/TR/SVG/text.html#LetterSpacingProperty
@@ -914,7 +900,6 @@ make_property!(
     LetterSpacing,
     default: LetterSpacingSpec::Normal,
     newtype_parse: LetterSpacingSpec,
-    parse_data_type: (),
     property_impl: {
         impl Property<ComputedValues> for LetterSpacing {
             fn inherits_automatically() -> bool {
@@ -935,7 +920,6 @@ make_property!(
     default: cssparser::Color::RGBA(cssparser::RGBA::new(255, 255, 255, 255)),
     inherits_automatically: false,
     newtype_parse: cssparser::Color,
-    parse_data_type: ()
 );
 
 // https://www.w3.org/TR/SVG/painting.html#MarkerEndProperty
@@ -945,7 +929,6 @@ make_property!(
     default: IRI::None,
     inherits_automatically: true,
     newtype_parse: IRI,
-    parse_data_type: ()
 );
 
 // https://www.w3.org/TR/SVG/painting.html#MarkerMidProperty
@@ -955,7 +938,6 @@ make_property!(
     default: IRI::None,
     inherits_automatically: true,
     newtype_parse: IRI,
-    parse_data_type: ()
 );
 
 // https://www.w3.org/TR/SVG/painting.html#MarkerStartProperty
@@ -965,7 +947,6 @@ make_property!(
     default: IRI::None,
     inherits_automatically: true,
     newtype_parse: IRI,
-    parse_data_type: ()
 );
 
 // https://www.w3.org/TR/SVG/masking.html#MaskProperty
@@ -975,7 +956,6 @@ make_property!(
     default: IRI::None,
     inherits_automatically: false,
     newtype_parse: IRI,
-    parse_data_type: ()
 );
 
 // https://www.w3.org/TR/SVG/masking.html#OpacityProperty
@@ -985,7 +965,6 @@ make_property!(
     default: UnitInterval(1.0),
     inherits_automatically: false,
     newtype_parse: UnitInterval,
-    parse_data_type: ()
 );
 
 // https://www.w3.org/TR/SVG/masking.html#OverflowProperty
@@ -1023,7 +1002,6 @@ make_property!(
     default: cssparser::Color::RGBA(cssparser::RGBA::new(0, 0, 0, 255)),
     inherits_automatically: false,
     newtype_parse: cssparser::Color,
-    parse_data_type: ()
 );
 
 // https://www.w3.org/TR/SVG/pservers.html#StopOpacityProperty
@@ -1033,7 +1011,6 @@ make_property!(
     default: UnitInterval(1.0),
     inherits_automatically: false,
     newtype_parse: UnitInterval,
-    parse_data_type: ()
 );
 
 // https://www.w3.org/TR/SVG/painting.html#StrokeProperty
@@ -1043,7 +1020,6 @@ make_property!(
     default: PaintServer::None,
     inherits_automatically: true,
     newtype_parse: PaintServer,
-    parse_data_type: ()
 );
 
 // https://www.w3.org/TR/SVG/painting.html#StrokeDasharrayProperty
@@ -1053,7 +1029,6 @@ make_property!(
     default: Dasharray::default(),
     inherits_automatically: true,
     newtype_parse: Dasharray,
-    parse_data_type: ()
 );
 
 // https://www.w3.org/TR/SVG/painting.html#StrokeDashoffsetProperty
@@ -1063,7 +1038,6 @@ make_property!(
     default: LengthBoth::default(),
     inherits_automatically: true,
     newtype_parse: LengthBoth,
-    parse_data_type: ()
 );
 
 // https://www.w3.org/TR/SVG/painting.html#StrokeLinecapProperty
@@ -1099,7 +1073,6 @@ make_property!(
     default: 4f64,
     inherits_automatically: true,
     newtype_parse: f64,
-    parse_data_type: ()
 );
 
 // https://www.w3.org/TR/SVG/painting.html#StrokeOpacityProperty
@@ -1109,17 +1082,15 @@ make_property!(
     default: UnitInterval(1.0),
     inherits_automatically: true,
     newtype_parse: UnitInterval,
-    parse_data_type: ()
 );
 
 // https://www.w3.org/TR/SVG/painting.html#StrokeWidthProperty
 make_property!(
     ComputedValues,
     StrokeWidth,
-    default: LengthBoth::parse_str("1.0", ()).unwrap(),
+    default: LengthBoth::parse_str("1.0").unwrap(),
     inherits_automatically: true,
     newtype_parse: LengthBoth,
-    parse_data_type: ()
 );
 
 // https://www.w3.org/TR/SVG/text.html#TextAnchorProperty
@@ -1149,10 +1120,9 @@ make_property!(
 
     parse_impl: {
         impl Parse for TextDecoration {
-            type Data = ();
             type Err = ValueErrorKind;
 
-            fn parse(parser: &mut Parser<'_, '_>, _: Self::Data) -> Result<TextDecoration, ValueErrorKind> {
+            fn parse(parser: &mut Parser<'_, '_>) -> Result<TextDecoration, ValueErrorKind> {
                 let mut overline = false;
                 let mut underline = false;
                 let mut strike = false;
@@ -1188,7 +1158,7 @@ make_property!(
 #[test]
 fn parses_text_decoration() {
     assert_eq!(
-        TextDecoration::parse_str("none", ()).unwrap(),
+        TextDecoration::parse_str("none").unwrap(),
         TextDecoration {
             overline: false,
             underline: false,
@@ -1197,7 +1167,7 @@ fn parses_text_decoration() {
     );
 
     assert_eq!(
-        TextDecoration::parse_str("overline", ()).unwrap(),
+        TextDecoration::parse_str("overline").unwrap(),
         TextDecoration {
             overline: true,
             underline: false,
@@ -1206,7 +1176,7 @@ fn parses_text_decoration() {
     );
 
     assert_eq!(
-        TextDecoration::parse_str("underline", ()).unwrap(),
+        TextDecoration::parse_str("underline").unwrap(),
         TextDecoration {
             overline: false,
             underline: true,
@@ -1215,7 +1185,7 @@ fn parses_text_decoration() {
     );
 
     assert_eq!(
-        TextDecoration::parse_str("line-through", ()).unwrap(),
+        TextDecoration::parse_str("line-through").unwrap(),
         TextDecoration {
             overline: false,
             underline: false,
@@ -1224,7 +1194,7 @@ fn parses_text_decoration() {
     );
 
     assert_eq!(
-        TextDecoration::parse_str("underline overline", ()).unwrap(),
+        TextDecoration::parse_str("underline overline").unwrap(),
         TextDecoration {
             overline: true,
             underline: true,
@@ -1232,7 +1202,7 @@ fn parses_text_decoration() {
         }
     );
 
-    assert!(TextDecoration::parse_str("airline", ()).is_err())
+    assert!(TextDecoration::parse_str("airline").is_err())
 }
 
 // https://www.w3.org/TR/SVG/painting.html#TextRenderingProperty
@@ -1308,29 +1278,26 @@ make_property!(
     newtype: String,
     parse_impl: {
         impl Parse for XmlLang {
-            type Data = ();
             type Err = ValueErrorKind;
 
             fn parse(
                 parser: &mut Parser<'_, '_>,
-                _: Self::Data
             ) -> Result<XmlLang, ValueErrorKind> {
                 Ok(XmlLang(parser.expect_ident()?.to_string()))
             }
         }
     },
-    parse_data_type: ()
 );
 
 #[cfg(test)]
 #[test]
 fn parses_xml_lang() {
     assert_eq!(
-        XmlLang::parse_str("es-MX", ()).unwrap(),
+        XmlLang::parse_str("es-MX").unwrap(),
         XmlLang("es-MX".to_string())
     );
 
-    assert!(XmlLang::parse_str("", ()).is_err());
+    assert!(XmlLang::parse_str("").is_err());
 }
 
 make_property!(
diff --git a/rsvg_internals/src/property_macros.rs b/rsvg_internals/src/property_macros.rs
index 86cce6d3..0bed5881 100644
--- a/rsvg_internals/src/property_macros.rs
+++ b/rsvg_internals/src/property_macros.rs
@@ -44,10 +44,9 @@ macro_rules! make_property {
         impl_property!($computed_values_type, $name, $inherits_automatically);
 
         impl ::parsers::Parse for $name {
-            type Data = ();
             type Err = ::error::ValueErrorKind;
 
-            fn parse(parser: &mut ::cssparser::Parser<'_, '_>, _: Self::Data) -> Result<$name, 
::error::ValueErrorKind> {
+            fn parse(parser: &mut ::cssparser::Parser<'_, '_>) -> Result<$name, ::error::ValueErrorKind> {
                 let loc = parser.current_source_location();
 
                 parser
@@ -76,7 +75,6 @@ macro_rules! make_property {
      default: $default: expr,
      inherits_automatically: $inherits_automatically: expr,
      newtype_parse: $type: ty,
-     parse_data_type: $parse_data_type: ty
     ) => {
         #[derive(Debug, Clone, PartialEq)]
         pub struct $name(pub $type);
@@ -94,11 +92,10 @@ macro_rules! make_property {
         }
 
         impl ::parsers::Parse for $name {
-            type Data = $parse_data_type;
             type Err = ::error::ValueErrorKind;
 
-            fn parse(parser: &mut ::cssparser::Parser<'_, '_>, d: Self::Data) -> Result<$name, 
::error::ValueErrorKind> {
-                Ok($name(<$type as ::parsers::Parse>::parse(parser, d)?))
+            fn parse(parser: &mut ::cssparser::Parser<'_, '_>) -> Result<$name, ::error::ValueErrorKind> {
+                Ok($name(<$type as ::parsers::Parse>::parse(parser)?))
             }
         }
     };
@@ -107,7 +104,6 @@ macro_rules! make_property {
      $name: ident,
      default: $default: expr,
      newtype_parse: $type: ty,
-     parse_data_type: $parse_data_type: ty,
      property_impl: { $prop: item }
     ) => {
         #[derive(Debug, Clone, PartialEq)]
@@ -118,11 +114,10 @@ macro_rules! make_property {
         $prop
 
         impl ::parsers::Parse for $name {
-            type Data = $parse_data_type;
             type Err = ::error::ValueErrorKind;
 
-            fn parse(parser: &mut ::cssparser::Parser<'_, '_>, d: Self::Data) -> Result<$name, 
::error::ValueErrorKind> {
-                Ok($name(<$type as ::parsers::Parse>::parse(parser, d)?))
+            fn parse(parser: &mut ::cssparser::Parser<'_, '_>) -> Result<$name, ::error::ValueErrorKind> {
+                Ok($name(<$type as ::parsers::Parse>::parse(parser)?))
             }
         }
     };
@@ -150,7 +145,6 @@ macro_rules! make_property {
      inherits_automatically: $inherits_automatically: expr,
      newtype: $type: ty,
      parse_impl: { $parse: item },
-     parse_data_type: $parse_data_type: ty
     ) => {
         #[derive(Debug, Clone, PartialEq)]
         pub struct $name(pub $type);
@@ -228,8 +222,8 @@ mod tests {
 
         assert_eq!(<Foo as Default>::default(), Foo::Def);
         assert_eq!(<Foo as Property<()>>::inherits_automatically(), true);
-        assert!(<Foo as Parse>::parse_str("blargh", ()).is_err());
-        assert_eq!(<Foo as Parse>::parse_str("bar", ()), Ok(Foo::Bar));
+        assert!(<Foo as Parse>::parse_str("blargh").is_err());
+        assert_eq!(<Foo as Parse>::parse_str("bar"), Ok(Foo::Bar));
     }
 
     #[test]
@@ -239,7 +233,6 @@ mod tests {
             AddColor,
             default: RGBA::new(1, 1, 1, 1),
             newtype_parse: RGBA,
-            parse_data_type: (),
             property_impl: {
                 impl Property<RGBA> for AddColor {
                     fn inherits_automatically() -> bool {
@@ -259,7 +252,7 @@ mod tests {
         }
 
         let color = RGBA::new(1, 1, 1, 1);
-        let a = <AddColor as Parse>::parse_str("#02030405", ()).unwrap();
+        let a = <AddColor as Parse>::parse_str("#02030405").unwrap();
         let b = a.compute(&color);
 
         assert_eq!(b, AddColor(RGBA::new(3, 4, 5, 6)));
diff --git a/rsvg_internals/src/shapes.rs b/rsvg_internals/src/shapes.rs
index 85161788..c0274214 100644
--- a/rsvg_internals/src/shapes.rs
+++ b/rsvg_internals/src/shapes.rs
@@ -184,10 +184,9 @@ impl Deref for Points {
 // Parse a list-of-points as for polyline and polygon elements
 // https://www.w3.org/TR/SVG/shapes.html#PointsBNF
 impl Parse for Points {
-    type Data = ();
     type Err = ValueErrorKind;
 
-    fn parse(parser: &mut Parser<'_, '_>, _: ()) -> Result<Points, ValueErrorKind> {
+    fn parse(parser: &mut Parser<'_, '_>) -> Result<Points, ValueErrorKind> {
         let mut v = Vec::new();
 
         loop {
@@ -237,7 +236,7 @@ impl NodeTrait for NodePoly {
         for (attr, value) in pbag.iter() {
             // support for svg < 1.0 which used verts
             if attr == Attribute::Points || attr == Attribute::Verts {
-                *self.points.borrow_mut() = attr.parse(value.trim(), ()).map(Some)?;
+                *self.points.borrow_mut() = attr.parse(value.trim()).map(Some)?;
             }
         }
 
@@ -297,10 +296,10 @@ impl NodeTrait for NodeLine {
     fn set_atts(&self, _: &RsvgNode, pbag: &PropertyBag<'_>) -> NodeResult {
         for (attr, value) in pbag.iter() {
             match attr {
-                Attribute::X1 => self.x1.set(attr.parse(value, ())?),
-                Attribute::Y1 => self.y1.set(attr.parse(value, ())?),
-                Attribute::X2 => self.x2.set(attr.parse(value, ())?),
-                Attribute::Y2 => self.y2.set(attr.parse(value, ())?),
+                Attribute::X1 => self.x1.set(attr.parse(value)?),
+                Attribute::Y1 => self.y1.set(attr.parse(value)?),
+                Attribute::X2 => self.x2.set(attr.parse(value)?),
+                Attribute::Y2 => self.y2.set(attr.parse(value)?),
                 _ => (),
             }
         }
@@ -363,24 +362,20 @@ impl NodeTrait for NodeRect {
     fn set_atts(&self, _: &RsvgNode, pbag: &PropertyBag<'_>) -> NodeResult {
         for (attr, value) in pbag.iter() {
             match attr {
-                Attribute::X => self.x.set(attr.parse(value, ())?),
-                Attribute::Y => self.y.set(attr.parse(value, ())?),
-                Attribute::Width => self.w.set(attr.parse_and_validate(
-                    value,
-                    (),
-                    LengthHorizontal::check_nonnegative,
-                )?),
-                Attribute::Height => self.h.set(attr.parse_and_validate(
-                    value,
-                    (),
-                    LengthVertical::check_nonnegative,
-                )?),
+                Attribute::X => self.x.set(attr.parse(value)?),
+                Attribute::Y => self.y.set(attr.parse(value)?),
+                Attribute::Width => self
+                    .w
+                    .set(attr.parse_and_validate(value, LengthHorizontal::check_nonnegative)?),
+                Attribute::Height => self
+                    .h
+                    .set(attr.parse_and_validate(value, LengthVertical::check_nonnegative)?),
                 Attribute::Rx => self.rx.set(
-                    attr.parse_and_validate(value, (), LengthHorizontal::check_nonnegative)
+                    attr.parse_and_validate(value, LengthHorizontal::check_nonnegative)
                         .map(Some)?,
                 ),
                 Attribute::Ry => self.ry.set(
-                    attr.parse_and_validate(value, (), LengthVertical::check_nonnegative)
+                    attr.parse_and_validate(value, LengthVertical::check_nonnegative)
                         .map(Some)?,
                 ),
 
@@ -559,12 +554,11 @@ impl NodeTrait for NodeCircle {
     fn set_atts(&self, _: &RsvgNode, pbag: &PropertyBag<'_>) -> NodeResult {
         for (attr, value) in pbag.iter() {
             match attr {
-                Attribute::Cx => self.cx.set(attr.parse(value, ())?),
-                Attribute::Cy => self.cy.set(attr.parse(value, ())?),
-                Attribute::R => {
-                    self.r
-                        .set(attr.parse_and_validate(value, (), LengthBoth::check_nonnegative)?)
-                }
+                Attribute::Cx => self.cx.set(attr.parse(value)?),
+                Attribute::Cy => self.cy.set(attr.parse(value)?),
+                Attribute::R => self
+                    .r
+                    .set(attr.parse_and_validate(value, LengthBoth::check_nonnegative)?),
 
                 _ => (),
             }
@@ -614,18 +608,14 @@ impl NodeTrait for NodeEllipse {
     fn set_atts(&self, _: &RsvgNode, pbag: &PropertyBag<'_>) -> NodeResult {
         for (attr, value) in pbag.iter() {
             match attr {
-                Attribute::Cx => self.cx.set(attr.parse(value, ())?),
-                Attribute::Cy => self.cy.set(attr.parse(value, ())?),
-                Attribute::Rx => self.rx.set(attr.parse_and_validate(
-                    value,
-                    (),
-                    LengthHorizontal::check_nonnegative,
-                )?),
-                Attribute::Ry => self.ry.set(attr.parse_and_validate(
-                    value,
-                    (),
-                    LengthVertical::check_nonnegative,
-                )?),
+                Attribute::Cx => self.cx.set(attr.parse(value)?),
+                Attribute::Cy => self.cy.set(attr.parse(value)?),
+                Attribute::Rx => self
+                    .rx
+                    .set(attr.parse_and_validate(value, LengthHorizontal::check_nonnegative)?),
+                Attribute::Ry => self
+                    .ry
+                    .set(attr.parse_and_validate(value, LengthVertical::check_nonnegative)?),
 
                 _ => (),
             }
@@ -660,32 +650,32 @@ mod tests {
 
     #[test]
     fn parses_points() {
-        assert_eq!(Points::parse_str(" 1 2 ", ()), Ok(Points(vec![(1.0, 2.0)])));
+        assert_eq!(Points::parse_str(" 1 2 "), Ok(Points(vec![(1.0, 2.0)])));
         assert_eq!(
-            Points::parse_str("1 2 3 4", ()),
+            Points::parse_str("1 2 3 4"),
             Ok(Points(vec![(1.0, 2.0), (3.0, 4.0)]))
         );
         assert_eq!(
-            Points::parse_str("1,2,3,4", ()),
+            Points::parse_str("1,2,3,4"),
             Ok(Points(vec![(1.0, 2.0), (3.0, 4.0)]))
         );
         assert_eq!(
-            Points::parse_str("1,2 3,4", ()),
+            Points::parse_str("1,2 3,4"),
             Ok(Points(vec![(1.0, 2.0), (3.0, 4.0)]))
         );
         assert_eq!(
-            Points::parse_str("1,2 -3,4", ()),
+            Points::parse_str("1,2 -3,4"),
             Ok(Points(vec![(1.0, 2.0), (-3.0, 4.0)]))
         );
         assert_eq!(
-            Points::parse_str("1,2,-3,4", ()),
+            Points::parse_str("1,2,-3,4"),
             Ok(Points(vec![(1.0, 2.0), (-3.0, 4.0)]))
         );
     }
 
     #[test]
     fn errors_on_invalid_points() {
-        assert!(Points::parse_str("-1-2-3-4", ()).is_err());
-        assert!(Points::parse_str("1 2-3,-4", ()).is_err());
+        assert!(Points::parse_str("-1-2-3-4").is_err());
+        assert!(Points::parse_str("1 2-3,-4").is_err());
     }
 }
diff --git a/rsvg_internals/src/stop.rs b/rsvg_internals/src/stop.rs
index 158e2e50..af9d3398 100644
--- a/rsvg_internals/src/stop.rs
+++ b/rsvg_internals/src/stop.rs
@@ -39,7 +39,7 @@ impl NodeTrait for NodeStop {
             match attr {
                 Attribute::Offset => {
                     self.offset.set(
-                        attr.parse_and_validate(value, (), validate_offset)
+                        attr.parse_and_validate(value, validate_offset)
                             .map(|l| UnitInterval::clamp(l.length()))?,
                     );
                 }
diff --git a/rsvg_internals/src/structure.rs b/rsvg_internals/src/structure.rs
index 641be301..04fb6e3b 100644
--- a/rsvg_internals/src/structure.rs
+++ b/rsvg_internals/src/structure.rs
@@ -109,10 +109,10 @@ impl NodeSvg {
     pub fn new() -> NodeSvg {
         NodeSvg {
             preserve_aspect_ratio: Cell::new(AspectRatio::default()),
-            x: Cell::new(LengthHorizontal::parse_str("0", ()).unwrap()),
-            y: Cell::new(LengthVertical::parse_str("0", ()).unwrap()),
-            w: Cell::new(LengthHorizontal::parse_str("100%", ()).unwrap()),
-            h: Cell::new(LengthVertical::parse_str("100%", ()).unwrap()),
+            x: Cell::new(LengthHorizontal::parse_str("0").unwrap()),
+            y: Cell::new(LengthVertical::parse_str("0").unwrap()),
+            w: Cell::new(LengthHorizontal::parse_str("100%").unwrap()),
+            h: Cell::new(LengthVertical::parse_str("100%").unwrap()),
             vbox: Cell::new(None),
             pbag: RefCell::new(None),
         }
@@ -155,34 +155,30 @@ impl NodeTrait for NodeSvg {
         for (attr, value) in pbag.iter() {
             match attr {
                 Attribute::PreserveAspectRatio => {
-                    self.preserve_aspect_ratio.set(attr.parse(value, ())?)
+                    self.preserve_aspect_ratio.set(attr.parse(value)?)
                 }
 
                 Attribute::X => {
                     if is_inner_svg {
-                        self.x.set(attr.parse(value, ())?);
+                        self.x.set(attr.parse(value)?);
                     }
                 }
 
                 Attribute::Y => {
                     if is_inner_svg {
-                        self.y.set(attr.parse(value, ())?);
+                        self.y.set(attr.parse(value)?);
                     }
                 }
 
-                Attribute::Width => self.w.set(attr.parse_and_validate(
-                    value,
-                    (),
-                    LengthHorizontal::check_nonnegative,
-                )?),
+                Attribute::Width => self
+                    .w
+                    .set(attr.parse_and_validate(value, LengthHorizontal::check_nonnegative)?),
 
-                Attribute::Height => self.h.set(attr.parse_and_validate(
-                    value,
-                    (),
-                    LengthVertical::check_nonnegative,
-                )?),
+                Attribute::Height => self
+                    .h
+                    .set(attr.parse_and_validate(value, LengthVertical::check_nonnegative)?),
 
-                Attribute::ViewBox => self.vbox.set(attr.parse(value, ()).map(Some)?),
+                Attribute::ViewBox => self.vbox.set(attr.parse(value).map(Some)?),
 
                 _ => (),
             }
@@ -264,15 +260,15 @@ impl NodeTrait for NodeUse {
                         Some(Fragment::parse(value).attribute(Attribute::XlinkHref)?)
                 }
 
-                Attribute::X => self.x.set(attr.parse(value, ())?),
-                Attribute::Y => self.y.set(attr.parse(value, ())?),
+                Attribute::X => self.x.set(attr.parse(value)?),
+                Attribute::Y => self.y.set(attr.parse(value)?),
 
                 Attribute::Width => self.w.set(
-                    attr.parse_and_validate(value, (), LengthHorizontal::check_nonnegative)
+                    attr.parse_and_validate(value, LengthHorizontal::check_nonnegative)
                         .map(Some)?,
                 ),
                 Attribute::Height => self.h.set(
-                    attr.parse_and_validate(value, (), LengthVertical::check_nonnegative)
+                    attr.parse_and_validate(value, LengthVertical::check_nonnegative)
                         .map(Some)?,
                 ),
 
@@ -334,12 +330,12 @@ impl NodeTrait for NodeUse {
         let nw = self
             .w
             .get()
-            .unwrap_or_else(|| LengthHorizontal::parse_str("100%", ()).unwrap())
+            .unwrap_or_else(|| LengthHorizontal::parse_str("100%").unwrap())
             .normalize(values, &params);
         let nh = self
             .h
             .get()
-            .unwrap_or_else(|| LengthVertical::parse_str("100%", ()).unwrap())
+            .unwrap_or_else(|| LengthVertical::parse_str("100%").unwrap())
             .normalize(values, &params);
 
         // width or height set to 0 disables rendering of the element
@@ -415,10 +411,10 @@ impl NodeTrait for NodeSymbol {
         for (attr, value) in pbag.iter() {
             match attr {
                 Attribute::PreserveAspectRatio => {
-                    self.preserve_aspect_ratio.set(attr.parse(value, ())?)
+                    self.preserve_aspect_ratio.set(attr.parse(value)?)
                 }
 
-                Attribute::ViewBox => self.vbox.set(attr.parse(value, ()).map(Some)?),
+                Attribute::ViewBox => self.vbox.set(attr.parse(value).map(Some)?),
 
                 _ => (),
             }
diff --git a/rsvg_internals/src/text.rs b/rsvg_internals/src/text.rs
index ab729916..a34be604 100644
--- a/rsvg_internals/src/text.rs
+++ b/rsvg_internals/src/text.rs
@@ -591,10 +591,10 @@ impl NodeTrait for NodeText {
     fn set_atts(&self, _: &RsvgNode, pbag: &PropertyBag<'_>) -> NodeResult {
         for (attr, value) in pbag.iter() {
             match attr {
-                Attribute::X => self.x.set(attr.parse(value, ())?),
-                Attribute::Y => self.y.set(attr.parse(value, ())?),
-                Attribute::Dx => self.dx.set(attr.parse(value, ()).map(Some)?),
-                Attribute::Dy => self.dy.set(attr.parse(value, ()).map(Some)?),
+                Attribute::X => self.x.set(attr.parse(value)?),
+                Attribute::Y => self.y.set(attr.parse(value)?),
+                Attribute::Dx => self.dx.set(attr.parse(value).map(Some)?),
+                Attribute::Dy => self.dy.set(attr.parse(value).map(Some)?),
                 _ => (),
             }
         }
@@ -770,10 +770,10 @@ impl NodeTrait for NodeTSpan {
     fn set_atts(&self, _: &RsvgNode, pbag: &PropertyBag<'_>) -> NodeResult {
         for (attr, value) in pbag.iter() {
             match attr {
-                Attribute::X => self.x.set(attr.parse(value, ()).map(Some)?),
-                Attribute::Y => self.y.set(attr.parse(value, ()).map(Some)?),
-                Attribute::Dx => self.dx.set(attr.parse(value, ()).map(Some)?),
-                Attribute::Dy => self.dy.set(attr.parse(value, ()).map(Some)?),
+                Attribute::X => self.x.set(attr.parse(value).map(Some)?),
+                Attribute::Y => self.y.set(attr.parse(value).map(Some)?),
+                Attribute::Dx => self.dx.set(attr.parse(value).map(Some)?),
+                Attribute::Dy => self.dy.set(attr.parse(value).map(Some)?),
                 _ => (),
             }
         }
diff --git a/rsvg_internals/src/transform.rs b/rsvg_internals/src/transform.rs
index d45ef7c4..9488163f 100644
--- a/rsvg_internals/src/transform.rs
+++ b/rsvg_internals/src/transform.rs
@@ -9,10 +9,9 @@ use error::*;
 use parsers::{finite_f32, CssParserExt, Parse, ParseError};
 
 impl Parse for cairo::Matrix {
-    type Data = ();
     type Err = ValueErrorKind;
 
-    fn parse(parser: &mut Parser<'_, '_>, _: ()) -> Result<cairo::Matrix, ValueErrorKind> {
+    fn parse(parser: &mut Parser<'_, '_>) -> Result<cairo::Matrix, ValueErrorKind> {
         let matrix = parse_transform_list(parser)?;
 
         matrix
@@ -251,7 +250,7 @@ mod tests {
     use std::f64;
 
     fn parse_transform(s: &str) -> Result<cairo::Matrix, ValueErrorKind> {
-        cairo::Matrix::parse_str(s, ())
+        cairo::Matrix::parse_str(s)
     }
 
     fn assert_matrix_eq(a: &cairo::Matrix, b: &cairo::Matrix) {
diff --git a/rsvg_internals/src/unit_interval.rs b/rsvg_internals/src/unit_interval.rs
index 861f293d..2577583c 100644
--- a/rsvg_internals/src/unit_interval.rs
+++ b/rsvg_internals/src/unit_interval.rs
@@ -14,10 +14,9 @@ impl UnitInterval {
 }
 
 impl Parse for UnitInterval {
-    type Data = ();
     type Err = ValueErrorKind;
 
-    fn parse(parser: &mut Parser<'_, '_>, _: ()) -> Result<UnitInterval, ValueErrorKind> {
+    fn parse(parser: &mut Parser<'_, '_>) -> Result<UnitInterval, ValueErrorKind> {
         let x = f64::from(
             parser
                 .expect_finite_number()
@@ -50,23 +49,23 @@ mod tests {
 
     #[test]
     fn parses_number() {
-        assert_eq!(UnitInterval::parse_str("0", ()), Ok(UnitInterval(0.0)));
-        assert_eq!(UnitInterval::parse_str("1", ()), Ok(UnitInterval(1.0)));
-        assert_eq!(UnitInterval::parse_str("0.5", ()), Ok(UnitInterval(0.5)));
+        assert_eq!(UnitInterval::parse_str("0"), Ok(UnitInterval(0.0)));
+        assert_eq!(UnitInterval::parse_str("1"), Ok(UnitInterval(1.0)));
+        assert_eq!(UnitInterval::parse_str("0.5"), Ok(UnitInterval(0.5)));
     }
 
     #[test]
     fn parses_out_of_range_number() {
-        assert_eq!(UnitInterval::parse_str("-10", ()), Ok(UnitInterval(0.0)));
-        assert_eq!(UnitInterval::parse_str("10", ()), Ok(UnitInterval(1.0)));
+        assert_eq!(UnitInterval::parse_str("-10"), Ok(UnitInterval(0.0)));
+        assert_eq!(UnitInterval::parse_str("10"), Ok(UnitInterval(1.0)));
     }
 
     #[test]
     fn errors_on_invalid_input() {
-        assert!(is_parse_error(&UnitInterval::parse_str("", ())));
-        assert!(is_parse_error(&UnitInterval::parse_str("foo", ())));
-        assert!(is_parse_error(&UnitInterval::parse_str("-x", ())));
-        assert!(is_parse_error(&UnitInterval::parse_str("0.0foo", ())));
+        assert!(is_parse_error(&UnitInterval::parse_str("")));
+        assert!(is_parse_error(&UnitInterval::parse_str("foo")));
+        assert!(is_parse_error(&UnitInterval::parse_str("-x")));
+        assert!(is_parse_error(&UnitInterval::parse_str("0.0foo")));
     }
 
     #[test]
diff --git a/rsvg_internals/src/viewbox.rs b/rsvg_internals/src/viewbox.rs
index 800b050d..618be2a9 100644
--- a/rsvg_internals/src/viewbox.rs
+++ b/rsvg_internals/src/viewbox.rs
@@ -29,7 +29,6 @@ impl ViewBox {
 }
 
 impl Parse for ViewBox {
-    type Data = ();
     type Err = ValueErrorKind;
 
     // Parse a viewBox attribute
@@ -40,7 +39,7 @@ impl Parse for ViewBox {
     // x, y, w, h
     //
     // Where w and h must be nonnegative.
-    fn parse(parser: &mut Parser<'_, '_>, _: ()) -> Result<ViewBox, ValueErrorKind> {
+    fn parse(parser: &mut Parser<'_, '_>) -> Result<ViewBox, ValueErrorKind> {
         let NumberList(v) = NumberList::parse(parser, NumberListLength::Exact(4))
             .map_err(|_| ParseError::new("string does not match 'x [,] y [,] w [,] h'"))?;
 
@@ -68,29 +67,29 @@ mod tests {
     #[test]
     fn parses_valid_viewboxes() {
         assert_eq!(
-            ViewBox::parse_str("  1 2 3 4", ()),
+            ViewBox::parse_str("  1 2 3 4"),
             Ok(ViewBox::new(1.0, 2.0, 3.0, 4.0))
         );
 
         assert_eq!(
-            ViewBox::parse_str(" -1.5 -2.5e1,34,56e2  ", ()),
+            ViewBox::parse_str(" -1.5 -2.5e1,34,56e2  "),
             Ok(ViewBox::new(-1.5, -25.0, 34.0, 5600.0))
         );
     }
 
     #[test]
     fn parsing_invalid_viewboxes_yields_error() {
-        assert!(is_parse_error(&ViewBox::parse_str("", ())));
+        assert!(is_parse_error(&ViewBox::parse_str("")));
 
-        assert!(is_value_error(&ViewBox::parse_str(" 1,2,-3,-4 ", ())));
+        assert!(is_value_error(&ViewBox::parse_str(" 1,2,-3,-4 ")));
 
-        assert!(is_parse_error(&ViewBox::parse_str("qwerasdfzxcv", ())));
+        assert!(is_parse_error(&ViewBox::parse_str("qwerasdfzxcv")));
 
-        assert!(is_parse_error(&ViewBox::parse_str(" 1 2 3 4   5", ())));
+        assert!(is_parse_error(&ViewBox::parse_str(" 1 2 3 4   5")));
 
-        assert!(is_parse_error(&ViewBox::parse_str(" 1 2 foo 3 4", ())));
+        assert!(is_parse_error(&ViewBox::parse_str(" 1 2 foo 3 4")));
 
         // https://gitlab.gnome.org/GNOME/librsvg/issues/344
-        assert!(is_parse_error(&ViewBox::parse_str("0 0 9E80.7", ())));
+        assert!(is_parse_error(&ViewBox::parse_str("0 0 9E80.7")));
     }
 }


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