use core::fmt::Formatter;
use utf_types::utf16::Bmp;
use utf_types::utf16::SurrogatePair;
use crate::Utf16Handler;
#[derive(Debug, PartialEq, Clone, Copy, Eq, Hash)]
#[non_exhaustive]
pub struct Utf16CharsError;
impl core::fmt::Display for Utf16CharsError {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), core::fmt::Error> {
write!(f, "unpaired surrogate")
}
}
impl core::error::Error for Utf16CharsError {}
#[derive(Debug, Clone)]
pub(crate) struct ErrorReportingHandler;
impl ErrorReportingHandler {
pub(crate) fn new() -> Self {
Self {}
}
}
impl Utf16Handler for ErrorReportingHandler {
type Output = Result<char, Utf16CharsError>;
#[inline(always)]
fn bmp(&self, bmp: Bmp) -> Self::Output {
Ok(bmp.to_char())
}
#[inline(always)]
fn surrogate_pair(&self, surrogate_pair: SurrogatePair) -> Self::Output {
Ok(surrogate_pair.to_char())
}
#[inline(always)]
fn error(&self) -> Self::Output {
Err(Utf16CharsError)
}
}
crate::macros::named_iterators_from_no_argument_handler!(
ErrorReportingHandler,
Result<char, Utf16CharsError>,
,
ErrorReportingUtf16Chars,
,
ErrorReportingUtf16CharIndices,
);
#[cfg(test)]
mod tests {
use crate::ErrorReportingUtf16Chars;
use crate::Utf16CharsEx;
#[test]
fn test_boundaries() {
assert!(ErrorReportingUtf16Chars::new([0xD7FFu16].as_slice())
.map(|r| r.unwrap_or('\u{FFFD}'))
.eq(core::iter::once('\u{D7FF}')));
assert!(ErrorReportingUtf16Chars::new([0xE000u16].as_slice())
.map(|r| r.unwrap_or('\u{FFFD}'))
.eq(core::iter::once('\u{E000}')));
assert!(ErrorReportingUtf16Chars::new([0xD800u16].as_slice())
.map(|r| r.unwrap_or('\u{FFFD}'))
.eq(core::iter::once('\u{FFFD}')));
assert!(ErrorReportingUtf16Chars::new([0xDFFFu16].as_slice())
.map(|r| r.unwrap_or('\u{FFFD}'))
.eq(core::iter::once('\u{FFFD}')));
}
#[test]
fn test_unpaired() {
assert!(
ErrorReportingUtf16Chars::new([0xD800u16, 0x0061u16].as_slice())
.map(|r| r.unwrap_or('\u{FFFD}'))
.eq([0xFFFDu16, 0x0061u16].as_slice().chars())
);
assert!(
ErrorReportingUtf16Chars::new([0xDFFFu16, 0x0061u16].as_slice())
.map(|r| r.unwrap_or('\u{FFFD}'))
.eq([0xFFFDu16, 0x0061u16].as_slice().chars())
);
}
#[test]
fn test_unpaired_rev() {
assert!(
ErrorReportingUtf16Chars::new([0xD800u16, 0x0061u16].as_slice())
.rev()
.map(|r| r.unwrap_or('\u{FFFD}'))
.eq([0xFFFDu16, 0x0061u16].as_slice().chars().rev())
);
assert!(
ErrorReportingUtf16Chars::new([0xDFFFu16, 0x0061u16].as_slice())
.rev()
.map(|r| r.unwrap_or('\u{FFFD}'))
.eq([0xFFFDu16, 0x0061u16].as_slice().chars().rev())
);
}
#[test]
fn test_paired() {
assert!(
ErrorReportingUtf16Chars::new([0xD83Eu16, 0xDD73u16].as_slice())
.map(|r| r.unwrap_or('\u{FFFD}'))
.eq(core::iter::once('🥳'))
);
}
#[test]
fn test_paired_rev() {
assert!(
ErrorReportingUtf16Chars::new([0xD83Eu16, 0xDD73u16].as_slice())
.rev()
.map(|r| r.unwrap_or('\u{FFFD}'))
.eq(core::iter::once('🥳'))
);
}
#[test]
fn test_as_slice() {
let mut iter = ErrorReportingUtf16Chars::new([0x0061u16, 0x0062u16].as_slice());
let at_start = iter.as_slice();
assert_eq!(iter.next(), Some(Ok('a')));
let in_middle = iter.as_slice();
assert_eq!(iter.next(), Some(Ok('b')));
let at_end = iter.as_slice();
assert_eq!(at_start.len(), 2);
assert_eq!(in_middle.len(), 1);
assert_eq!(at_end.len(), 0);
assert_eq!(at_start[0], 0x0061u16);
assert_eq!(at_start[1], 0x0062u16);
assert_eq!(in_middle[0], 0x0062u16);
}
#[test]
fn test_size() {
assert_eq!(
core::mem::size_of::<Option<<ErrorReportingUtf16Chars<'_> as Iterator>::Item>>(),
core::mem::size_of::<Option<char>>()
);
}
}