1use cssparser::Parser;
4use std::ops::Deref;
5
6use crate::error::*;
7use crate::parsers::{CommaSeparatedList, Parse};
8use crate::rect::Rect;
9
10#[derive(Debug, Copy, Clone, PartialEq)]
18pub struct ViewBox(Rect);
19
20impl Deref for ViewBox {
21 type Target = Rect;
22
23 fn deref(&self) -> &Rect {
24 &self.0
25 }
26}
27
28impl From<Rect> for ViewBox {
29 fn from(r: Rect) -> ViewBox {
30 ViewBox(r)
31 }
32}
33
34impl Parse for ViewBox {
35 fn parse<'i>(parser: &mut Parser<'i, '_>) -> Result<ViewBox, ParseError<'i>> {
44 let loc = parser.current_source_location();
45
46 let CommaSeparatedList::<f64, 4, 4>(v) = CommaSeparatedList::parse(parser)?;
47 let (x, y, width, height) = (v[0], v[1], v[2], v[3]);
48
49 if width >= 0.0 && height >= 0.0 {
50 Ok(ViewBox(Rect::new(x, y, x + width, y + height)))
51 } else {
52 Err(loc.new_custom_error(ValueErrorKind::value_error(
53 "width and height must not be negative",
54 )))
55 }
56 }
57}
58
59#[cfg(test)]
60mod tests {
61 use super::*;
62
63 #[test]
64 fn parses_valid_viewboxes() {
65 assert_eq!(
66 ViewBox::parse_str(" 1 2 3 4").unwrap(),
67 ViewBox(Rect::new(1.0, 2.0, 4.0, 6.0))
68 );
69
70 assert_eq!(
71 ViewBox::parse_str(" -1.5 -2.5e1,34,56e2 ").unwrap(),
72 ViewBox(Rect::new(-1.5, -25.0, 32.5, 5575.0))
73 );
74 }
75
76 #[test]
77 fn parsing_invalid_viewboxes_yields_error() {
78 assert!(ViewBox::parse_str("").is_err());
79 assert!(ViewBox::parse_str(" 1,2,-3,-4 ").is_err());
80 assert!(ViewBox::parse_str("qwerasdfzxcv").is_err());
81 assert!(ViewBox::parse_str(" 1 2 3 4 5").is_err());
82 assert!(ViewBox::parse_str(" 1 2 foo 3 4").is_err());
83
84 assert!(ViewBox::parse_str("0 0 9E80.7").is_err());
86 }
87}