icu_datetime/provider/pattern/runtime/
pattern.rs1#![allow(clippy::exhaustive_structs)] use super::super::{reference, PatternError, PatternItem, TimeGranularity};
8use alloc::vec::Vec;
9use core::str::FromStr;
10use icu_plurals::provider::FourBitMetadata;
11use icu_provider::prelude::*;
12use zerovec::{ZeroSlice, ZeroVec};
13
14#[derive(Debug, PartialEq, Eq, Clone, yoke::Yokeable, zerofrom::ZeroFrom)]
25#[cfg_attr(feature = "datagen", derive(databake::Bake))]
26#[cfg_attr(feature = "datagen", databake(path = icu_datetime::provider::pattern::runtime))]
27#[zerovec::make_varule(PatternULE)]
28#[zerovec::derive(Debug)]
29#[zerovec::skip_derive(Ord)]
30#[cfg_attr(feature = "serde", zerovec::derive(Deserialize))]
31#[cfg_attr(feature = "datagen", zerovec::derive(Serialize))]
32pub struct Pattern<'data> {
33 pub items: ZeroVec<'data, PatternItem>,
35 pub metadata: PatternMetadata,
40}
41
42#[derive(Debug, Copy, Clone)]
44pub(crate) struct PatternBorrowed<'data> {
45 pub(crate) items: &'data ZeroSlice<PatternItem>,
46 pub(crate) metadata: PatternMetadata,
47}
48
49#[derive(Debug, Copy, Clone, PartialEq, Eq)]
57#[zerovec::make_ule(PatternMetadataULE)]
58#[zerovec::skip_derive(Ord)]
59pub struct PatternMetadata(u8);
60
61impl PatternMetadata {
62 pub(crate) const DEFAULT: PatternMetadata = Self::from_time_granularity(TimeGranularity::None);
63
64 #[inline]
65 pub(crate) fn time_granularity(self) -> TimeGranularity {
66 TimeGranularity::from_ordinal(self.0)
67 }
68
69 pub(crate) fn from_items(items: &[PatternItem]) -> Self {
70 Self::from_iter_items(items.iter().copied())
71 }
72
73 pub(crate) fn from_iter_items(iter_items: impl Iterator<Item = PatternItem>) -> Self {
74 let time_granularity: TimeGranularity =
75 iter_items.map(Into::into).max().unwrap_or_default();
76 Self::from_time_granularity(time_granularity)
77 }
78
79 #[inline]
81 pub(crate) fn merge_date_and_time_metadata(
82 _date: PatternMetadata,
83 time: PatternMetadata,
84 ) -> PatternMetadata {
85 time
87 }
88
89 #[inline]
91 pub const fn from_time_granularity(time_granularity: TimeGranularity) -> Self {
92 Self(time_granularity.ordinal())
93 }
94
95 #[cfg(feature = "datagen")]
96 #[inline]
97 pub(crate) fn set_time_granularity(&mut self, time_granularity: TimeGranularity) {
98 self.0 = time_granularity.ordinal();
99 }
100
101 pub(crate) fn to_four_bit_metadata(self) -> FourBitMetadata {
102 #[allow(clippy::unwrap_used)] FourBitMetadata::try_from_byte(self.0).unwrap()
104 }
105
106 pub(crate) fn from_u8(other: u8) -> Self {
107 Self(TimeGranularity::from_ordinal(other).ordinal())
108 }
109}
110
111impl Default for PatternMetadata {
112 #[inline]
113 fn default() -> Self {
114 Self::DEFAULT
115 }
116}
117
118impl Pattern<'_> {
119 pub(crate) fn into_owned(self) -> Pattern<'static> {
120 Pattern {
121 items: self.items.into_owned(),
122 metadata: self.metadata,
123 }
124 }
125
126 pub(crate) fn as_borrowed(&self) -> PatternBorrowed {
127 PatternBorrowed {
128 items: &self.items,
129 metadata: self.metadata,
130 }
131 }
132
133 pub fn as_ref(&self) -> Pattern<'_> {
135 self.as_borrowed().as_pattern()
136 }
137}
138
139impl<'data> PatternBorrowed<'data> {
140 pub(crate) const DEFAULT: PatternBorrowed<'static> = PatternBorrowed {
141 items: ZeroSlice::new_empty(),
142 metadata: PatternMetadata::DEFAULT,
143 };
144
145 pub(crate) fn as_pattern(self) -> Pattern<'data> {
146 Pattern {
147 items: self.items.as_zerovec(),
148 metadata: self.metadata,
149 }
150 }
151}
152
153impl From<Vec<PatternItem>> for Pattern<'_> {
154 fn from(items: Vec<PatternItem>) -> Self {
155 Self {
156 metadata: PatternMetadata::from_items(&items),
157 items: ZeroVec::alloc_from_slice(&items),
158 }
159 }
160}
161
162impl FromIterator<PatternItem> for Pattern<'_> {
163 fn from_iter<T: IntoIterator<Item = PatternItem>>(iter: T) -> Self {
164 let items = iter.into_iter().collect::<ZeroVec<PatternItem>>();
165 Self {
166 metadata: PatternMetadata::from_iter_items(items.iter()),
167 items,
168 }
169 }
170}
171
172impl From<&reference::Pattern> for Pattern<'_> {
173 fn from(input: &reference::Pattern) -> Self {
174 Self {
175 items: ZeroVec::alloc_from_slice(&input.items),
176 metadata: PatternMetadata::from_time_granularity(input.time_granularity),
177 }
178 }
179}
180
181impl From<&Pattern<'_>> for reference::Pattern {
182 fn from(input: &Pattern<'_>) -> Self {
183 Self {
184 items: input.items.to_vec(),
185 time_granularity: input.metadata.time_granularity(),
186 }
187 }
188}
189
190impl FromStr for Pattern<'_> {
191 type Err = PatternError;
192
193 fn from_str(input: &str) -> Result<Self, Self::Err> {
194 let reference = reference::Pattern::from_str(input)?;
195 Ok(Self::from(&reference))
196 }
197}
198
199impl Default for Pattern<'_> {
200 fn default() -> Self {
201 Self {
202 items: ZeroVec::new(),
203 metadata: PatternMetadata::default(),
204 }
205 }
206}
207
208#[cfg(feature = "datagen")]
209impl databake::Bake for PatternMetadata {
210 fn bake(&self, ctx: &databake::CrateEnv) -> databake::TokenStream {
211 ctx.insert("icu_datetime");
212 let time_granularity = databake::Bake::bake(&self.time_granularity(), ctx);
213 databake::quote! {
214 icu_datetime::provider::pattern::runtime::PatternMetadata::from_time_granularity(#time_granularity)
215 }
216 }
217}
218
219#[cfg(feature = "datagen")]
220impl databake::BakeSize for PatternMetadata {
221 fn borrows_size(&self) -> usize {
222 0
223 }
224}
225
226#[test]
227#[cfg(feature = "datagen")]
228fn databake() {
229 databake::test_bake!(
230 PatternMetadata,
231 const,
232 crate::provider::pattern::runtime::PatternMetadata::from_time_granularity(
233 crate::provider::pattern::TimeGranularity::Hours
234 ),
235 icu_datetime,
236 );
237}