Skip to main content

ixdtf/
encoding.rs

1// This file is part of ICU4X. For terms of use, please see the file
2// called LICENSE at the top level of the ICU4X source tree
3// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
4
5//! This module contains the supported encoding for `ixdtf` parsing.
6
7use crate::{ParseError, ParserResult};
8
9mod private {
10    pub trait Sealed {}
11}
12
13/// A trait for defining various supported encodings
14/// and implementing functionality that is encoding
15/// sensitive / specific.
16pub trait EncodingType: private::Sealed {
17    /// The code unit for the current encoding.
18    type CodeUnit: PartialEq + core::fmt::Debug + Clone;
19
20    /// Get a slice from the underlying source using for start..end
21    #[doc(hidden)]
22    fn slice(source: &[Self::CodeUnit], start: usize, end: usize) -> Option<&[Self::CodeUnit]>;
23
24    /// Retrieve the provided code unit index and returns the value as an ASCII byte
25    /// or None if the value is not ASCII representable.
26    #[doc(hidden)]
27    fn get_ascii(source: &[Self::CodeUnit], index: usize) -> ParserResult<Option<u8>>;
28
29    /// Checks for the known calendar annotation key `u-ca`.
30    #[doc(hidden)]
31    fn check_calendar_key(key: &[Self::CodeUnit]) -> bool;
32}
33
34/// A marker type that signals a parser should parse the source as UTF-16 bytes.
35#[derive(Debug, PartialEq, Clone)]
36#[allow(clippy::exhaustive_structs)] // ZST Marker trait, no fields should be added
37pub 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/// A marker type that signals a parser should parse the source as UTF-8 bytes.
65#[derive(Debug, PartialEq, Clone)]
66#[allow(clippy::exhaustive_structs)] // ZST Marker trait, no fields should be added.
67pub 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}