[librsvg: 2/3] number_list: refactor a NumberList type



commit c9fa28e0bf3544f01ec53817080ebd7041ad100d
Author: Paolo Borelli <pborelli gnome org>
Date:   Fri Jan 18 21:30:54 2019 +0100

    number_list: refactor a NumberList type
    
    Split it in its own module and implement the Parse trait

 Makefile.am                                      |   1 +
 rsvg_internals/src/filters/color_matrix.rs       |  35 ++++---
 rsvg_internals/src/filters/component_transfer.rs |  23 ++---
 rsvg_internals/src/filters/convolve_matrix.rs    |   9 +-
 rsvg_internals/src/lib.rs                        |   1 +
 rsvg_internals/src/number_list.rs                | 124 +++++++++++++++++++++++
 rsvg_internals/src/parsers.rs                    | 121 ----------------------
 rsvg_internals/src/viewbox.rs                    |  15 ++-
 8 files changed, 166 insertions(+), 163 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index db9309fa..1460d01a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -88,6 +88,7 @@ RUST_SRC =                                                    \
        rsvg_internals/src/marker.rs                            \
        rsvg_internals/src/mask.rs                              \
        rsvg_internals/src/node.rs                              \
+       rsvg_internals/src/number_list.rs                       \
        rsvg_internals/src/paint_server.rs                      \
        rsvg_internals/src/parsers.rs                           \
        rsvg_internals/src/path_builder.rs                      \
diff --git a/rsvg_internals/src/filters/color_matrix.rs b/rsvg_internals/src/filters/color_matrix.rs
index 9bba598a..ae0b9540 100644
--- a/rsvg_internals/src/filters/color_matrix.rs
+++ b/rsvg_internals/src/filters/color_matrix.rs
@@ -7,7 +7,8 @@ use attributes::Attribute;
 use drawing_ctx::DrawingCtx;
 use error::NodeError;
 use node::{NodeResult, NodeTrait, RsvgNode};
-use parsers::{self, ListLength, NumberListError, ParseError};
+use number_list::{NumberList, NumberListError, NumberListLength};
+use parsers::{self, Parse, ParseError};
 use property_bag::PropertyBag;
 use surface_utils::{
     iterators::Pixels,
@@ -74,24 +75,22 @@ impl NodeTrait for ColorMatrix {
                 let new_matrix = match operation_type {
                     OperationType::LuminanceToAlpha => unreachable!(),
                     OperationType::Matrix => {
-                        let matrix = Matrix4x5::from_row_slice(
-                            &parsers::number_list_from_str(value, ListLength::Exact(20)).map_err(
-                                |err| {
-                                    NodeError::parse_error(
-                                        attr,
-                                        match err {
-                                            NumberListError::IncorrectNumberOfElements => {
-                                                ParseError::new(
-                                                    "incorrect number of elements: expected 20",
-                                                )
-                                            }
-                                            NumberListError::Parse(err) => err,
-                                        },
-                                    )
+                        let NumberList(v) = NumberList::parse_str(
+                            value,
+                            NumberListLength::Exact(20),
+                        )
+                        .map_err(|err| {
+                            NodeError::parse_error(
+                                attr,
+                                match err {
+                                    NumberListError::IncorrectNumberOfElements => {
+                                        ParseError::new("incorrect number of elements: expected 20")
+                                    }
+                                    NumberListError::Parse(err) => err,
                                 },
-                            )?,
-                        );
-
+                            )
+                        })?;
+                        let matrix = Matrix4x5::from_row_slice(&v);
                         let mut matrix = matrix.fixed_resize(0.0);
                         matrix[(4, 4)] = 1.0;
                         matrix
diff --git a/rsvg_internals/src/filters/component_transfer.rs 
b/rsvg_internals/src/filters/component_transfer.rs
index b76b9af4..eebfb915 100644
--- a/rsvg_internals/src/filters/component_transfer.rs
+++ b/rsvg_internals/src/filters/component_transfer.rs
@@ -7,7 +7,8 @@ use attributes::Attribute;
 use drawing_ctx::DrawingCtx;
 use error::NodeError;
 use node::{NodeResult, NodeTrait, NodeType, RsvgNode};
-use parsers::{self, ListLength, NumberListError, ParseError};
+use number_list::{NumberList, NumberListError, NumberListLength};
+use parsers::{self, Parse, ParseError};
 use property_bag::PropertyBag;
 use surface_utils::{
     iterators::Pixels,
@@ -214,17 +215,15 @@ impl NodeTrait for FuncX {
             match attr {
                 Attribute::Type => self.function_type.set(FunctionType::parse(attr, value)?),
                 Attribute::TableValues => {
-                    self.table_values.replace(
-                        parsers::number_list_from_str(value, ListLength::Unbounded).map_err(
-                            |err| {
-                                if let NumberListError::Parse(err) = err {
-                                    NodeError::parse_error(attr, err)
-                                } else {
-                                    panic!("unexpected number list error");
-                                }
-                            },
-                        )?,
-                    );
+                    let NumberList(v) = NumberList::parse_str(value, NumberListLength::Unbounded)
+                        .map_err(|err| {
+                        if let NumberListError::Parse(err) = err {
+                            NodeError::parse_error(attr, err)
+                        } else {
+                            panic!("unexpected number list error");
+                        }
+                    })?;
+                    self.table_values.replace(v);
                 }
                 Attribute::Slope => self.slope.set(
                     parsers::number(value).map_err(|err| NodeError::attribute_error(attr, err))?,
diff --git a/rsvg_internals/src/filters/convolve_matrix.rs b/rsvg_internals/src/filters/convolve_matrix.rs
index b4047dc9..7b2d785e 100644
--- a/rsvg_internals/src/filters/convolve_matrix.rs
+++ b/rsvg_internals/src/filters/convolve_matrix.rs
@@ -7,7 +7,8 @@ use attributes::Attribute;
 use drawing_ctx::DrawingCtx;
 use error::NodeError;
 use node::{NodeResult, NodeTrait, RsvgNode};
-use parsers::{self, ListLength, NumberListError, ParseError};
+use number_list::{NumberList, NumberListError, NumberListLength};
+use parsers::{self, Parse, ParseError};
 use property_bag::PropertyBag;
 use rect::IRect;
 use surface_utils::{
@@ -171,7 +172,7 @@ impl NodeTrait for ConvolveMatrix {
 
                 // #352: Parse as an unbounded list rather than exact length to prevent aborts due
                 //       to huge allocation attempts by underlying Vec::with_capacity().
-                let elements = parsers::number_list_from_str(value, ListLength::Unbounded)
+                let NumberList(v) = NumberList::parse_str(value, NumberListLength::Unbounded)
                     .map_err(|err| {
                         NodeError::parse_error(
                             attr,
@@ -182,7 +183,7 @@ impl NodeTrait for ConvolveMatrix {
                         )
                     })?;
 
-                if elements.len() != number_of_elements {
+                if v.len() != number_of_elements {
                     return Err(NodeError::value_error(
                         attr,
                         &format!(
@@ -195,7 +196,7 @@ impl NodeTrait for ConvolveMatrix {
                 DMatrix::from_data(MatrixVec::new(
                     Dynamic::new(self.order.get().1 as usize),
                     Dynamic::new(self.order.get().0 as usize),
-                    elements,
+                    v,
                 ))
             }));
         }
diff --git a/rsvg_internals/src/lib.rs b/rsvg_internals/src/lib.rs
index fdafca77..ef469489 100644
--- a/rsvg_internals/src/lib.rs
+++ b/rsvg_internals/src/lib.rs
@@ -118,6 +118,7 @@ mod link;
 mod marker;
 mod mask;
 mod node;
+mod number_list;
 mod paint_server;
 mod parsers;
 mod path_builder;
diff --git a/rsvg_internals/src/number_list.rs b/rsvg_internals/src/number_list.rs
new file mode 100644
index 00000000..73ab065d
--- /dev/null
+++ b/rsvg_internals/src/number_list.rs
@@ -0,0 +1,124 @@
+use cssparser::Parser;
+
+use parsers::{CssParserExt, Parse, ParseError};
+
+#[derive(Eq, PartialEq)]
+pub enum NumberListLength {
+    Exact(usize),
+    Unbounded,
+}
+
+#[derive(Debug, PartialEq)]
+pub enum NumberListError {
+    IncorrectNumberOfElements,
+    Parse(ParseError),
+}
+
+#[derive(Debug, PartialEq)]
+pub struct NumberList(pub Vec<f64>);
+
+impl Parse for NumberList {
+    type Data = NumberListLength;
+    type Err = NumberListError;
+
+    fn parse(
+        parser: &mut Parser<'_, '_>,
+        length: NumberListLength,
+    ) -> Result<NumberList, NumberListError> {
+        let mut v = match length {
+            NumberListLength::Exact(l) if l > 0 => Vec::<f64>::with_capacity(l),
+            NumberListLength::Exact(_) => unreachable!(),
+            NumberListLength::Unbounded => Vec::<f64>::new(),
+        };
+
+        if parser.is_exhausted() && length == NumberListLength::Unbounded {
+            return Ok(NumberList(v));
+        }
+
+        for i in 0.. {
+            if i != 0 {
+                parser.optional_comma();
+            }
+
+            v.push(f64::from(parser.expect_finite_number().map_err(|_| {
+                NumberListError::Parse(ParseError::new("expected number"))
+            })?));
+
+            if let NumberListLength::Exact(l) = length {
+                if i + 1 == l {
+                    break;
+                }
+            }
+
+            if parser.is_exhausted() {
+                match length {
+                    NumberListLength::Exact(l) => {
+                        if i + 1 == l {
+                            break;
+                        }
+                    }
+                    _ => break,
+                }
+            }
+        }
+
+        parser
+            .expect_exhausted()
+            .map_err(|_| NumberListError::IncorrectNumberOfElements)?;
+
+        Ok(NumberList(v))
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn parses_number_list() {
+        assert_eq!(
+            NumberList::parse_str("5", NumberListLength::Exact(1)),
+            Ok(NumberList(vec![5.0]))
+        );
+
+        assert_eq!(
+            NumberList::parse_str("1 2 3 4", NumberListLength::Exact(4)),
+            Ok(NumberList(vec![1.0, 2.0, 3.0, 4.0]))
+        );
+
+        assert_eq!(
+            NumberList::parse_str("", NumberListLength::Unbounded),
+            Ok(NumberList(vec![]))
+        );
+
+        assert_eq!(
+            NumberList::parse_str("1, 2, 3.0, 4, 5", NumberListLength::Unbounded),
+            Ok(NumberList(vec![1.0, 2.0, 3.0, 4.0, 5.0]))
+        );
+    }
+
+    #[test]
+    fn errors_on_invalid_number_list() {
+        // empty
+        assert!(NumberList::parse_str("", NumberListLength::Exact(1)).is_err());
+
+        // garbage
+        assert!(NumberList::parse_str("foo", NumberListLength::Exact(1)).is_err());
+        assert!(NumberList::parse_str("1foo", NumberListLength::Exact(2)).is_err());
+        assert!(NumberList::parse_str("1 foo", NumberListLength::Exact(2)).is_err());
+        assert!(NumberList::parse_str("1 foo 2", NumberListLength::Exact(2)).is_err());
+        assert!(NumberList::parse_str("1,foo", NumberListLength::Exact(2)).is_err());
+
+        // too many
+        assert!(NumberList::parse_str("1 2", NumberListLength::Exact(1)).is_err());
+
+        // extra token
+        assert!(NumberList::parse_str("1,", NumberListLength::Exact(1)).is_err());
+        assert!(NumberList::parse_str("1,", NumberListLength::Exact(1)).is_err());
+        assert!(NumberList::parse_str("1,", NumberListLength::Unbounded).is_err());
+
+        // too few
+        assert!(NumberList::parse_str("1", NumberListLength::Exact(2)).is_err());
+        assert!(NumberList::parse_str("1 2", NumberListLength::Exact(3)).is_err());
+    }
+}
diff --git a/rsvg_internals/src/parsers.rs b/rsvg_internals/src/parsers.rs
index d89e8cd6..08327a57 100644
--- a/rsvg_internals/src/parsers.rs
+++ b/rsvg_internals/src/parsers.rs
@@ -200,83 +200,6 @@ pub fn integer_optional_integer(s: &str) -> Result<(i32, i32), ValueErrorKind> {
     }
 }
 
-// Lists of number values
-
-#[derive(Eq, PartialEq)]
-pub enum ListLength {
-    Exact(usize),
-    Unbounded,
-}
-
-#[derive(Debug, PartialEq)]
-pub enum NumberListError {
-    IncorrectNumberOfElements,
-    Parse(ParseError),
-}
-
-pub fn number_list(
-    parser: &mut Parser<'_, '_>,
-    length: ListLength,
-) -> Result<Vec<f64>, NumberListError> {
-    let n;
-
-    match length {
-        ListLength::Exact(l) => {
-            assert!(l > 0);
-            n = Some(l);
-        }
-        ListLength::Unbounded => {
-            n = None;
-        }
-    }
-
-    let mut v = Vec::<f64>::with_capacity(n.unwrap_or(0));
-
-    if parser.is_exhausted() && length == ListLength::Unbounded {
-        return Ok(v);
-    }
-
-    for i in 0.. {
-        if i != 0 {
-            parser.optional_comma();
-        }
-
-        v.push(f64::from(parser.expect_finite_number().map_err(|_| {
-            NumberListError::Parse(ParseError::new("expected number"))
-        })?));
-
-        if let ListLength::Exact(l) = length {
-            if i + 1 == l {
-                break;
-            }
-        }
-
-        if parser.is_exhausted() {
-            match length {
-                ListLength::Exact(l) => {
-                    if i + 1 == l {
-                        break;
-                    }
-                }
-                _ => break,
-            }
-        }
-    }
-
-    parser
-        .expect_exhausted()
-        .map_err(|_| NumberListError::IncorrectNumberOfElements)?;
-
-    Ok(v)
-}
-
-pub fn number_list_from_str(s: &str, length: ListLength) -> Result<Vec<f64>, NumberListError> {
-    let mut input = ParserInput::new(s);
-    let mut parser = Parser::new(&mut input);
-
-    number_list(&mut parser, length)
-}
-
 #[cfg(test)]
 mod tests {
     use super::*;
@@ -303,50 +226,6 @@ mod tests {
         assert!(number_optional_number("1 2 x").is_err());
     }
 
-    #[test]
-    fn parses_number_list() {
-        assert_eq!(
-            number_list_from_str("5", ListLength::Exact(1)),
-            Ok(vec![5.0])
-        );
-
-        assert_eq!(
-            number_list_from_str("1 2 3 4", ListLength::Exact(4)),
-            Ok(vec![1.0, 2.0, 3.0, 4.0])
-        );
-
-        assert_eq!(number_list_from_str("", ListLength::Unbounded), Ok(vec![]));
-        assert_eq!(
-            number_list_from_str("1, 2, 3.0, 4, 5", ListLength::Unbounded),
-            Ok(vec![1.0, 2.0, 3.0, 4.0, 5.0])
-        );
-    }
-
-    #[test]
-    fn errors_on_invalid_number_list() {
-        // empty
-        assert!(number_list_from_str("", ListLength::Exact(1)).is_err());
-
-        // garbage
-        assert!(number_list_from_str("foo", ListLength::Exact(1)).is_err());
-        assert!(number_list_from_str("1foo", ListLength::Exact(2)).is_err());
-        assert!(number_list_from_str("1 foo", ListLength::Exact(2)).is_err());
-        assert!(number_list_from_str("1 foo 2", ListLength::Exact(2)).is_err());
-        assert!(number_list_from_str("1,foo", ListLength::Exact(2)).is_err());
-
-        // too many
-        assert!(number_list_from_str("1 2", ListLength::Exact(1)).is_err());
-
-        // extra token
-        assert!(number_list_from_str("1,", ListLength::Exact(1)).is_err());
-        assert!(number_list_from_str("1,", ListLength::Exact(1)).is_err());
-        assert!(number_list_from_str("1,", ListLength::Unbounded).is_err());
-
-        // too few
-        assert!(number_list_from_str("1", ListLength::Exact(2)).is_err());
-        assert!(number_list_from_str("1 2", ListLength::Exact(3)).is_err());
-    }
-
     #[test]
     fn parses_integer() {
         assert_eq!(integer("1"), Ok(1));
diff --git a/rsvg_internals/src/viewbox.rs b/rsvg_internals/src/viewbox.rs
index 37c8d8f8..800b050d 100644
--- a/rsvg_internals/src/viewbox.rs
+++ b/rsvg_internals/src/viewbox.rs
@@ -1,9 +1,8 @@
 use cssparser::Parser;
 
 use error::*;
-use parsers;
-use parsers::Parse;
-use parsers::{ListLength, ParseError};
+use number_list::{NumberList, NumberListLength};
+use parsers::{Parse, ParseError};
 
 #[derive(Debug, Copy, Clone, PartialEq)]
 pub struct ViewBox {
@@ -42,17 +41,17 @@ impl Parse for ViewBox {
     //
     // Where w and h must be nonnegative.
     fn parse(parser: &mut Parser<'_, '_>, _: ()) -> Result<ViewBox, ValueErrorKind> {
-        let v = parsers::number_list(parser, ListLength::Exact(4))
+        let NumberList(v) = NumberList::parse(parser, NumberListLength::Exact(4))
             .map_err(|_| ParseError::new("string does not match 'x [,] y [,] w [,] h'"))?;
 
-        let (x, y, w, h) = (v[0], v[1], v[2], v[3]);
+        let (x, y, width, height) = (v[0], v[1], v[2], v[3]);
 
-        if w >= 0.0 && h >= 0.0 {
+        if width >= 0.0 && height >= 0.0 {
             Ok(ViewBox {
                 x,
                 y,
-                width: w,
-                height: h,
+                width,
+                height,
             })
         } else {
             Err(ValueErrorKind::Value(


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