#![forbid(unsafe_code)]
const CODE_UNIT_INDICATE_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, ];
pub(crate) const fn utf8_char_width(code_unit: u8) -> Option<usize> {
let x = CODE_UNIT_INDICATE_WIDTH[code_unit as usize];
if x == 0 {
None
} else {
Some(x as usize)
}
}
pub(crate) fn rfind_utf8_end(buf: &[u8]) -> usize {
let mut position = buf.len();
while position > 0 {
position -= 1;
if let Some(need_more) = utf8_char_width(buf[position]) {
if position + need_more <= buf.len() {
position += need_more;
}
break;
}
}
position
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn rfind_utf8_end_examples() {
assert_eq!(rfind_utf8_end("1234".as_bytes()), 4);
assert_eq!(rfind_utf8_end("🚀".as_bytes()), 4);
assert_eq!(rfind_utf8_end(b"\xf0\x9f\x9a\x80"), 4); assert_eq!(rfind_utf8_end(b"\xf0\x9f\x9a"), 0); }
}