use core::slice::Iter;
use utf_types::utf16::Bmp;
use utf_types::utf16::BmpOrSurrogate;
use utf_types::utf16::HighSurrogate;
use utf_types::utf16::LowSurrogate;
use utf_types::utf16::Surrogate;
use utf_types::utf16::SurrogatePair;
const REPLACEMENT_CHARACTER_AS_BMP: Bmp = const {
if let Ok(bmp) = Bmp::try_new(char::REPLACEMENT_CHARACTER as u16) {
bmp
} else {
panic!()
}
};
pub trait Utf16Handler {
type Output;
fn bmp(&self, bmp: Bmp) -> Self::Output;
fn surrogate_pair(&self, surrogate_pair: SurrogatePair) -> Self::Output;
#[inline(always)]
fn error(&self) -> Self::Output {
self.bmp(REPLACEMENT_CHARACTER_AS_BMP)
}
}
#[derive(Debug, Clone)]
pub struct Utf16CharsWithHandler<'a, H>
where
H: Utf16Handler,
{
iter: Iter<'a, u16>,
handler: H,
}
impl<'a, H> Utf16CharsWithHandler<'a, H>
where
H: Utf16Handler,
{
#[inline(always)]
pub fn new(code_units: &'a [u16], handler: H) -> Self {
Utf16CharsWithHandler::<'a, H> {
iter: code_units.iter(),
handler,
}
}
#[inline(always)]
pub fn as_slice(&self) -> &'a [u16] {
self.iter.as_slice()
}
#[inline(always)]
pub fn handler(&self) -> &H {
&self.handler
}
#[cold]
fn error(&self) -> H::Output {
self.handler.error()
}
#[cold]
#[inline(never)]
fn surrogate_next(&mut self, surrogate: Surrogate) -> H::Output {
if let Ok(high) = HighSurrogate::try_new_with_surrogate(surrogate) {
let mut cloned_iter = self.iter.clone();
if let Some(&u) = cloned_iter.next() {
if let Ok(low) = LowSurrogate::try_new(u) {
self.iter = cloned_iter;
return self.handler.surrogate_pair(SurrogatePair::new(high, low));
}
}
}
self.error()
}
#[cold]
#[inline(never)]
fn surrogate_next_back(&mut self, surrogate: Surrogate) -> H::Output {
if let Ok(low) = LowSurrogate::try_new_with_surrogate(surrogate) {
let mut cloned_iter = self.iter.clone();
if let Some(&u) = cloned_iter.next_back() {
if let Ok(high) = HighSurrogate::try_new(u) {
self.iter = cloned_iter;
return self.handler.surrogate_pair(SurrogatePair::new(high, low));
}
}
}
self.error()
}
}
impl<'a, H> Iterator for Utf16CharsWithHandler<'a, H>
where
H: Utf16Handler,
{
type Item = H::Output;
#[inline(always)]
fn next(&mut self) -> Option<H::Output> {
match BmpOrSurrogate::new(*self.iter.next()?) {
BmpOrSurrogate::Bmp(bmp) => Some(self.handler.bmp(bmp)),
BmpOrSurrogate::Surrogate(surrogate) => Some(self.surrogate_next(surrogate)),
}
}
#[inline(always)]
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.as_slice().len();
(len.div_ceil(2), Some(len))
}
#[inline(always)]
fn last(mut self) -> Option<Self::Item> {
self.next_back()
}
}
impl<'a, H> DoubleEndedIterator for Utf16CharsWithHandler<'a, H>
where
H: Utf16Handler,
{
#[inline(always)]
fn next_back(&mut self) -> Option<H::Output> {
match BmpOrSurrogate::new(*self.iter.next_back()?) {
BmpOrSurrogate::Bmp(bmp) => Some(self.handler.bmp(bmp)),
BmpOrSurrogate::Surrogate(surrogate) => Some(self.surrogate_next_back(surrogate)),
}
}
}
impl<H> core::iter::FusedIterator for Utf16CharsWithHandler<'_, H> where H: Utf16Handler {}