pub(crate) struct CharIterator<'a> {
bytes: &'a [u8],
index: usize
}
impl<'a> CharIterator<'a> {
#[inline]
pub(crate) const fn from(value: &'a str) -> Self {
Self {
bytes: value.as_bytes(),
index: 0,
}
}
}
impl CharIterator<'_> {
pub(crate) const fn count(self) -> usize {
let len = self.bytes.len();
let mut count = 0;
let mut i = 0;
while i < len {
if (self.bytes[i] as i8) >= -64 {
count += 1;
}
i += 1;
}
count
}
pub(crate) const fn next(&mut self) -> Option<char> {
const MULTIBYTE_2: u8 = 0b1100_0000;
const MULTIBYTE_3: u8 = 0b1110_0000;
const MULTIBYTE_4: u8 = 0b1111_0000;
const MULTIBYTE_2_MASK: u8 = 0b1110_0000;
const MULTIBYTE_3_MASK: u8 = 0b1111_0000;
const MULTIBYTE_4_MASK: u8 = 0b1111_1000;
const CONTINUATION: u8 = 0b1000_0000;
const CONTINUATION_MASK: u8 = 0b1100_0000;
#[inline] const fn is_continuation(b: u8) -> bool { b & CONTINUATION_MASK == CONTINUATION }
#[inline] const fn cont_bits(b: u8) -> u32 { (b & !CONTINUATION_MASK) as u32 }
if self.index >= self.bytes.len() {
return None;
}
let byte0 = self.bytes[self.index];
let len = match byte0 {
..0x80 => 1,
_ if (byte0 & MULTIBYTE_2_MASK) == MULTIBYTE_2 => 2,
_ if (byte0 & MULTIBYTE_3_MASK) == MULTIBYTE_3 => 3,
_ if (byte0 & MULTIBYTE_4_MASK) == MULTIBYTE_4 => 4,
_ => {
return None;
}
};
if len > self.bytes.len() - self.index {
return None;
}
let Some(result) = (match len {
1 => Some(byte0 as char),
2 if is_continuation(self.bytes[self.index + 1])
=> {
let cp = (((byte0 & !MULTIBYTE_2_MASK) as u32) << 6) | cont_bits(self.bytes[self.index + 1]);
char::from_u32(cp)
},
3 if is_continuation(self.bytes[self.index + 1])
&& is_continuation(self.bytes[self.index + 2])
=> {
let cp = (((byte0 & !MULTIBYTE_3_MASK) as u32) << 12)
| (cont_bits(self.bytes[self.index + 1]) << 6)
| cont_bits(self.bytes[self.index + 2]);
char::from_u32(cp)
}
4 if is_continuation(self.bytes[self.index + 1])
&& is_continuation(self.bytes[self.index + 2])
&& is_continuation(self.bytes[self.index + 3])
=> {
let cp = (((byte0 & !MULTIBYTE_4_MASK) as u32) << 18)
| (cont_bits(self.bytes[self.index + 1]) << 12)
| (cont_bits(self.bytes[self.index + 2]) << 6)
| cont_bits(self.bytes[self.index + 3]);
char::from_u32(cp)
}
_ => None,
}) else {
return None
};
self.index += len;
Some(result)
}
}