icu_datetime/provider/fields/
length.rs1use core::cmp::{Ord, PartialOrd};
6use core::fmt;
7use displaydoc::Display;
8use zerovec::ule::{AsULE, UleError, ULE};
9
10#[derive(Display, Debug, PartialEq, Copy, Clone)]
12#[non_exhaustive]
13pub enum LengthError {
14 #[displaydoc("Invalid length")]
17 InvalidLength,
18}
19
20impl core::error::Error for LengthError {}
21
22#[derive(Debug, Eq, PartialEq, Clone, Copy, Ord, PartialOrd)]
29#[cfg_attr(feature = "datagen", derive(serde::Serialize, databake::Bake))]
30#[cfg_attr(feature = "datagen", databake(path = icu_datetime::fields))]
31#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
32#[allow(clippy::exhaustive_enums)] pub enum FieldLength {
34 One,
38 Two,
42 Three,
46 Four,
50 Five,
54 Six,
58 NumericOverride(FieldNumericOverrides),
60}
61
62const FIRST_NUMERIC_OVERRIDE: u8 = 17;
67const LAST_NUMERIC_OVERRIDE: u8 = 31;
69
70impl FieldLength {
71 #[inline]
72 pub(crate) fn idx(self) -> u8 {
73 match self {
74 FieldLength::One => 1,
75 FieldLength::Two => 2,
76 FieldLength::Three => 3,
77 FieldLength::Four => 4,
78 FieldLength::Five => 5,
79 FieldLength::Six => 6,
80 FieldLength::NumericOverride(o) => FIRST_NUMERIC_OVERRIDE
81 .saturating_add(o as u8)
82 .min(LAST_NUMERIC_OVERRIDE),
83 }
84 }
85
86 #[inline]
87 pub(crate) fn from_idx(idx: u8) -> Result<Self, LengthError> {
88 Ok(match idx {
89 1 => Self::One,
90 2 => Self::Two,
91 3 => Self::Three,
92 4 => Self::Four,
93 5 => Self::Five,
94 6 => Self::Six,
95 idx if (FIRST_NUMERIC_OVERRIDE..=LAST_NUMERIC_OVERRIDE).contains(&idx) => {
96 Self::NumericOverride((idx - FIRST_NUMERIC_OVERRIDE).try_into()?)
97 }
98 _ => return Err(LengthError::InvalidLength),
99 })
100 }
101
102 #[inline]
103 pub(crate) fn to_len(self) -> usize {
104 match self {
105 FieldLength::One => 1,
106 FieldLength::Two => 2,
107 FieldLength::Three => 3,
108 FieldLength::Four => 4,
109 FieldLength::Five => 5,
110 FieldLength::Six => 6,
111 FieldLength::NumericOverride(o) => FIRST_NUMERIC_OVERRIDE as usize + o as usize,
112 }
113 }
114
115 pub(crate) fn numeric_to_abbr(self) -> Self {
120 match self {
121 FieldLength::One | FieldLength::Two => FieldLength::Three,
122 other => other,
123 }
124 }
125}
126
127#[repr(transparent)]
128#[derive(Debug, Copy, Clone, PartialEq, Eq)]
129pub struct FieldLengthULE(u8);
130
131impl AsULE for FieldLength {
132 type ULE = FieldLengthULE;
133 fn to_unaligned(self) -> Self::ULE {
134 FieldLengthULE(self.idx())
135 }
136 fn from_unaligned(unaligned: Self::ULE) -> Self {
137 #[allow(clippy::unwrap_used)] Self::from_idx(unaligned.0).unwrap()
139 }
140}
141
142impl FieldLengthULE {
143 #[inline]
144 pub(crate) fn validate_byte(byte: u8) -> Result<(), UleError> {
145 FieldLength::from_idx(byte)
146 .map(|_| ())
147 .map_err(|_| UleError::parse::<FieldLength>())
148 }
149}
150
151unsafe impl ULE for FieldLengthULE {
161 fn validate_bytes(bytes: &[u8]) -> Result<(), UleError> {
162 for byte in bytes {
163 Self::validate_byte(*byte)?;
164 }
165 Ok(())
166 }
167}
168
169#[derive(Debug, Eq, PartialEq, Clone, Copy, Ord, PartialOrd)]
172#[cfg_attr(feature = "datagen", derive(serde::Serialize, databake::Bake))]
173#[cfg_attr(feature = "datagen", databake(path = icu_datetime::fields))]
174#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
175#[non_exhaustive]
176pub enum FieldNumericOverrides {
177 Hanidec = 0,
179 Hanidays = 1,
181 Hebr = 2,
183 Romanlow = 3,
185 Jpnyear = 4,
187}
188
189impl TryFrom<u8> for FieldNumericOverrides {
190 type Error = LengthError;
191 fn try_from(other: u8) -> Result<Self, LengthError> {
192 Ok(match other {
193 0 => Self::Hanidec,
194 1 => Self::Hanidays,
195 2 => Self::Hebr,
196 3 => Self::Romanlow,
197 4 => Self::Jpnyear,
198 _ => return Err(LengthError::InvalidLength),
199 })
200 }
201}
202
203impl FieldNumericOverrides {
204 pub fn as_str(self) -> &'static str {
206 match self {
207 Self::Hanidec => "hanidec",
208 Self::Hanidays => "hanidays",
209 Self::Hebr => "hebr",
210 Self::Romanlow => "romanlow",
211 Self::Jpnyear => "jpnyear",
212 }
213 }
214}
215
216impl fmt::Display for FieldNumericOverrides {
217 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
218 self.as_str().fmt(f)
219 }
220}