[librsvg: 2/3] number_list: refactor a NumberList type
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg: 2/3] number_list: refactor a NumberList type
- Date: Sat, 19 Jan 2019 00:28:39 +0000 (UTC)
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]