1use crate::{ParseError, ParserResult};
8
9mod private {
10 pub trait Sealed {}
11}
12
13pub trait EncodingType: private::Sealed {
17 type CodeUnit: PartialEq + core::fmt::Debug + Clone;
19
20 #[doc(hidden)]
22 fn slice(source: &[Self::CodeUnit], start: usize, end: usize) -> Option<&[Self::CodeUnit]>;
23
24 #[doc(hidden)]
27 fn get_ascii(source: &[Self::CodeUnit], index: usize) -> ParserResult<Option<u8>>;
28
29 #[doc(hidden)]
31 fn check_calendar_key(key: &[Self::CodeUnit]) -> bool;
32}
33
34#[derive(Debug, PartialEq, Clone)]
36#[allow(clippy::exhaustive_structs)] pub struct Utf16;
38
39impl private::Sealed for Utf16 {}
40
41impl EncodingType for Utf16 {
42 type CodeUnit = u16;
43 fn slice(source: &[Self::CodeUnit], start: usize, end: usize) -> Option<&[Self::CodeUnit]> {
44 source.get(start..end)
45 }
46
47 fn get_ascii(source: &[Self::CodeUnit], index: usize) -> ParserResult<Option<u8>> {
48 source.get(index).copied().map(to_ascii_byte).transpose()
49 }
50
51 fn check_calendar_key(key: &[Self::CodeUnit]) -> bool {
52 key == [0x75, 0x2d, 0x63, 0x61]
53 }
54}
55
56#[inline]
57fn to_ascii_byte(b: u16) -> ParserResult<u8> {
58 if !(0x01..0x7F).contains(&b) {
59 return Err(ParseError::NonAsciiCodePoint);
60 }
61 Ok(b as u8)
62}
63
64#[derive(Debug, PartialEq, Clone)]
66#[allow(clippy::exhaustive_structs)] pub struct Utf8;
68
69impl private::Sealed for Utf8 {}
70
71impl EncodingType for Utf8 {
72 type CodeUnit = u8;
73
74 fn slice(source: &[Self::CodeUnit], start: usize, end: usize) -> Option<&[Self::CodeUnit]> {
75 source.get(start..end)
76 }
77
78 fn get_ascii(source: &[Self::CodeUnit], index: usize) -> ParserResult<Option<u8>> {
79 Ok(source.get(index).copied())
80 }
81
82 fn check_calendar_key(key: &[Self::CodeUnit]) -> bool {
83 key == "u-ca".as_bytes()
84 }
85}