parsers::Parse - new trait; we'll use this instead of std::FromStr

This has a Data associated type, which is passed to parse(&str, data) -> Result<>

We'll use that Data to pass RsvgLength's auxiliary data for parsing.

Hopefully this way we can have a unified way to parse attribute values
from strings, without having exceptions just because:

  a) RsvgLength needs to know the direction upon parsing/construction;

  b) We can't impl FromStr for cairo::Matrix because they both come
  from extern traits.
parent d996f282
......@@ -18,8 +18,7 @@
use ::libc;
use ::glib::translate::*;
use std::str::FromStr;
use parsers::Parse;
use parsers::ParseError;
use error::*;
......@@ -258,10 +257,11 @@ fn make_err () -> AttributeError {
AttributeError::Parse (ParseError::new ("expected \"[defer] <align> [meet | slice]\""))
}
impl FromStr for AspectRatio {
impl Parse for AspectRatio {
type Data = ();
type Err = AttributeError;
fn from_str(s: &str) -> Result<AspectRatio, AttributeError> {
fn parse(s: &str, _: ()) -> Result<AspectRatio, AttributeError> {
let mut defer = false;
let mut align: Align = Default::default ();
let mut fit_mode = FitMode::Meet;
......@@ -333,7 +333,7 @@ impl FromStr for AspectRatio {
#[no_mangle]
pub extern fn rsvg_aspect_ratio_parse (c_str: *const libc::c_char) -> u32 {
let my_str = unsafe { &String::from_glib_none (c_str) };
let parsed = AspectRatio::from_str (my_str);
let parsed = AspectRatio::parse (my_str, ());
match parsed {
Ok (aspect_ratio) => { aspect_ratio.to_u32 () },
......@@ -365,61 +365,60 @@ pub extern fn rsvg_aspect_ratio_compute (aspect: u32,
#[cfg(test)]
mod tests {
use super::*;
use std::str::FromStr;
#[test]
fn parsing_invalid_strings_yields_error () {
assert! (AspectRatio::from_str ("").is_err ());
assert! (AspectRatio::parse ("", ()).is_err ());
assert! (AspectRatio::from_str ("defer").is_err ());
assert! (AspectRatio::parse ("defer", ()).is_err ());
assert! (AspectRatio::from_str ("defer foo").is_err ());
assert! (AspectRatio::parse ("defer foo", ()).is_err ());
assert! (AspectRatio::from_str ("defer xmidymid").is_err ());
assert! (AspectRatio::parse ("defer xmidymid", ()).is_err ());
assert! (AspectRatio::from_str ("defer xMidYMid foo").is_err ());
assert! (AspectRatio::parse ("defer xMidYMid foo", ()).is_err ());
assert! (AspectRatio::from_str ("xmidymid").is_err ());
assert! (AspectRatio::parse ("xmidymid", ()).is_err ());
assert! (AspectRatio::from_str ("xMidYMid foo").is_err ());
assert! (AspectRatio::parse ("xMidYMid foo", ()).is_err ());
assert! (AspectRatio::from_str ("defer xMidYMid meet foo").is_err ());
assert! (AspectRatio::parse ("defer xMidYMid meet foo", ()).is_err ());
}
#[test]
fn parses_valid_strings () {
assert_eq! (AspectRatio::from_str ("defer none"),
assert_eq! (AspectRatio::parse ("defer none", ()),
Ok (AspectRatio { defer: true,
align: Align::None }));
assert_eq! (AspectRatio::from_str ("xMidYMid"),
assert_eq! (AspectRatio::parse ("xMidYMid", ()),
Ok (AspectRatio { defer: false,
align: Align::Aligned { align: AlignMode::XmidYmid,
fit: FitMode::Meet } }));
assert_eq! (AspectRatio::from_str ("defer xMidYMid"),
assert_eq! (AspectRatio::parse ("defer xMidYMid", ()),
Ok (AspectRatio { defer: true,
align: Align::Aligned { align: AlignMode::XmidYmid,
fit: FitMode::Meet } }));
assert_eq! (AspectRatio::from_str ("defer xMinYMax"),
assert_eq! (AspectRatio::parse ("defer xMinYMax", ()),
Ok (AspectRatio { defer: true,
align: Align::Aligned { align: AlignMode::XminYmax,
fit: FitMode::Meet } }));
assert_eq! (AspectRatio::from_str ("defer xMaxYMid meet"),
assert_eq! (AspectRatio::parse ("defer xMaxYMid meet", ()),
Ok (AspectRatio { defer: true,
align: Align::Aligned { align: AlignMode::XmaxYmid,
fit: FitMode::Meet } }));
assert_eq! (AspectRatio::from_str ("defer xMinYMax slice"),
assert_eq! (AspectRatio::parse ("defer xMinYMax slice", ()),
Ok (AspectRatio { defer: true,
align: Align::Aligned { align: AlignMode::XminYmax,
fit: FitMode::Slice } }));
}
fn test_roundtrip (s: &str) {
let a = AspectRatio::from_str (s).unwrap ();
let a = AspectRatio::parse (s, ()).unwrap ();
assert_eq! (AspectRatio::from_u32 (a.to_u32 ()), a);
}
......@@ -434,31 +433,31 @@ mod tests {
#[test]
fn aligns () {
assert_eq! (AspectRatio::from_str ("xMinYMin meet").unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 1.0), (0.0, 0.0, 0.1, 1.0));
assert_eq! (AspectRatio::from_str ("xMinYMin slice").unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 1.0), (0.0, 0.0, 10.0, 100.0));
assert_eq! (AspectRatio::parse ("xMinYMin meet", ()).unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 1.0), (0.0, 0.0, 0.1, 1.0));
assert_eq! (AspectRatio::parse ("xMinYMin slice", ()).unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 1.0), (0.0, 0.0, 10.0, 100.0));
assert_eq! (AspectRatio::from_str ("xMinYMid meet").unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 1.0), (0.0, 0.0, 0.1, 1.0));
assert_eq! (AspectRatio::from_str ("xMinYMid slice").unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 1.0), (0.0, -49.5, 10.0, 100.0));
assert_eq! (AspectRatio::parse ("xMinYMid meet", ()).unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 1.0), (0.0, 0.0, 0.1, 1.0));
assert_eq! (AspectRatio::parse ("xMinYMid slice", ()).unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 1.0), (0.0, -49.5, 10.0, 100.0));
assert_eq! (AspectRatio::from_str ("xMinYMax meet").unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 1.0), (0.0, 0.0, 0.1, 1.0));
assert_eq! (AspectRatio::from_str ("xMinYMax slice").unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 1.0), (0.0, -99.0, 10.0, 100.0));
assert_eq! (AspectRatio::parse ("xMinYMax meet", ()).unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 1.0), (0.0, 0.0, 0.1, 1.0));
assert_eq! (AspectRatio::parse ("xMinYMax slice", ()).unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 1.0), (0.0, -99.0, 10.0, 100.0));
assert_eq! (AspectRatio::from_str ("xMidYMin meet").unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 1.0), (4.95, 0.0, 0.1, 1.0));
assert_eq! (AspectRatio::from_str ("xMidYMin slice").unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 1.0), (0.0, 0.0, 10.0, 100.0));
assert_eq! (AspectRatio::parse ("xMidYMin meet", ()).unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 1.0), (4.95, 0.0, 0.1, 1.0));
assert_eq! (AspectRatio::parse ("xMidYMin slice", ()).unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 1.0), (0.0, 0.0, 10.0, 100.0));
assert_eq! (AspectRatio::from_str ("xMidYMid meet").unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 1.0), (4.95, 0.0, 0.1, 1.0));
assert_eq! (AspectRatio::from_str ("xMidYMid slice").unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 1.0), (0.0, -49.5, 10.0, 100.0));
assert_eq! (AspectRatio::parse ("xMidYMid meet", ()).unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 1.0), (4.95, 0.0, 0.1, 1.0));
assert_eq! (AspectRatio::parse ("xMidYMid slice", ()).unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 1.0), (0.0, -49.5, 10.0, 100.0));
assert_eq! (AspectRatio::from_str ("xMidYMax meet").unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 1.0), (4.95, 0.0, 0.1, 1.0));
assert_eq! (AspectRatio::from_str ("xMidYMax slice").unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 1.0), (0.0, -99.0, 10.0, 100.0));
assert_eq! (AspectRatio::parse ("xMidYMax meet", ()).unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 1.0), (4.95, 0.0, 0.1, 1.0));
assert_eq! (AspectRatio::parse ("xMidYMax slice", ()).unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 1.0), (0.0, -99.0, 10.0, 100.0));
assert_eq! (AspectRatio::from_str ("xMaxYMin meet").unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 1.0), (9.9, 0.0, 0.1, 1.0));
assert_eq! (AspectRatio::from_str ("xMaxYMin slice").unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 1.0), (0.0, 0.0, 10.0, 100.0));
assert_eq! (AspectRatio::parse ("xMaxYMin meet", ()).unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 1.0), (9.9, 0.0, 0.1, 1.0));
assert_eq! (AspectRatio::parse ("xMaxYMin slice", ()).unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 1.0), (0.0, 0.0, 10.0, 100.0));
assert_eq! (AspectRatio::from_str ("xMaxYMid meet").unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 1.0), (9.9, 0.0, 0.1, 1.0));
assert_eq! (AspectRatio::from_str ("xMaxYMid slice").unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 1.0), (0.0, -49.5, 10.0, 100.0));
assert_eq! (AspectRatio::parse ("xMaxYMid meet", ()).unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 1.0), (9.9, 0.0, 0.1, 1.0));
assert_eq! (AspectRatio::parse ("xMaxYMid slice", ()).unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 1.0), (0.0, -49.5, 10.0, 100.0));
assert_eq! (AspectRatio::from_str ("xMaxYMax meet").unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 1.0), (9.9, 0.0, 0.1, 1.0));
assert_eq! (AspectRatio::from_str ("xMaxYMax slice").unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 1.0), (0.0, -99.0, 10.0, 100.0));
assert_eq! (AspectRatio::parse ("xMaxYMax meet", ()).unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 1.0), (9.9, 0.0, 0.1, 1.0));
assert_eq! (AspectRatio::parse ("xMaxYMax slice", ()).unwrap().compute (1.0, 10.0, 0.0, 0.0, 10.0, 1.0), (0.0, -99.0, 10.0, 100.0));
}
}
......@@ -556,9 +556,9 @@ impl NodeTrait for NodeGradient {
// Attributes common to linear and radial gradients
g.common.units = property_bag::parse_or_none (pbag, "gradientUnits")?;
g.common.units = property_bag::parse_or_none (pbag, "gradientUnits", ())?;
g.common.affine = property_bag::transform_or_none (pbag, "gradientTransform")?;
g.common.spread = property_bag::parse_or_none (pbag, "spreadMethod")?;
g.common.spread = property_bag::parse_or_none (pbag, "spreadMethod", ())?;
g.common.fallback = property_bag::lookup (pbag, "xlink:href");
// Attributes specific to each gradient type. The defaults mandated by the spec
......
......@@ -4,7 +4,6 @@ use ::libc;
use std::cell::Cell;
use std::f64::consts::*;
use std::str::FromStr;
use cairo::MatrixTrait;
......@@ -17,6 +16,7 @@ use length::*;
use node::*;
use path_builder::*;
use parsers;
use parsers::Parse;
use parsers::ParseError;
use property_bag;
use property_bag::*;
......@@ -37,10 +37,11 @@ impl Default for MarkerUnits {
}
}
impl FromStr for MarkerUnits {
impl Parse for MarkerUnits {
type Data = ();
type Err = AttributeError;
fn from_str (s: &str) -> Result <MarkerUnits, AttributeError> {
fn parse (s: &str, _: ()) -> Result <MarkerUnits, AttributeError> {
match s {
"userSpaceOnUse" => Ok (MarkerUnits::UserSpaceOnUse),
"strokeWidth" => Ok (MarkerUnits::StrokeWidth),
......@@ -63,10 +64,11 @@ impl Default for MarkerOrient {
}
}
impl FromStr for MarkerOrient {
impl Parse for MarkerOrient {
type Data = ();
type Err = AttributeError;
fn from_str (s: &str) -> Result <MarkerOrient, AttributeError> {
fn parse (s: &str, _: ()) -> Result <MarkerOrient, AttributeError> {
match s {
"auto" => Ok (MarkerOrient::Auto),
_ => parsers::angle_degrees (s)
......@@ -190,7 +192,7 @@ impl NodeMarker {
impl NodeTrait for NodeMarker {
fn set_atts (&self, _: &RsvgNode, _: *const RsvgHandle, pbag: *const RsvgPropertyBag) -> NodeResult {
self.units.set (property_bag::parse_or_default (pbag, "markerUnits")?);
self.units.set (property_bag::parse_or_default (pbag, "markerUnits", ())?);
self.ref_x.set (property_bag::length_or_default (pbag, "refX", LengthDir::Horizontal)?);
self.ref_y.set (property_bag::length_or_default (pbag, "refY", LengthDir::Vertical)?);
......@@ -207,10 +209,10 @@ impl NodeTrait for NodeMarker {
.check_nonnegative ()
.map_err (|e| NodeError::attribute_error ("markerHeight", e))?);
self.orient.set (property_bag::parse_or_default (pbag, "orient")?);
self.aspect.set (property_bag::parse_or_default (pbag, "preserveAspectRatio")?);
self.vbox.set (property_bag::parse_or_none (pbag, "viewBox")?);
self.aspect.set (property_bag::parse_or_default (pbag, "preserveAspectRatio")?);
self.orient.set (property_bag::parse_or_default (pbag, "orient", ())?);
self.aspect.set (property_bag::parse_or_default (pbag, "preserveAspectRatio", ())?);
self.vbox.set (property_bag::parse_or_none (pbag, "viewBox", ())?);
self.aspect.set (property_bag::parse_or_default (pbag, "preserveAspectRatio", ())?);
Ok (())
}
......@@ -769,32 +771,32 @@ mod parser_tests {
#[test]
fn parsing_invalid_marker_units_yields_error () {
assert! (is_parse_error (&MarkerUnits::from_str ("").map_err (|e| AttributeError::from (e))));
assert! (is_parse_error (&MarkerUnits::from_str ("foo").map_err (|e| AttributeError::from (e))));
assert! (is_parse_error (&MarkerUnits::parse ("", ()).map_err (|e| AttributeError::from (e))));
assert! (is_parse_error (&MarkerUnits::parse ("foo", ()).map_err (|e| AttributeError::from (e))));
}
#[test]
fn parses_marker_units () {
assert_eq! (MarkerUnits::from_str ("userSpaceOnUse"), Ok (MarkerUnits::UserSpaceOnUse));
assert_eq! (MarkerUnits::from_str ("strokeWidth"), Ok (MarkerUnits::StrokeWidth));
assert_eq! (MarkerUnits::parse ("userSpaceOnUse", ()), Ok (MarkerUnits::UserSpaceOnUse));
assert_eq! (MarkerUnits::parse ("strokeWidth", ()), Ok (MarkerUnits::StrokeWidth));
}
#[test]
fn parsing_invalid_marker_orient_yields_error () {
assert! (is_parse_error (&MarkerOrient::from_str ("").map_err (|e| AttributeError::from (e))));
assert! (is_parse_error (&MarkerOrient::from_str ("blah").map_err (|e| AttributeError::from (e))));
assert! (is_parse_error (&MarkerOrient::from_str ("45blah").map_err (|e| AttributeError::from (e))));
assert! (is_parse_error (&MarkerOrient::parse ("", ()).map_err (|e| AttributeError::from (e))));
assert! (is_parse_error (&MarkerOrient::parse ("blah", ()).map_err (|e| AttributeError::from (e))));
assert! (is_parse_error (&MarkerOrient::parse ("45blah", ()).map_err (|e| AttributeError::from (e))));
}
#[test]
fn parses_marker_orient () {
assert_eq! (MarkerOrient::from_str ("auto"), Ok (MarkerOrient::Auto));
assert_eq! (MarkerOrient::parse ("auto", ()), Ok (MarkerOrient::Auto));
assert_eq! (MarkerOrient::from_str ("0"), Ok (MarkerOrient::Degrees (0.0)));
assert_eq! (MarkerOrient::from_str ("180"), Ok (MarkerOrient::Degrees (180.0)));
assert_eq! (MarkerOrient::from_str ("180deg"), Ok (MarkerOrient::Degrees (180.0)));
assert_eq! (MarkerOrient::from_str ("-400grad"), Ok (MarkerOrient::Degrees (-360.0)));
assert_eq! (MarkerOrient::from_str ("1rad"), Ok (MarkerOrient::Degrees (180.0 / PI)));
assert_eq! (MarkerOrient::parse ("0", ()), Ok (MarkerOrient::Degrees (0.0)));
assert_eq! (MarkerOrient::parse ("180", ()), Ok (MarkerOrient::Degrees (180.0)));
assert_eq! (MarkerOrient::parse ("180deg", ()), Ok (MarkerOrient::Degrees (180.0)));
assert_eq! (MarkerOrient::parse ("-400grad", ()), Ok (MarkerOrient::Degrees (-360.0)));
assert_eq! (MarkerOrient::parse ("1rad", ()), Ok (MarkerOrient::Degrees (180.0 / PI)));
}
}
......
use ::cairo;
use std::str::FromStr;
use error::*;
use parsers::Parse;
use parsers::ParseError;
/// Defines the units to be used for scaling paint servers, per the [svg specification].
......@@ -14,10 +13,11 @@ pub enum PaintServerUnits {
ObjectBoundingBox
}
impl FromStr for PaintServerUnits {
impl Parse for PaintServerUnits {
type Data = ();
type Err = AttributeError;
fn from_str (s: &str) -> Result<PaintServerUnits, AttributeError> {
fn parse (s: &str, _: ()) -> Result<PaintServerUnits, AttributeError> {
match s {
"userSpaceOnUse" => Ok (PaintServerUnits::UserSpaceOnUse),
"objectBoundingBox" => Ok (PaintServerUnits::ObjectBoundingBox),
......@@ -32,14 +32,14 @@ impl Default for PaintServerUnits {
}
}
// We define this as a newtype so we can impl FromStr on it
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct PaintServerSpread (pub cairo::enums::Extend);
impl FromStr for PaintServerSpread {
impl Parse for PaintServerSpread {
type Data = ();
type Err = AttributeError;
fn from_str (s: &str) -> Result <PaintServerSpread, AttributeError> {
fn parse (s: &str, _: ()) -> Result <PaintServerSpread, AttributeError> {
match s {
"pad" => Ok (PaintServerSpread (cairo::enums::Extend::Pad)),
"reflect" => Ok (PaintServerSpread (cairo::enums::Extend::Reflect)),
......@@ -58,31 +58,30 @@ impl Default for PaintServerSpread {
#[cfg(test)]
mod tests {
use super::*;
use std::str::FromStr;
#[test]
fn parsing_invalid_strings_yields_error () {
assert! (PaintServerUnits::from_str ("").is_err ());
assert! (PaintServerUnits::from_str ("foo").is_err ());
assert! (PaintServerUnits::parse ("", ()).is_err ());
assert! (PaintServerUnits::parse ("foo", ()).is_err ());
}
#[test]
fn parses_paint_server_units () {
assert_eq! (PaintServerUnits::from_str ("userSpaceOnUse"), Ok (PaintServerUnits::UserSpaceOnUse));
assert_eq! (PaintServerUnits::from_str ("objectBoundingBox"), Ok (PaintServerUnits::ObjectBoundingBox));
assert_eq! (PaintServerUnits::parse ("userSpaceOnUse", ()), Ok (PaintServerUnits::UserSpaceOnUse));
assert_eq! (PaintServerUnits::parse ("objectBoundingBox", ()), Ok (PaintServerUnits::ObjectBoundingBox));
}
#[test]
fn parses_spread_method () {
assert_eq! (PaintServerSpread::from_str ("pad"),
assert_eq! (PaintServerSpread::parse ("pad", ()),
Ok (PaintServerSpread (cairo::enums::Extend::Pad)));
assert_eq! (PaintServerSpread::from_str ("reflect"),
assert_eq! (PaintServerSpread::parse ("reflect", ()),
Ok (PaintServerSpread (cairo::enums::Extend::Reflect)));
assert_eq! (PaintServerSpread::from_str ("repeat"),
assert_eq! (PaintServerSpread::parse ("repeat", ()),
Ok (PaintServerSpread (cairo::enums::Extend::Repeat)));
assert! (PaintServerSpread::from_str ("foobar").is_err ());
assert! (PaintServerSpread::parse ("foobar", ()).is_err ());
}
}
......@@ -26,6 +26,13 @@ impl<'a> From<BasicParseError<'a>> for ParseError {
}
}
pub trait Parse: Sized {
type Data;
type Err;
fn parse (s: &str, data: Self::Data) -> Result<Self, Self::Err>;
}
// angle:
// https://www.w3.org/TR/SVG/types.html#DataTypeAngle
//
......
......@@ -5,7 +5,6 @@ use ::libc;
use std::cell::RefCell;
use std::rc::*;
use std::str::FromStr;
use cairo::MatrixTrait;
use cairo::Pattern as CairoPattern;
......@@ -19,6 +18,7 @@ use handle::RsvgHandle;
use length::*;
use node::*;
use paint_server::*;
use parsers::Parse;
use property_bag;
use property_bag::*;
use util::*;
......@@ -83,11 +83,12 @@ impl Default for PatternContentUnits {
}
}
impl FromStr for PatternContentUnits {
impl Parse for PatternContentUnits {
type Data = ();
type Err = AttributeError;
fn from_str (s: &str) -> Result<PatternContentUnits, AttributeError> {
Ok (PatternContentUnits::from (PaintServerUnits::from_str (s)?))
fn parse (s: &str, _: ()) -> Result<PatternContentUnits, AttributeError> {
Ok (PatternContentUnits::from (PaintServerUnits::parse (s, ())?))
}
}
......@@ -198,11 +199,11 @@ impl NodeTrait for NodePattern {
p.node = Some (Rc::downgrade (node));
p.units = property_bag::parse_or_none (pbag, "patternUnits")?;
p.content_units = property_bag::parse_or_none (pbag, "patternContentUnits")?;
p.vbox = property_bag::parse_or_none (pbag, "viewBox")?.map (Some).or (None);
p.units = property_bag::parse_or_none (pbag, "patternUnits", ())?;
p.content_units = property_bag::parse_or_none (pbag, "patternContentUnits", ())?;
p.vbox = property_bag::parse_or_none (pbag, "viewBox", ())?.map (Some).or (None);
p.preserve_aspect_ratio = property_bag::parse_or_none (pbag, "preserveAspectRatio")?;
p.preserve_aspect_ratio = property_bag::parse_or_none (pbag, "preserveAspectRatio", ())?;
p.affine = property_bag::transform_or_none (pbag, "patternTransform")?;
......
......@@ -2,11 +2,10 @@ use ::cairo;
use ::glib::translate::*;
use ::libc;
use std::str::FromStr;
use error::*;
use length::*;
use transform::*;
use parsers::Parse;
pub enum RsvgPropertyBag {}
......@@ -66,14 +65,14 @@ pub fn length_or_value (pbag: *const RsvgPropertyBag, key: &'static str, length_
}
}
pub fn parse_or_none<T> (pbag: *const RsvgPropertyBag, key: &'static str) -> Result <Option<T>, NodeError>
where T: FromStr<Err = AttributeError>
pub fn parse_or_none<T> (pbag: *const RsvgPropertyBag, key: &'static str, data: <T as Parse>::Data) -> Result <Option<T>, NodeError>
where T: Parse<Err = AttributeError>
{
let value = lookup (pbag, key);
match value {
Some (v) => {
T::from_str (&v).map (|v| Some (v))
T::parse (&v, data).map (|v| Some (v))
.map_err (|e| NodeError::attribute_error (key, e))
},
......@@ -81,16 +80,16 @@ pub fn parse_or_none<T> (pbag: *const RsvgPropertyBag, key: &'static str) -> Res
}
}
pub fn parse_or_default<T> (pbag: *const RsvgPropertyBag, key: &'static str) -> Result <T, NodeError>
where T: Default + FromStr<Err = AttributeError> + Copy
pub fn parse_or_default<T> (pbag: *const RsvgPropertyBag, key: &'static str, data: <T as Parse>::Data) -> Result <T, NodeError>
where T: Default + Parse<Err = AttributeError> + Copy
{
parse_or_value (pbag, key, T::default ())
parse_or_value (pbag, key, data, T::default ())
}
pub fn parse_or_value<T> (pbag: *const RsvgPropertyBag, key: &'static str, value: T) -> Result <T, NodeError>
where T: Default + FromStr<Err = AttributeError> + Copy
pub fn parse_or_value<T> (pbag: *const RsvgPropertyBag, key: &'static str, data: <T as Parse>::Data, value: T) -> Result <T, NodeError>
where T: Default + Parse<Err = AttributeError> + Copy
{
let r = parse_or_none::<T> (pbag, key);
let r = parse_or_none::<T> (pbag, key, data);
match r {
Ok (Some (v)) => Ok (v),
......
......@@ -135,7 +135,7 @@ impl NodeSvg {
impl NodeTrait for NodeSvg {
fn set_atts (&self, node: &RsvgNode, _: *const RsvgHandle, pbag: *const RsvgPropertyBag) -> NodeResult {
self.preserve_aspect_ratio.set (property_bag::parse_or_default (pbag, "preserveAspectRatio")?);
self.preserve_aspect_ratio.set (property_bag::parse_or_default (pbag, "preserveAspectRatio", ())?);
// x & y attributes have no effect on outermost svg
// http://www.w3.org/TR/SVG/struct.html#SVGElement
......@@ -152,7 +152,7 @@ impl NodeTrait for NodeSvg {
.and_then (|l| l.check_nonnegative ()
.map_err (|e| NodeError::attribute_error ("height", e)))?);
self.vbox.set (property_bag::parse_or_none (pbag, "viewBox")?);
self.vbox.set (property_bag::parse_or_none (pbag, "viewBox", ())?);
// The "style" sub-element is not loaded yet here, so we need
// to store other attributes to be applied later.
......@@ -419,8 +419,8 @@ impl NodeSymbol {
impl NodeTrait for NodeSymbol {
fn set_atts (&self, _: &RsvgNode, _: *const RsvgHandle, pbag: *const RsvgPropertyBag) -> NodeResult {
self.preserve_aspect_ratio.set (property_bag::parse_or_default (pbag, "preserveAspectRatio")?);
self.vbox.set (property_bag::parse_or_none (pbag, "viewBox")?);
self.preserve_aspect_ratio.set (property_bag::parse_or_default (pbag, "preserveAspectRatio", ())?);
self.vbox.set (property_bag::parse_or_none (pbag, "viewBox", ())?);
Ok (())
}
......
......@@ -2,10 +2,9 @@ use ::cairo;
use ::glib_sys;
use ::glib;
use std::str::FromStr;
use error::*;
use parsers;
use parsers::Parse;
use parsers::{ListLength, ParseError};
use self::glib::translate::*;
......@@ -40,7 +39,8 @@ impl From<Option<ViewBox>> for RsvgViewBox {
}
}
impl FromStr for ViewBox {
impl Parse for ViewBox {
type Data = ();
type Err = AttributeError;
// Parse a viewBox attribute
......@@ -51,7 +51,7 @@ impl FromStr for ViewBox {
// x, y, w, h
//
// Where w and h must be nonnegative.
fn from_str (s: &str) -> Result<ViewBox, AttributeError> {
fn parse (s: &str, _: ()) -> Result<ViewBox, AttributeError> {
let v = parsers::number_list (s, ListLength::Exact (4))
.map_err (|_| ParseError::new ("string does not match 'x [,] y [,] w [,] h'"))?;
......@@ -71,17 +71,16 @@ impl FromStr for ViewBox {
#[cfg(test)]
mod tests {
use super::*;
use std::str::FromStr;
#[test]
fn parses_valid_viewboxes () {
assert_eq! (ViewBox::from_str (" 1 2 3 4"),
assert_eq! (ViewBox::parse (" 1 2 3 4", ()),
Ok (ViewBox (cairo::Rectangle { x: 1.0,
y: 2.0,
width: 3.0,
height: 4.0 })));
assert_eq! (ViewBox::from_str (" -1.5 -2.5e1,34,56e2 "),
assert_eq! (ViewBox::parse (" -1.5 -2.5e1,34,56e2 ", ()),
Ok (ViewBox (cairo::Rectangle { x: -1.5,
y: -25.0,
width: 34.0,
......@@ -90,14 +89,14 @@ mod tests {
#[test]
fn parsing_invalid_viewboxes_yields_error () {
assert! (is_parse_error (&ViewBox::from_str ("")));
assert! (is_parse_error (&ViewBox::parse ("", ())));
assert! (is_value_error (&ViewBox::from_str (" 1,2,-3,-4 ")));
assert! (is_value_error (&ViewBox::parse (" 1,2,-3,-4 ", ())));
assert! (is_parse_error (&ViewBox::from_str ("qwerasdfzxcv")));
assert! (is_parse_error (&ViewBox::parse ("qwerasdfzxcv", ())));
assert! (is_parse_error (&ViewBox::from_str (" 1 2 3 4 5")));
assert! (is_parse_error (&ViewBox::parse (" 1 2 3 4 5", ())));
assert! (is_parse_error (&ViewBox::from_str (" 1 2 foo 3 4")));
assert! (is_parse_error (&ViewBox::parse (" 1 2 foo 3 4", ())));
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment