#![forbid(unsafe_code)]
pub struct CharDecoder<I: Iterator<Item = u8>> {
iter: core::iter::Peekable<I>,
}
impl<I: Iterator<Item = u8>> From<I> for CharDecoder<I> {
#[inline]
#[must_use]
fn from(i: I) -> Self {
Self { iter: i.peekable() }
}
}
impl<I: Iterator<Item = u8>> CharDecoder<I> {
#[inline]
#[must_use]
fn next_continuation_bits(&mut self) -> Option<u32> {
match self.iter.peek()? {
x if x >> 6 == 0b10 => Some((self.iter.next()? as u32) & 0b111111),
_ => None,
}
}
}
impl<I: Iterator<Item = u8>> Iterator for CharDecoder<I> {
type Item = char;
#[inline]
#[must_use]
fn next(&mut self) -> Option<char> {
let x = u32::from(self.iter.next()?);
if x < 128 {
Some(x as u8 as char)
} else {
match UTF8_CHAR_WIDTH[x as usize] {
2 => {
let Some(y) = self.next_continuation_bits() else {
return Some(char::REPLACEMENT_CHARACTER);
};
let u = ((x & 0b11111) << 6) | y;
Some(char::from_u32(u).unwrap_or(char::REPLACEMENT_CHARACTER))
}
3 => {
let Some(y) = self.next_continuation_bits() else {
return Some(char::REPLACEMENT_CHARACTER);
};
let Some(z) = self.next_continuation_bits() else {
return Some(char::REPLACEMENT_CHARACTER);
};
let u = ((x & 0b1111) << 12) | y << 6 | z;
Some(char::from_u32(u).unwrap_or(char::REPLACEMENT_CHARACTER))
}
4 => {
let Some(y) = self.next_continuation_bits() else {
return Some(char::REPLACEMENT_CHARACTER);
};
let Some(z) = self.next_continuation_bits() else {
return Some(char::REPLACEMENT_CHARACTER);
};
let Some(w) = self.next_continuation_bits() else {
return Some(char::REPLACEMENT_CHARACTER);
};
let u = ((x & 0b111) << 18) | y << 12 | z << 6 | w;
Some(char::from_u32(u).unwrap_or(char::REPLACEMENT_CHARACTER))
}
_ => Some(char::REPLACEMENT_CHARACTER),
}
}
}
}
const UTF8_CHAR_WIDTH: &[u8; 256] = &[
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ];