1use ::core::str::Bytes;
4
5use crate::mappings::{from_ascii_byte, SegmentBits};
6
7#[derive(Debug, Clone)]
27pub struct StrParser<'a> {
28 bytes: Bytes<'a>,
29 current: Option<u8>,
30 or: u8,
37 size: usize,
38}
39
40#[cfg(feature = "defmt")]
41impl defmt::Format for StrParser<'_> {
42 fn format(&self, fmt: defmt::Formatter) {
43 defmt::write!(fmt, "StrParser {{ .. }}")
44 }
45}
46
47impl<'a> StrParser<'a> {
48 pub fn new(str: &'a str) -> Self {
50 Self {
51 bytes: str.bytes(),
52 current: None,
53 or: 0,
54 size: str.bytes().filter(|byte| *byte != b'.').count(),
55 }
56 }
57}
58
59impl<'a> From<&'a str> for StrParser<'a> {
60 fn from(value: &'a str) -> Self {
61 Self::new(value)
62 }
63}
64
65impl Iterator for StrParser<'_> {
66 type Item = u8;
67
68 fn next(&mut self) -> Option<Self::Item> {
69 if self.size == 0 {
70 return None;
71 }
72
73 loop {
74 match self.bytes.next() {
75 Some(byte) => match byte {
76 b'.' => match self.current.take() {
77 Some(current) => {
78 self.size -= 1;
79
80 return Some(from_ascii_byte(current) | SegmentBits::Dot as u8);
81 }
82 None => continue,
83 },
84 byte => match self.current.replace(byte) {
85 Some(current) => {
86 self.size -= 1;
87
88 return Some(from_ascii_byte(current));
89 }
90 None => self.current = Some(byte),
91 },
92 },
93 None => match self.current.take().map(from_ascii_byte) {
94 Some(current) => {
95 self.size -= 1;
96
97 return Some(current);
98 }
99 None => return None,
100 },
101 }
102 }
103 }
104
105 fn size_hint(&self) -> (usize, Option<usize>) {
106 (self.size, Some(self.size))
107 }
108}
109
110impl ExactSizeIterator for StrParser<'_> {}
111
112impl DoubleEndedIterator for StrParser<'_> {
113 fn next_back(&mut self) -> Option<Self::Item> {
114 if self.size == 0 {
115 return None;
116 }
117
118 loop {
119 match self.bytes.next_back() {
120 Some(byte) => match byte {
121 b'.' => {
122 self.or = SegmentBits::Dot as u8;
123
124 continue;
125 }
126 byte => {
127 let byte = from_ascii_byte(byte) | self.or;
128
129 self.or = 0;
130 self.size -= 1;
131
132 return Some(byte);
133 }
134 },
135 None => match self.current.take() {
136 Some(current) => {
137 let byte = from_ascii_byte(current) | self.or;
138
139 self.or = 0;
140 self.size -= 1;
141
142 return Some(byte);
143 }
144 None => return None,
145 },
146 }
147 }
148 }
149}
150
151#[cfg(test)]
152mod tests {
153 extern crate std;
154 use std::vec;
155 use std::vec::Vec;
156
157 use crate::mappings::{DigitBits, UpCharBits};
158
159 use super::*;
160
161 #[test]
162 fn no_dots() {
163 let parser = StrParser::new("1234");
164 let result: Vec<u8> = parser.collect();
165
166 assert_eq!(
167 vec![
168 DigitBits::One as u8,
169 DigitBits::Two as u8,
170 DigitBits::Three as u8,
171 DigitBits::Four as u8
172 ],
173 result
174 );
175 }
176
177 #[test]
178 fn len() {
179 let mut parser = StrParser::new("..12.3..45..............6.7");
180
181 assert_eq!(7, parser.len());
182 parser.next();
183 assert_eq!(6, parser.len());
184 parser.next();
185 assert_eq!(5, parser.len());
186 parser.next();
187 assert_eq!(4, parser.len());
188 parser.next();
189 assert_eq!(3, parser.len());
190 parser.next();
191 assert_eq!(2, parser.len());
192 parser.next();
193 assert_eq!(1, parser.len());
194 parser.next();
195 assert_eq!(0, parser.len());
196 assert_eq!(None, parser.next());
197 assert_eq!(0, parser.len());
198 }
199
200 #[test]
201 fn dots() {
202 let parser = StrParser::new("..12.3..45..............6.7");
203 let result: Vec<u8> = parser.collect();
204 assert_eq!(
205 vec![
206 DigitBits::One as u8,
207 DigitBits::Two as u8 | SegmentBits::Dot as u8,
208 DigitBits::Three as u8 | SegmentBits::Dot as u8,
209 DigitBits::Four as u8,
210 DigitBits::Five as u8 | SegmentBits::Dot as u8,
211 DigitBits::Six as u8 | SegmentBits::Dot as u8,
212 DigitBits::Seven as u8
213 ],
214 result
215 );
216 }
217
218 #[test]
219 fn no_dots_rev() {
220 let parser = StrParser::new("1234");
221 let result: Vec<u8> = parser.rev().collect();
222 let mut expected = vec![
223 DigitBits::One as u8,
224 DigitBits::Two as u8,
225 DigitBits::Three as u8,
226 DigitBits::Four as u8,
227 ];
228 expected.reverse();
229 assert_eq!(expected, result);
230 }
231
232 #[test]
233 fn dots_rev() {
234 let parser = StrParser::new("HE.LLO");
235 let result: Vec<u8> = parser.take(3).rev().collect();
236
237 assert_eq!(
238 vec![
239 UpCharBits::UpH as u8,
240 UpCharBits::UpE as u8 | SegmentBits::Dot as u8,
241 UpCharBits::UpL as u8,
242 ]
243 .into_iter()
244 .rev()
245 .collect::<Vec<_>>(),
246 result
247 );
248
249 let parser = StrParser::new("..12.3..45..............6.7");
250 let result: Vec<u8> = parser.rev().collect();
251 let mut expected = vec![
252 DigitBits::One as u8,
253 DigitBits::Two as u8 | SegmentBits::Dot as u8,
254 DigitBits::Three as u8 | SegmentBits::Dot as u8,
255 DigitBits::Four as u8,
256 DigitBits::Five as u8 | SegmentBits::Dot as u8,
257 DigitBits::Six as u8 | SegmentBits::Dot as u8,
258 DigitBits::Seven as u8,
259 ];
260 expected.reverse();
261 assert_eq!(expected, result);
262 }
263
264 #[test]
265 fn back_and_forth() {
266 let mut parser = StrParser::new("..12.3..45..............6.7");
267
268 assert_eq!(7, parser.len());
269
270 assert_eq!(Some(DigitBits::One as u8), parser.next());
271 assert_eq!(6, parser.len());
272
273 assert_eq!(
274 Some(DigitBits::Two as u8 | SegmentBits::Dot as u8),
275 parser.next()
276 );
277 assert_eq!(5, parser.len());
278
279 assert_eq!(Some(DigitBits::Seven as u8), parser.next_back());
280 assert_eq!(4, parser.len());
281
282 assert_eq!(
283 Some(DigitBits::Three as u8 | SegmentBits::Dot as u8),
284 parser.next()
285 );
286 assert_eq!(3, parser.len());
287
288 assert_eq!(
289 Some(DigitBits::Six as u8 | SegmentBits::Dot as u8),
290 parser.next_back()
291 );
292 assert_eq!(2, parser.len());
293
294 assert_eq!(Some(DigitBits::Four as u8), parser.next());
295 assert_eq!(1, parser.len());
296
297 assert_eq!(
298 Some(DigitBits::Five as u8 | SegmentBits::Dot as u8),
299 parser.next()
300 );
301 assert_eq!(0, parser.len());
302
303 assert_eq!(None, parser.next_back());
304 assert_eq!(None, parser.next());
305 assert_eq!(0, parser.len());
306 }
307
308 #[test]
309 fn overlap() {
310 let mut parser = StrParser::new("12345");
311
312 assert_eq!(5, parser.len());
313
314 assert_eq!(Some(DigitBits::One as u8), parser.next());
315 assert_eq!(4, parser.len());
316
317 assert_eq!(Some(DigitBits::Two as u8), parser.next());
318 assert_eq!(3, parser.len());
319
320 assert_eq!(Some(DigitBits::Three as u8), parser.next());
321 assert_eq!(2, parser.len());
322
323 assert_eq!(Some(DigitBits::Five as u8), parser.next_back());
324 assert_eq!(1, parser.len());
325
326 assert_eq!(Some(DigitBits::Four as u8), parser.next_back());
327 assert_eq!(0, parser.len());
328
329 assert_eq!(None, parser.next());
330 assert_eq!(None, parser.next_back());
331 assert_eq!(0, parser.len());
332 }
333
334 #[test]
335 fn overlap_dots_on_next() {
336 let mut parser = StrParser::new("12.3");
337
338 assert_eq!(3, parser.len());
339
340 assert_eq!(Some(DigitBits::One as u8), parser.next());
341 assert_eq!(2, parser.len());
342
343 assert_eq!(Some(DigitBits::Three as u8), parser.next_back());
344 assert_eq!(1, parser.len());
345
346 assert_eq!(
347 Some(DigitBits::Two as u8 | SegmentBits::Dot as u8),
348 parser.next()
349 );
350 assert_eq!(0, parser.len());
351
352 assert_eq!(None, parser.next());
353 assert_eq!(None, parser.next_back());
354 assert_eq!(0, parser.len());
355 }
356
357 #[test]
358 fn overlap_dots_on_next_back() {
359 let mut parser = StrParser::new("12...3");
360
361 assert_eq!(3, parser.len());
362
363 assert_eq!(Some(DigitBits::One as u8), parser.next());
364 assert_eq!(2, parser.len());
365
366 assert_eq!(Some(DigitBits::Three as u8), parser.next_back());
367 assert_eq!(1, parser.len());
368
369 assert_eq!(
370 Some(DigitBits::Two as u8 | SegmentBits::Dot as u8),
371 parser.next_back()
372 );
373 assert_eq!(0, parser.len());
374
375 assert_eq!(None, parser.next());
376 assert_eq!(None, parser.next_back());
377 assert_eq!(0, parser.len());
378 }
379}