[librsvg: 1/3] parser: use const generics for NumberList
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg: 1/3] parser: use const generics for NumberList
- Date: Mon, 3 May 2021 17:18:27 +0000 (UTC)
commit 3b4bb2430c98766185493ec91b51ac8647ed07e9
Author: Paolo Borelli <pborelli gnome org>
Date: Sun May 2 16:33:56 2021 +0200
parser: use const generics for NumberList
src/filters/color_matrix.rs | 5 +--
src/filters/component_transfer.rs | 9 ++--
src/filters/convolve_matrix.rs | 8 ++--
src/parsers.rs | 94 +++++++++++++--------------------------
src/viewbox.rs | 5 +--
5 files changed, 42 insertions(+), 79 deletions(-)
---
diff --git a/src/filters/color_matrix.rs b/src/filters/color_matrix.rs
index a39e4f38..46f5257c 100644
--- a/src/filters/color_matrix.rs
+++ b/src/filters/color_matrix.rs
@@ -7,7 +7,7 @@ use crate::drawing_ctx::DrawingCtx;
use crate::element::{ElementResult, SetAttributes};
use crate::error::*;
use crate::node::{CascadedValues, Node};
-use crate::parsers::{NumberList, NumberListLength, Parse, ParseValue};
+use crate::parsers::{NumberList, Parse, ParseValue};
use crate::property_defs::ColorInterpolationFilters;
use crate::rect::IRect;
use crate::surface_utils::{
@@ -95,8 +95,7 @@ impl SetAttributes for FeColorMatrix {
let new_matrix = match operation_type {
OperationType::LuminanceToAlpha => unreachable!(),
OperationType::Matrix => {
- let NumberList(v) =
- NumberList::parse_str(value, NumberListLength::Exact(20))
+ let NumberList::<20, 20>(v) = NumberList::parse_str(value)
.attribute(attr)?;
let matrix = Matrix4x5::from_row_slice(&v);
let mut matrix = matrix.fixed_resize(0.0);
diff --git a/src/filters/component_transfer.rs b/src/filters/component_transfer.rs
index 11259d1e..e38f3991 100644
--- a/src/filters/component_transfer.rs
+++ b/src/filters/component_transfer.rs
@@ -8,7 +8,7 @@ use crate::drawing_ctx::DrawingCtx;
use crate::element::{Draw, Element, ElementResult, SetAttributes};
use crate::error::*;
use crate::node::{CascadedValues, Node, NodeBorrow};
-use crate::parsers::{NumberList, NumberListLength, Parse, ParseValue};
+use crate::parsers::{NumberList, Parse, ParseValue};
use crate::property_defs::ColorInterpolationFilters;
use crate::rect::IRect;
use crate::surface_utils::{
@@ -219,10 +219,9 @@ macro_rules! func_x {
match attr.expanded() {
expanded_name!("", "type") => self.function_type = attr.parse(value)?,
expanded_name!("", "tableValues") => {
- let NumberList(v) =
- // #691: Limit list to 256 to mitigate malicious SVGs
- NumberList::parse_str(value, NumberListLength::MaxLength(256))
- .attribute(attr)?;
+ // #691: Limit list to 256 to mitigate malicious SVGs
+ let NumberList::<0, 256>(v) =
+ NumberList::parse_str(value).attribute(attr)?;
self.table_values = v;
}
expanded_name!("", "slope") => self.slope = attr.parse(value)?,
diff --git a/src/filters/convolve_matrix.rs b/src/filters/convolve_matrix.rs
index 3b802e2c..8f77d2d8 100644
--- a/src/filters/convolve_matrix.rs
+++ b/src/filters/convolve_matrix.rs
@@ -7,9 +7,7 @@ use crate::drawing_ctx::DrawingCtx;
use crate::element::{ElementResult, SetAttributes};
use crate::error::*;
use crate::node::{CascadedValues, Node};
-use crate::parsers::{
- NonNegative, NumberList, NumberListLength, NumberOptionalNumber, Parse, ParseValue,
-};
+use crate::parsers::{NonNegative, NumberList, NumberOptionalNumber, Parse, ParseValue};
use crate::property_defs::ColorInterpolationFilters;
use crate::rect::IRect;
use crate::surface_utils::{
@@ -109,8 +107,8 @@ impl SetAttributes for FeConvolveMatrix {
// #352: Parse as an unbounded list rather than exact length to prevent aborts due
// to huge allocation attempts by underlying Vec::with_capacity().
// #691: Limit list to 400 (20x20) to mitigate malicious SVGs
- let NumberList(v) = NumberList::parse_str(value, NumberListLength::MaxLength(400))
- .attribute(attr.clone())?;
+ let NumberList::<0, 400>(v) =
+ NumberList::parse_str(value).attribute(attr.clone())?;
// #691: Update check as v.len can be different than number of elements because
// of the above limit (and will = 400 if that happens)
if v.len() != number_of_elements && v.len() != 400 {
diff --git a/src/parsers.rs b/src/parsers.rs
index 51eb84a8..75b1db48 100644
--- a/src/parsers.rs
+++ b/src/parsers.rs
@@ -131,70 +131,38 @@ impl Parse for u32 {
}
}
-#[derive(Eq, PartialEq)]
-pub enum NumberListLength {
- MaxLength(usize),
- Exact(usize),
-}
-
-#[derive(Debug, PartialEq)]
-pub struct NumberList(pub Vec<f64>);
-
/// CSS number-list values.
-impl NumberList {
- pub fn parse<'i>(
- parser: &mut Parser<'i, '_>,
- length: NumberListLength,
- ) -> Result<Self, ParseError<'i>> {
- let mut v = match length {
- NumberListLength::MaxLength(l) if l > 0 => Vec::<f64>::with_capacity(l),
- NumberListLength::MaxLength(_) => {
- //cargo fmt suggests this formatting for some reason
- unreachable!("NumberListLength::MaxLength cannot be 0")
- }
- NumberListLength::Exact(l) if l > 0 => Vec::<f64>::with_capacity(l),
- NumberListLength::Exact(_) => unreachable!("NumberListLength::Exact cannot be 0"),
- };
+#[derive(Debug, PartialEq)]
+pub struct NumberList<const REQUIRED: usize, const MAX: usize>(pub Vec<f64>);
- for i in 0.. {
+impl<const REQUIRED: usize, const MAX: usize> NumberList<REQUIRED, MAX> {
+ pub fn parse<'i>(parser: &mut Parser<'i, '_>) -> Result<Self, ParseError<'i>> {
+ let loc = parser.current_source_location();
+ let mut v = Vec::<f64>::with_capacity(MAX);
+ for i in 0..MAX {
if i != 0 {
optional_comma(parser);
}
v.push(f64::parse(parser)?);
- if let NumberListLength::MaxLength(l) = length {
- if i + 1 == l {
- break;
- }
- }
-
- 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,
- }
+ break;
}
}
- Ok(NumberList(v))
+ if REQUIRED > 0 && v.len() < REQUIRED {
+ Err(loc.new_custom_error(ValueErrorKind::value_error("expected more numbers")))
+ } else {
+ Ok(NumberList(v))
+ }
}
- pub fn parse_str(s: &str, length: NumberListLength) -> Result<NumberList, ParseError<'_>> {
+ pub fn parse_str(s: &str) -> Result<Self, ParseError<'_>> {
let mut input = ParserInput::new(s);
let mut parser = Parser::new(&mut input);
- let res = Self::parse(&mut parser, length)?;
+ let res = Self::parse(&mut parser)?;
parser.expect_exhausted()?;
Ok(res)
}
@@ -374,22 +342,22 @@ mod tests {
#[test]
fn parses_number_list() {
assert_eq!(
- NumberList::parse_str("5", NumberListLength::Exact(1)).unwrap(),
+ NumberList::<1, 1>::parse_str("5").unwrap(),
NumberList(vec![5.0])
);
assert_eq!(
- NumberList::parse_str("1 2 3 4", NumberListLength::Exact(4)).unwrap(),
+ NumberList::<4, 4>::parse_str("1 2 3 4").unwrap(),
NumberList(vec![1.0, 2.0, 3.0, 4.0])
);
assert_eq!(
- NumberList::parse_str("1 2 3 4 5", NumberListLength::MaxLength(5)).unwrap(),
+ NumberList::<0, 5>::parse_str("1 2 3 4 5").unwrap(),
NumberList(vec![1.0, 2.0, 3.0, 4.0, 5.0])
);
assert_eq!(
- NumberList::parse_str("1 2 3", NumberListLength::MaxLength(5)).unwrap(),
+ NumberList::<0, 5>::parse_str("1 2 3").unwrap(),
NumberList(vec![1.0, 2.0, 3.0])
);
}
@@ -397,26 +365,26 @@ mod tests {
#[test]
fn errors_on_invalid_number_list() {
// empty
- assert!(NumberList::parse_str("", NumberListLength::Exact(1)).is_err());
- assert!(NumberList::parse_str("", NumberListLength::MaxLength(1)).is_err());
+ assert!(NumberList::<1, 1>::parse_str("").is_err());
+ assert!(NumberList::<0, 1>::parse_str("").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());
+ assert!(NumberList::<1, 1>::parse_str("foo").is_err());
+ assert!(NumberList::<2, 2>::parse_str("1foo").is_err());
+ assert!(NumberList::<2, 2>::parse_str("1 foo").is_err());
+ assert!(NumberList::<2, 2>::parse_str("1 foo 2").is_err());
+ assert!(NumberList::<2, 2>::parse_str("1,foo").is_err());
// too many
- assert!(NumberList::parse_str("1 2", NumberListLength::Exact(1)).is_err());
+ assert!(NumberList::<1, 1>::parse_str("1 2").is_err());
// extra token
- assert!(NumberList::parse_str("1,", NumberListLength::Exact(1)).is_err());
- assert!(NumberList::parse_str("1,", NumberListLength::MaxLength(1)).is_err());
+ assert!(NumberList::<1, 1>::parse_str("1,").is_err());
+ assert!(NumberList::<0, 1>::parse_str("1,").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());
+ assert!(NumberList::<2, 2>::parse_str("1").is_err());
+ assert!(NumberList::<3, 3>::parse_str("1 2").is_err());
}
#[test]
diff --git a/src/viewbox.rs b/src/viewbox.rs
index b979f216..b9be4d8b 100644
--- a/src/viewbox.rs
+++ b/src/viewbox.rs
@@ -4,7 +4,7 @@ use cssparser::Parser;
use std::ops::Deref;
use crate::error::*;
-use crate::parsers::{NumberList, NumberListLength, Parse};
+use crate::parsers::{NumberList, Parse};
use crate::rect::Rect;
/// Newtype around a [`Rect`], used to represent the `viewBox` attribute.
@@ -45,8 +45,7 @@ impl Parse for ViewBox {
fn parse<'i>(parser: &mut Parser<'i, '_>) -> Result<ViewBox, ParseError<'i>> {
let loc = parser.current_source_location();
- let NumberList(v) = NumberList::parse(parser, NumberListLength::Exact(4))?;
-
+ let NumberList::<4, 4>(v) = NumberList::parse(parser)?;
let (x, y, width, height) = (v[0], v[1], v[2], v[3]);
if width >= 0.0 && height >= 0.0 {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]