[librsvg: 1/4] marker: impl Parse for Angle



commit 7df8225fe6979b8c380a4d99f627eaee8c104b78
Author: Paolo Borelli <pborelli gnome org>
Date:   Mon Dec 10 22:29:37 2018 +0100

    marker: impl Parse for Angle
    
    Now that we have a struct, we can move the parsing code to it.
    Also change the MarkerOrient enum to hold Angle directly.

 rsvg_internals/src/marker.rs  | 78 ++++++++++++++++++++++++++++++++++++-------
 rsvg_internals/src/parsers.rs | 61 ---------------------------------
 2 files changed, 66 insertions(+), 73 deletions(-)
---
diff --git a/rsvg_internals/src/marker.rs b/rsvg_internals/src/marker.rs
index 88faa874..be28eb9f 100644
--- a/rsvg_internals/src/marker.rs
+++ b/rsvg_internals/src/marker.rs
@@ -14,7 +14,6 @@ use handle::RsvgHandle;
 use iri::IRI;
 use length::{Length, LengthDir};
 use node::*;
-use parsers;
 use parsers::ParseError;
 use parsers::{parse, parse_and_validate, Parse};
 use path_builder::*;
@@ -65,12 +64,12 @@ impl Parse for MarkerUnits {
 #[derive(Debug, Copy, Clone, PartialEq)]
 enum MarkerOrient {
     Auto,
-    Degrees(f64),
+    Angle(Angle),
 }
 
 impl Default for MarkerOrient {
     fn default() -> MarkerOrient {
-        MarkerOrient::Degrees(0.0)
+        MarkerOrient::Angle(Angle::new(0.0))
     }
 }
 
@@ -82,9 +81,8 @@ impl Parse for MarkerOrient {
         if parser.try(|p| p.expect_ident_matching("auto")).is_ok() {
             Ok(MarkerOrient::Auto)
         } else {
-            parsers::angle_degrees(parser)
-                .map(MarkerOrient::Degrees)
-                .map_err(ValueErrorKind::Parse)
+            Angle::parse(parser, ())
+                .map(MarkerOrient::Angle)
         }
     }
 }
@@ -151,7 +149,7 @@ impl NodeMarker {
 
         let rotation = match self.orient.get() {
             MarkerOrient::Auto => computed_angle,
-            MarkerOrient::Degrees(d) => Angle::from_degrees(d),
+            MarkerOrient::Angle(a) => a,
         };
 
         affine.rotate(rotation.radians());
@@ -635,6 +633,49 @@ impl Angle {
     }
 }
 
+// angle:
+// https://www.w3.org/TR/SVG/types.html#DataTypeAngle
+//
+// angle ::= number ("deg" | "grad" | "rad")?
+//
+impl Parse for Angle {
+    type Data = ();
+    type Err = ValueErrorKind;
+
+    fn parse(parser: &mut Parser<'_, '_>, _: ()) -> Result<Angle, ValueErrorKind> {
+        let angle = {
+            let token = parser
+                .next()
+                .map_err(|_| ParseError::new("expected angle"))?;
+
+            match *token {
+                Token::Number { value, .. } => Angle::from_degrees(value as f64),
+
+                Token::Dimension {
+                    value, ref unit, ..
+                } => {
+                    let value = f64::from(value);
+
+                    match unit.as_ref() {
+                        "deg" => Angle::from_degrees(value),
+                        "grad" => Angle::from_degrees(value * 360.0 / 400.0),
+                        "rad" => Angle::new(value),
+                        _ => return Err(ValueErrorKind::Parse(ParseError::new("expected 'deg' | 'grad' | 
'rad'"))),
+                    }
+                }
+
+                _ => return Err(ValueErrorKind::Parse(ParseError::new("expected angle"))),
+            }
+        };
+
+        parser
+            .expect_exhausted()
+            .map_err(|_| ValueErrorKind::Parse(ParseError::new("expected angle")))?;
+
+        Ok(angle)
+    }
+}
+
 // From SVG's marker-start, marker-mid, marker-end properties
 #[derive(Debug, Copy, Clone, PartialEq)]
 enum MarkerType {
@@ -877,6 +918,19 @@ where
 mod parser_tests {
     use super::*;
 
+    #[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("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", ()), 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());
+    }
+
     #[test]
     fn parsing_invalid_marker_units_yields_error() {
         assert!(is_parse_error(
@@ -918,23 +972,23 @@ mod parser_tests {
 
         assert_eq!(
             MarkerOrient::parse_str("0", ()),
-            Ok(MarkerOrient::Degrees(0.0))
+            Ok(MarkerOrient::Angle(Angle::new(0.0)))
         );
         assert_eq!(
             MarkerOrient::parse_str("180", ()),
-            Ok(MarkerOrient::Degrees(180.0))
+            Ok(MarkerOrient::Angle(Angle::from_degrees(180.0)))
         );
         assert_eq!(
             MarkerOrient::parse_str("180deg", ()),
-            Ok(MarkerOrient::Degrees(180.0))
+            Ok(MarkerOrient::Angle(Angle::from_degrees(180.0)))
         );
         assert_eq!(
             MarkerOrient::parse_str("-400grad", ()),
-            Ok(MarkerOrient::Degrees(-360.0))
+            Ok(MarkerOrient::Angle(Angle::from_degrees(-360.0)))
         );
         assert_eq!(
             MarkerOrient::parse_str("1rad", ()),
-            Ok(MarkerOrient::Degrees(180.0 / PI))
+            Ok(MarkerOrient::Angle(Angle::new(1.0)))
         );
     }
 }
diff --git a/rsvg_internals/src/parsers.rs b/rsvg_internals/src/parsers.rs
index 5eae2591..e87e373b 100644
--- a/rsvg_internals/src/parsers.rs
+++ b/rsvg_internals/src/parsers.rs
@@ -1,6 +1,5 @@
 use cssparser::{BasicParseError, Parser, ParserInput, Token};
 
-use std::f64::consts::*;
 use std::str::{self, FromStr};
 
 use attributes::Attribute;
@@ -116,46 +115,6 @@ where
         .map_err(|e| NodeError::attribute_error(Attribute::from_str(key).unwrap(), e))
 }
 
-// angle:
-// https://www.w3.org/TR/SVG/types.html#DataTypeAngle
-//
-// angle ::= number ("deg" | "grad" | "rad")?
-//
-// Returns an f64 angle in degrees
-
-pub fn angle_degrees(parser: &mut Parser<'_, '_>) -> Result<f64, ParseError> {
-    let angle = {
-        let token = parser
-            .next()
-            .map_err(|_| ParseError::new("expected angle"))?;
-
-        match *token {
-            Token::Number { value, .. } => f64::from(value),
-
-            Token::Dimension {
-                value, ref unit, ..
-            } => {
-                let value = f64::from(value);
-
-                match unit.as_ref() {
-                    "deg" => value,
-                    "grad" => value * 360.0 / 400.0,
-                    "rad" => value * 180.0 / PI,
-                    _ => return Err(ParseError::new("expected 'deg' | 'grad' | 'rad'")),
-                }
-            }
-
-            _ => return Err(ParseError::new("expected angle")),
-        }
-    };
-
-    parser
-        .expect_exhausted()
-        .map_err(|_| ParseError::new("expected angle"))?;
-
-    Ok(angle)
-}
-
 pub fn optional_comma(parser: &mut Parser<'_, '_>) {
     let _ = parser.try(|p| p.expect_comma());
 }
@@ -391,26 +350,6 @@ mod tests {
         assert!(list_of_points("1 2-3,-4").is_err());
     }
 
-    fn angle_degrees_str(s: &str) -> Result<f64, ParseError> {
-        let mut input = ParserInput::new(s);
-        let mut parser = Parser::new(&mut input);
-
-        angle_degrees(&mut parser)
-    }
-
-    #[test]
-    fn parses_angle() {
-        assert_eq!(angle_degrees_str("0"), Ok(0.0));
-        assert_eq!(angle_degrees_str("15"), Ok(15.0));
-        assert_eq!(angle_degrees_str("180.5deg"), Ok(180.5));
-        assert_eq!(angle_degrees_str("1rad"), Ok(180.0 / PI));
-        assert_eq!(angle_degrees_str("-400grad"), Ok(-360.0));
-
-        assert!(angle_degrees_str("").is_err());
-        assert!(angle_degrees_str("foo").is_err());
-        assert!(angle_degrees_str("300foo").is_err());
-    }
-
     #[test]
     fn parses_number_list() {
         assert_eq!(


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