use crate::{
decode_utf16_surrogate_pair,
error::{DecodeUtf16Error, DecodeUtf32Error},
is_utf16_high_surrogate, is_utf16_low_surrogate, is_utf16_surrogate,
};
#[allow(unused_imports)]
use core::{
char,
iter::{DoubleEndedIterator, ExactSizeIterator, FusedIterator},
};
#[derive(Debug, Clone)]
pub struct DecodeUtf16<I>
where
I: Iterator<Item = u16>,
{
iter: I,
forward_buf: Option<u16>,
back_buf: Option<u16>,
}
impl<I> DecodeUtf16<I>
where
I: Iterator<Item = u16>,
{
pub(crate) fn new(iter: I) -> Self {
Self {
iter,
forward_buf: None,
back_buf: None,
}
}
}
impl<I> Iterator for DecodeUtf16<I>
where
I: Iterator<Item = u16>,
{
type Item = Result<char, DecodeUtf16Error>;
fn next(&mut self) -> Option<Self::Item> {
let u = match self.forward_buf.take() {
Some(buf) => buf,
None => self.iter.next().or_else(|| self.back_buf.take())?,
};
if !is_utf16_surrogate(u) {
Some(Ok(unsafe { char::from_u32_unchecked(u as u32) }))
} else if is_utf16_low_surrogate(u) {
Some(Err(DecodeUtf16Error::new(u)))
} else {
let u2 = match self.iter.next().or_else(|| self.back_buf.take()) {
Some(u2) => u2,
None => return Some(Err(DecodeUtf16Error::new(u))),
};
if !is_utf16_low_surrogate(u2) {
self.forward_buf = Some(u2);
return Some(Err(DecodeUtf16Error::new(u)));
}
unsafe { Some(Ok(decode_utf16_surrogate_pair(u, u2))) }
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let (low, high) = self.iter.size_hint();
(low / 2, high)
}
}
impl<I> DoubleEndedIterator for DecodeUtf16<I>
where
I: Iterator<Item = u16> + DoubleEndedIterator,
{
fn next_back(&mut self) -> Option<Self::Item> {
let u2 = match self.back_buf.take() {
Some(buf) => buf,
None => self.iter.next_back().or_else(|| self.forward_buf.take())?,
};
if !is_utf16_surrogate(u2) {
Some(Ok(unsafe { char::from_u32_unchecked(u2 as u32) }))
} else if is_utf16_high_surrogate(u2) {
Some(Err(DecodeUtf16Error::new(u2)))
} else {
let u = match self.iter.next_back().or_else(|| self.forward_buf.take()) {
Some(u) => u,
None => return Some(Err(DecodeUtf16Error::new(u2))),
};
if !is_utf16_high_surrogate(u) {
self.back_buf = Some(u);
return Some(Err(DecodeUtf16Error::new(u2)));
}
unsafe { Some(Ok(decode_utf16_surrogate_pair(u, u2))) }
}
}
}
impl<I> FusedIterator for DecodeUtf16<I> where I: Iterator<Item = u16> + FusedIterator {}
#[derive(Debug, Clone)]
pub struct DecodeUtf16Lossy<I>
where
I: Iterator<Item = u16>,
{
pub(crate) iter: DecodeUtf16<I>,
}
impl<I> Iterator for DecodeUtf16Lossy<I>
where
I: Iterator<Item = u16>,
{
type Item = char;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.iter
.next()
.map(|res| res.unwrap_or(char::REPLACEMENT_CHARACTER))
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl<I> DoubleEndedIterator for DecodeUtf16Lossy<I>
where
I: Iterator<Item = u16> + DoubleEndedIterator,
{
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
self.iter
.next_back()
.map(|res| res.unwrap_or(char::REPLACEMENT_CHARACTER))
}
}
impl<I> FusedIterator for DecodeUtf16Lossy<I> where I: Iterator<Item = u16> + FusedIterator {}
#[derive(Debug, Clone)]
pub struct DecodeUtf32<I>
where
I: Iterator<Item = u32>,
{
pub(crate) iter: I,
}
impl<I> Iterator for DecodeUtf32<I>
where
I: Iterator<Item = u32>,
{
type Item = Result<char, DecodeUtf32Error>;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.iter
.next()
.map(|u| char::from_u32(u).ok_or_else(|| DecodeUtf32Error::new(u)))
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl<I> DoubleEndedIterator for DecodeUtf32<I>
where
I: Iterator<Item = u32> + DoubleEndedIterator,
{
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
self.iter
.next_back()
.map(|u| char::from_u32(u).ok_or_else(|| DecodeUtf32Error::new(u)))
}
}
impl<I> FusedIterator for DecodeUtf32<I> where I: Iterator<Item = u32> + FusedIterator {}
impl<I> ExactSizeIterator for DecodeUtf32<I>
where
I: Iterator<Item = u32> + ExactSizeIterator,
{
#[inline]
fn len(&self) -> usize {
self.iter.len()
}
}
#[derive(Debug, Clone)]
pub struct DecodeUtf32Lossy<I>
where
I: Iterator<Item = u32>,
{
pub(crate) iter: DecodeUtf32<I>,
}
impl<I> Iterator for DecodeUtf32Lossy<I>
where
I: Iterator<Item = u32>,
{
type Item = char;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.iter
.next()
.map(|res| res.unwrap_or(core::char::REPLACEMENT_CHARACTER))
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl<I> DoubleEndedIterator for DecodeUtf32Lossy<I>
where
I: Iterator<Item = u32> + DoubleEndedIterator,
{
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
self.iter
.next_back()
.map(|res| res.unwrap_or(core::char::REPLACEMENT_CHARACTER))
}
}
impl<I> FusedIterator for DecodeUtf32Lossy<I> where I: Iterator<Item = u32> + FusedIterator {}
impl<I> ExactSizeIterator for DecodeUtf32Lossy<I>
where
I: Iterator<Item = u32> + ExactSizeIterator,
{
#[inline]
fn len(&self) -> usize {
self.iter.len()
}
}
#[derive(Debug, Clone)]
pub struct EncodeUtf8<I>
where
I: Iterator<Item = char>,
{
iter: I,
buf: [u8; 4],
idx: u8,
len: u8,
}
impl<I> EncodeUtf8<I>
where
I: Iterator<Item = char>,
{
pub(crate) fn new(iter: I) -> Self {
Self {
iter,
buf: [0; 4],
idx: 0,
len: 0,
}
}
}
impl<I> Iterator for EncodeUtf8<I>
where
I: Iterator<Item = char>,
{
type Item = u8;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
if self.idx >= self.len {
let c = self.iter.next()?;
self.idx = 0;
self.len = c.encode_utf8(&mut self.buf).len() as u8;
}
self.idx += 1;
let idx = (self.idx - 1) as usize;
Some(self.buf[idx])
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let (lower, upper) = self.iter.size_hint();
(lower, upper.and_then(|len| len.checked_mul(4))) }
}
impl<I> FusedIterator for EncodeUtf8<I> where I: Iterator<Item = char> + FusedIterator {}
#[derive(Debug, Clone)]
pub struct EncodeUtf16<I>
where
I: Iterator<Item = char>,
{
iter: I,
buf: Option<u16>,
}
impl<I> EncodeUtf16<I>
where
I: Iterator<Item = char>,
{
pub(crate) fn new(iter: I) -> Self {
Self { iter, buf: None }
}
}
impl<I> Iterator for EncodeUtf16<I>
where
I: Iterator<Item = char>,
{
type Item = u16;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.buf.take().or_else(|| {
let c = self.iter.next()?;
let mut buf = [0; 2];
let buf = c.encode_utf16(&mut buf);
if buf.len() > 1 {
self.buf = Some(buf[1]);
}
Some(buf[0])
})
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let (lower, upper) = self.iter.size_hint();
(lower, upper.and_then(|len| len.checked_mul(2))) }
}
impl<I> FusedIterator for EncodeUtf16<I> where I: Iterator<Item = char> + FusedIterator {}
#[derive(Debug, Clone)]
pub struct EncodeUtf32<I>
where
I: Iterator<Item = char>,
{
iter: I,
}
impl<I> EncodeUtf32<I>
where
I: Iterator<Item = char>,
{
pub(crate) fn new(iter: I) -> Self {
Self { iter }
}
}
impl<I> Iterator for EncodeUtf32<I>
where
I: Iterator<Item = char>,
{
type Item = u32;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(|c| c as u32)
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl<I> FusedIterator for EncodeUtf32<I> where I: Iterator<Item = char> + FusedIterator {}
impl<I> ExactSizeIterator for EncodeUtf32<I>
where
I: Iterator<Item = char> + ExactSizeIterator,
{
#[inline]
fn len(&self) -> usize {
self.iter.len()
}
}
impl<I> DoubleEndedIterator for EncodeUtf32<I>
where
I: Iterator<Item = char> + DoubleEndedIterator,
{
#[inline]
fn next_back(&mut self) -> Option<Self::Item> {
self.iter.next_back().map(|c| c as u32)
}
}