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