use super::*;
#[inline(always)]
pub fn get_utf16_len(bytes: &BytesSlice) -> u32 {
let str = bytes_to_str(bytes);
let utf16 = encode_utf16(str).count();
utf16 as u32
}
pub fn utf16_to_utf8(bytes: &BytesSlice, utf16_index: usize) -> usize {
let str = bytes_to_str(bytes);
let mut iter = encode_utf16(str);
for _ in 0..utf16_index {
iter.next();
}
iter.visited
}
#[inline(always)]
fn bytes_to_str(bytes: &BytesSlice) -> &str {
#[allow(unsafe_code)]
let str = unsafe { std::str::from_utf8_unchecked(&bytes[..]) };
str
}
fn encode_utf16(s: &str) -> EncodeUtf16 {
EncodeUtf16 {
chars: s.chars(),
extra: 0,
visited: 0,
}
}
#[derive(Clone)]
pub struct EncodeUtf16<'a> {
chars: Chars<'a>,
extra: u16,
visited: usize,
}
impl fmt::Debug for EncodeUtf16<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("EncodeUtf16").finish_non_exhaustive()
}
}
impl<'a> Iterator for EncodeUtf16<'a> {
type Item = u16;
#[inline]
fn next(&mut self) -> Option<u16> {
if self.extra != 0 {
let tmp = self.extra;
self.extra = 0;
return Some(tmp);
}
let mut buf = [0; 2];
self.chars.next().map(|ch| {
self.visited += ch.len_utf8();
let n = ch.encode_utf16(&mut buf).len();
if n == 2 {
self.extra = buf[1];
}
buf[0]
})
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let (low, high) = self.chars.size_hint();
(low, high.and_then(|n| n.checked_mul(2)))
}
}