1pub use chars::Chars;
4pub use flatten::Flatten;
5
6pub mod chars {
7 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
12 pub struct BadUnicode(pub u32);
13 impl std::error::Error for BadUnicode {}
14 impl std::fmt::Display for BadUnicode {
15 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
16 let Self(code) = self;
17 write!(f, "Bad unicode: {code}")
18 }
19 }
20
21 #[derive(Clone, Debug)]
24 pub struct Chars<I: Iterator<Item = u8>>(pub I);
25 impl<I: Iterator<Item = u8>> Iterator for Chars<I> {
26 type Item = Result<char, BadUnicode>;
27 fn next(&mut self) -> Option<Self::Item> {
28 let Self(bytes) = self;
29 let start = bytes.next()? as u32;
30 let (mut out, count) = match start {
31 start if start & 0x80 == 0x00 => (start, 0), start if start & 0xe0 == 0xc0 => (start & 0x1f, 1), start if start & 0xf0 == 0xe0 => (start & 0x0f, 2), start if start & 0xf8 == 0xf0 => (start & 0x07, 3), _ => return None,
36 };
37 for _ in 0..count {
38 let cont = bytes.next()? as u32;
39 if cont & 0xc0 != 0x80 {
40 return None;
41 }
42 out = (out << 6) | (cont & 0x3f);
43 }
44 Some(char::from_u32(out).ok_or(BadUnicode(out)))
45 }
46 }
47}
48pub mod flatten {
49 #[derive(Clone, Debug)]
55 pub struct Flatten<T, I: Iterator<Item = T>>(pub I);
56 impl<T, E, I: Iterator<Item = Result<T, E>>> Iterator for Flatten<Result<T, E>, I> {
57 type Item = T;
58 fn next(&mut self) -> Option<Self::Item> {
59 self.0.next()?.ok()
60 }
61 }
62 impl<T, I: Iterator<Item = Option<T>>> Iterator for Flatten<Option<T>, I> {
63 type Item = T;
64 fn next(&mut self) -> Option<Self::Item> {
65 self.0.next()?
66 }
67 }
68}