[librsvg] viewbox.rs: Implement FromStr for RsvgViewBox based on the parsers



commit 9a927252b2a4d7e81aa12b3201d5757deb571560
Author: Federico Mena Quintero <federico gnome org>
Date:   Tue Feb 21 21:19:59 2017 -0600

    viewbox.rs: Implement FromStr for RsvgViewBox based on the parsers
    
    parsers.rs: Don't validate the viewBox's width and height here; do it upstream

 rust/src/parsers.rs |   26 +++++++++-----
 rust/src/viewbox.rs |   99 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 115 insertions(+), 10 deletions(-)
---
diff --git a/rust/src/parsers.rs b/rust/src/parsers.rs
index 364eacc..f8a5681 100644
--- a/rust/src/parsers.rs
+++ b/rust/src/parsers.rs
@@ -61,15 +61,15 @@ named! (pub comma,
 // Where w and h must be nonnegative.
 
 named! (pub view_box<(f64, f64, f64, f64)>,
-        verify! (ws! (do_parse! (x: double >>
-                                 opt! (comma) >>
-                                 y: double >>
-                                 opt! (comma) >>
-                                 w: double >>
-                                 opt! (comma) >>
-                                 h: double >>
-                                 (x, y, w, h))),
-                 |(x, y, w, h)| w >= 0.0 && h >= 0.0));
+        ws! (do_parse! (x: double    >>
+                        opt! (comma) >>
+                        y: double    >>
+                        opt! (comma) >>
+                        w: double    >>
+                        opt! (comma) >>
+                        h: double    >>
+                        eof! ()      >>
+                        (x, y, w, h))));
 
 #[cfg(test)]
 mod tests {
@@ -93,5 +93,13 @@ mod tests {
     #[test]
     fn parses_view_box () {
         assert_eq! (view_box (b"1 2 3 4"), IResult::Done (&b""[..], (1.0, 2.0, 3.0, 4.0)));
+        assert_eq! (view_box (b"1,2,3 4"), IResult::Done (&b""[..], (1.0, 2.0, 3.0, 4.0)));
+
+        let result = view_box (b"1 2 3 4 5");
+
+        match result {
+            IResult::Error (_) => { },
+            _ => { panic! ("{:?}", result); }
+        }
     }
 }
diff --git a/rust/src/viewbox.rs b/rust/src/viewbox.rs
index 1799d22..e878bdb 100644
--- a/rust/src/viewbox.rs
+++ b/rust/src/viewbox.rs
@@ -1,8 +1,15 @@
 extern crate cairo;
 
+use std::fmt;
+use std::str::FromStr;
+
+use nom::{IResult};
+
+use parsers;
+
 /* Keep this in sync with rsvg-private.h:RsvgViewBox */
 #[repr(C)]
-#[derive(Debug, Copy, Clone)]
+#[derive(Debug, Copy, Clone, PartialEq)]
 pub struct RsvgViewBox {
     pub rect:   cairo::Rectangle,
     pub active: bool
@@ -19,3 +26,93 @@ impl RsvgViewBox {
         }
     }
 }
+
+impl Default for RsvgViewBox {
+    fn default () -> RsvgViewBox {
+        RsvgViewBox::new_inactive ()
+    }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub enum ParseViewBoxError {
+    NegativeWidthOrHeight, // In "x y w h", w and h must be nonnegative
+    Error                  // General parsing error
+}
+
+impl fmt::Display for ParseViewBoxError {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match *self {
+            ParseViewBoxError::NegativeWidthOrHeight => {
+                "width and height must not be negative".fmt (f)
+            },
+
+            ParseViewBoxError::Error => {
+                "string does not match 'x [,] y [,] w [,] h'".fmt (f)
+            }
+        }
+    }
+}
+
+impl FromStr for RsvgViewBox {
+    type Err = ParseViewBoxError;
+
+    fn from_str (s: &str) -> Result<RsvgViewBox, ParseViewBoxError> {
+        let result = parsers::view_box (s.as_bytes ()).to_full_result ();
+
+        match result {
+            Ok ((x, y, w, h)) => {
+                if w >= 0.0 && h >= 0.0 {
+                    Ok (RsvgViewBox { rect: cairo::Rectangle { x: x,
+                                                               y: y,
+                                                               width: w,
+                                                               height: h },
+                                      active: true })
+                } else {
+                    Err (ParseViewBoxError::NegativeWidthOrHeight)
+                }
+            },
+
+            Err (_) => {
+                Err (ParseViewBoxError::Error)
+            }
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use std::str::FromStr;
+
+    #[test]
+    fn parses_valid_viewboxes () {
+        assert_eq! (RsvgViewBox::from_str ("1 2 3 4"),
+                    Ok (RsvgViewBox { rect: cairo::Rectangle { x: 1.0,
+                                                               y: 2.0,
+                                                               width: 3.0,
+                                                               height: 4.0 },
+                                      active: true }));
+
+        assert_eq! (RsvgViewBox::from_str ("-1.5 -2.5e1,34,56e2"),
+                    Ok (RsvgViewBox { rect: cairo::Rectangle { x: -1.5,
+                                                               y: -25.0,
+                                                               width: 34.0,
+                                                               height: 5600.0 },
+                                      active: true }));
+    }
+
+    #[test]
+    fn parsing_invalid_viewboxes_yields_error () {
+        assert_eq! (RsvgViewBox::from_str (""),
+                    Err (ParseViewBoxError::Error));
+
+        assert_eq! (RsvgViewBox::from_str ("1,2,-3,-4"),
+                    Err (ParseViewBoxError::NegativeWidthOrHeight));
+
+        assert_eq! (RsvgViewBox::from_str ("qwerasdfzxcv"),
+                    Err (ParseViewBoxError::Error));
+
+        assert_eq! (RsvgViewBox::from_str ("1 2 3 4 5"),
+                    Err (ParseViewBoxError::Error));
+    }
+}


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