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
14 impl std::error::Error for BadUnicode {}
15
16 impl std::fmt::Display for BadUnicode {
17 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
18 let Self(code) = self;
19 write!(f, "Bad unicode: {code}")
20 }
21 }
22
23 #[derive(Clone, Debug)]
26 pub struct Chars<I: Iterator<Item = u8>>(pub I);
27
28 impl<I: Iterator<Item = u8>> Iterator for Chars<I> {
29 type Item = Result<char, BadUnicode>;
30
31 fn next(&mut self) -> Option<Self::Item> {
32 let Self(bytes) = self;
33 let start = bytes.next()? as u32;
34 let (mut out, count) = match start {
35 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,
40 };
41 for _ in 0..count {
42 let cont = bytes.next()? as u32;
43 if cont & 0xc0 != 0x80 {
44 return None;
45 }
46 out = (out << 6) | (cont & 0x3f);
47 }
48 Some(char::from_u32(out).ok_or(BadUnicode(out)))
49 }
50 }
51}
52pub mod flatten {
53 #[derive(Clone, Debug)]
59 pub struct Flatten<T, I: Iterator<Item = T>>(pub I);
60
61 impl<T, E, I: Iterator<Item = Result<T, E>>> Iterator for Flatten<Result<T, E>, I> {
62 type Item = T;
63 fn next(&mut self) -> Option<Self::Item> {
64 self.0.next()?.ok()
65 }
66 }
67
68 impl<T, I: Iterator<Item = Option<T>>> Iterator for Flatten<Option<T>, I> {
69 type Item = T;
70 fn next(&mut self) -> Option<Self::Item> {
71 self.0.next()?
72 }
73 }
74}