svgtypes/
paint_order.rs
1use crate::stream::Stream;
5
6#[derive(Clone, Copy, PartialEq, Eq, Debug)]
10#[allow(missing_docs)]
11pub enum PaintOrderKind {
12 Fill,
13 Stroke,
14 Markers,
15}
16
17#[derive(Clone, Copy, PartialEq, Eq, Debug)]
21pub struct PaintOrder {
22 pub order: [PaintOrderKind; 3],
26}
27
28impl Default for PaintOrder {
29 #[inline]
30 fn default() -> Self {
31 Self {
32 order: [
33 PaintOrderKind::Fill,
34 PaintOrderKind::Stroke,
35 PaintOrderKind::Markers,
36 ],
37 }
38 }
39}
40
41impl From<[PaintOrderKind; 3]> for PaintOrder {
42 #[inline]
43 fn from(order: [PaintOrderKind; 3]) -> Self {
44 Self { order }
45 }
46}
47
48impl std::str::FromStr for PaintOrder {
49 type Err = ();
50
51 fn from_str(text: &str) -> Result<Self, Self::Err> {
55 let mut order = Vec::new();
56
57 let mut left = vec![
58 PaintOrderKind::Fill,
59 PaintOrderKind::Stroke,
60 PaintOrderKind::Markers,
61 ];
62
63 let mut s = Stream::from(text);
64 while !s.at_end() && order.len() < 3 {
65 s.skip_spaces();
66 let name = s.consume_ascii_ident();
67 s.skip_spaces();
68 let name = match name {
69 "normal" => return Ok(PaintOrder::default()),
71 "fill" => PaintOrderKind::Fill,
72 "stroke" => PaintOrderKind::Stroke,
73 "markers" => PaintOrderKind::Markers,
74 _ => return Ok(PaintOrder::default()),
75 };
76
77 if let Some(index) = left.iter().position(|v| *v == name) {
78 left.remove(index);
79 }
80
81 order.push(name);
82 }
83
84 s.skip_spaces();
85 if !s.at_end() {
86 return Ok(PaintOrder::default());
88 }
89
90 if order.is_empty() {
91 return Ok(PaintOrder::default());
92 }
93
94 while order.len() < 3 && !left.is_empty() {
96 order.push(left.remove(0));
97 }
98
99 if order[0] == order[1] || order[0] == order[2] || order[1] == order[2] {
101 return Ok(PaintOrder::default());
103 }
104
105 Ok(PaintOrder {
106 order: [order[0], order[1], order[2]],
107 })
108 }
109}
110
111#[rustfmt::skip]
112#[cfg(test)]
113mod tests {
114 use super::*;
115 use std::str::FromStr;
116
117 #[test]
118 fn parse_1() {
119 assert_eq!(PaintOrder::from_str("normal").unwrap(), PaintOrder::default());
120 }
121
122 #[test]
123 fn parse_2() {
124 assert_eq!(PaintOrder::from_str("qwe").unwrap(), PaintOrder::default());
125 }
126
127 #[test]
128 fn parse_3() {
129 assert_eq!(PaintOrder::from_str("").unwrap(), PaintOrder::default());
130 }
131
132 #[test]
133 fn parse_4() {
134 assert_eq!(PaintOrder::from_str("stroke qwe").unwrap(), PaintOrder::default());
135 }
136
137 #[test]
138 fn parse_5() {
139 assert_eq!(PaintOrder::from_str("stroke stroke").unwrap(), PaintOrder::default());
140 }
141
142 #[test]
143 fn parse_6() {
144 assert_eq!(PaintOrder::from_str("stroke").unwrap(), PaintOrder::from([
145 PaintOrderKind::Stroke, PaintOrderKind::Fill, PaintOrderKind::Markers
146 ]));
147 }
148
149 #[test]
150 fn parse_7() {
151 assert_eq!(PaintOrder::from_str("stroke markers").unwrap(), PaintOrder::from([
152 PaintOrderKind::Stroke, PaintOrderKind::Markers, PaintOrderKind::Fill
153 ]));
154 }
155
156 #[test]
157 fn parse_8() {
158 assert_eq!(PaintOrder::from_str("stroke markers fill").unwrap(), PaintOrder::from([
159 PaintOrderKind::Stroke, PaintOrderKind::Markers, PaintOrderKind::Fill
160 ]));
161 }
162
163 #[test]
164 fn parse_9() {
165 assert_eq!(PaintOrder::from_str("markers").unwrap(), PaintOrder::from([
166 PaintOrderKind::Markers, PaintOrderKind::Fill, PaintOrderKind::Stroke
167 ]));
168 }
169
170 #[test]
171 fn parse_10() {
172 assert_eq!(PaintOrder::from_str(" stroke\n").unwrap(), PaintOrder::from([
173 PaintOrderKind::Stroke, PaintOrderKind::Fill, PaintOrderKind::Markers
174 ]));
175 }
176
177 #[test]
178 fn parse_11() {
179 assert_eq!(PaintOrder::from_str("stroke stroke stroke stroke").unwrap(), PaintOrder::default());
180 }
181}