gpui_ce_motion/vector/
parser.rs1use super::{PathCommand, PathError, PathShape};
3use std::fmt;
4
5#[derive(Debug)]
7pub enum SvgPathError {
8 Syntax(svgtypes::Error),
10 Geometry(PathError),
12}
13
14impl fmt::Display for SvgPathError {
15 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
16 match self {
17 Self::Syntax(error) => write!(f, "invalid SVG path: {error}"),
18 Self::Geometry(error) => error.fmt(f),
19 }
20 }
21}
22
23impl std::error::Error for SvgPathError {
24 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
25 match self {
26 Self::Syntax(error) => Some(error),
27 Self::Geometry(error) => Some(error),
28 }
29 }
30}
31
32impl PathShape {
33 #[cfg_attr(feature = "svg-path", doc = "```")]
42 #[cfg_attr(feature = "svg-path", doc = "use gpui_ce_motion::PathShape;")]
43 #[cfg_attr(
44 feature = "svg-path",
45 doc = "let path = PathShape::parse_svg(\"M0 0h20a10 10 0 0 1 10 10z\").unwrap();"
46 )]
47 #[cfg_attr(feature = "svg-path", doc = "assert!(path.commands().len() >= 4);")]
48 #[cfg_attr(feature = "svg-path", doc = "```")]
49 pub fn parse_svg(data: &str) -> Result<Self, SvgPathError> {
50 if data.len() > 1_048_576 {
51 return Err(SvgPathError::Geometry(PathError::Complexity));
52 }
53
54 let mut commands = Vec::new();
55
56 for segment in svgtypes::SimplifyingPathParser::from(data) {
57 if commands.len() >= 65_536 {
58 return Err(SvgPathError::Geometry(PathError::Complexity));
59 }
60
61 let command = match segment.map_err(SvgPathError::Syntax)? {
62 svgtypes::SimplePathSegment::MoveTo { x, y } => PathCommand::Move([x, y]),
63 svgtypes::SimplePathSegment::LineTo { x, y } => PathCommand::Line([x, y]),
64 svgtypes::SimplePathSegment::CurveTo {
65 x1,
66 y1,
67 x2,
68 y2,
69 x,
70 y,
71 } => PathCommand::Cubic([x1, y1], [x2, y2], [x, y]),
72 svgtypes::SimplePathSegment::Quadratic { x1, y1, x, y } => {
73 PathCommand::Quadratic([x1, y1], [x, y])
74 }
75 svgtypes::SimplePathSegment::ClosePath => PathCommand::Close,
76 };
77
78 commands.push(command);
79 }
80
81 Self::new(commands).map_err(SvgPathError::Geometry)
82 }
83}