/rust/registry/src/index.crates.io-6f17d22bba15001f/icu_calendar-1.5.2/src/provider.rs
Line | Count | Source (jump to first uncovered line) |
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 | | //! π§ \[Unstable\] Data provider struct definitions for this ICU4X component. |
6 | | //! |
7 | | //! <div class="stab unstable"> |
8 | | //! π§ This code is considered unstable; it may change at any time, in breaking or non-breaking ways, |
9 | | //! including in SemVer minor releases. While the serde representation of data structs is guaranteed |
10 | | //! to be stable, their Rust representation might not be. Use with caution. |
11 | | //! </div> |
12 | | //! |
13 | | //! Read more about data providers: [`icu_provider`] |
14 | | |
15 | | // Provider structs must be stable |
16 | | #![allow(clippy::exhaustive_structs, clippy::exhaustive_enums)] |
17 | | |
18 | | pub mod chinese_based; |
19 | | pub mod islamic; |
20 | | pub use chinese_based::{ChineseCacheV1Marker, DangiCacheV1Marker}; |
21 | | pub use islamic::{IslamicObservationalCacheV1Marker, IslamicUmmAlQuraCacheV1Marker}; |
22 | | |
23 | | use crate::types::IsoWeekday; |
24 | | use core::str::FromStr; |
25 | | use icu_provider::prelude::*; |
26 | | use tinystr::TinyStr16; |
27 | | use zerovec::ZeroVec; |
28 | | |
29 | | #[cfg(feature = "compiled_data")] |
30 | | #[derive(Debug)] |
31 | | /// Baked data |
32 | | /// |
33 | | /// <div class="stab unstable"> |
34 | | /// π§ This code is considered unstable; it may change at any time, in breaking or non-breaking ways, |
35 | | /// including in SemVer minor releases. In particular, the `DataProvider` implementations are only |
36 | | /// guaranteed to match with this version's `*_unstable` providers. Use with caution. |
37 | | /// </div> |
38 | | pub struct Baked; |
39 | | |
40 | | #[cfg(feature = "compiled_data")] |
41 | | const _: () = { |
42 | | pub mod icu { |
43 | | pub use crate as calendar; |
44 | | #[allow(unused_imports)] // baked data may or may not need this |
45 | | pub use icu_locid_transform as locid_transform; |
46 | | } |
47 | | icu_calendar_data::make_provider!(Baked); |
48 | | icu_calendar_data::impl_calendar_chinesecache_v1!(Baked); |
49 | | icu_calendar_data::impl_calendar_dangicache_v1!(Baked); |
50 | | icu_calendar_data::impl_calendar_islamicobservationalcache_v1!(Baked); |
51 | | icu_calendar_data::impl_calendar_islamicummalquracache_v1!(Baked); |
52 | | icu_calendar_data::impl_calendar_japanese_v1!(Baked); |
53 | | icu_calendar_data::impl_calendar_japanext_v1!(Baked); |
54 | | icu_calendar_data::impl_datetime_week_data_v1!(Baked); |
55 | | icu_calendar_data::impl_datetime_week_data_v2!(Baked); |
56 | | }; |
57 | | |
58 | | #[cfg(feature = "datagen")] |
59 | | /// The latest minimum set of keys required by this component. |
60 | | pub const KEYS: &[DataKey] = &[ |
61 | | ChineseCacheV1Marker::KEY, |
62 | | DangiCacheV1Marker::KEY, |
63 | | IslamicObservationalCacheV1Marker::KEY, |
64 | | IslamicUmmAlQuraCacheV1Marker::KEY, |
65 | | JapaneseErasV1Marker::KEY, |
66 | | JapaneseExtendedErasV1Marker::KEY, |
67 | | WeekDataV2Marker::KEY, |
68 | | // We include the duplicate data for now, as icu_datetime loads it directly |
69 | | // https://github.com/unicode-org/icu4x/pull/4364#discussion_r1419877997 |
70 | | WeekDataV1Marker::KEY, |
71 | | ]; |
72 | | |
73 | | /// The date at which an era started |
74 | | /// |
75 | | /// The order of fields in this struct is important! |
76 | | /// |
77 | | /// <div class="stab unstable"> |
78 | | /// π§ This code is considered unstable; it may change at any time, in breaking or non-breaking ways, |
79 | | /// including in SemVer minor releases. While the serde representation of data structs is guaranteed |
80 | | /// to be stable, their Rust representation might not be. Use with caution. |
81 | | /// </div> |
82 | 0 | #[zerovec::make_ule(EraStartDateULE)] Unexecuted instantiation: <icu_calendar::provider::EraStartDate as zerovec::ule::AsULE>::to_unaligned Unexecuted instantiation: <icu_calendar::provider::EraStartDate as zerovec::ule::AsULE>::from_unaligned Unexecuted instantiation: <icu_calendar::provider::EraStartDateULE as core::cmp::PartialOrd>::partial_cmp Unexecuted instantiation: <icu_calendar::provider::EraStartDateULE as core::cmp::Ord>::cmp |
83 | | #[derive( |
84 | 0 | Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Debug, yoke::Yokeable, zerofrom::ZeroFrom, Unexecuted instantiation: <icu_calendar::provider::EraStartDate as yoke::yokeable::Yokeable>::transform Unexecuted instantiation: <icu_calendar::provider::EraStartDate as yoke::yokeable::Yokeable>::transform_owned Unexecuted instantiation: <icu_calendar::provider::EraStartDate as yoke::yokeable::Yokeable>::make Unexecuted instantiation: <icu_calendar::provider::EraStartDate as yoke::yokeable::Yokeable>::transform_mut::<_> |
85 | | )] |
86 | | #[cfg_attr( |
87 | | feature = "datagen", |
88 | | derive(serde::Serialize, databake::Bake), |
89 | | databake(path = icu_calendar::provider), |
90 | | )] |
91 | | #[cfg_attr(feature = "serde", derive(serde::Deserialize))] |
92 | | pub struct EraStartDate { |
93 | | /// The year the era started in |
94 | | pub year: i32, |
95 | | /// The month the era started in |
96 | | pub month: u8, |
97 | | /// The day the era started in |
98 | | pub day: u8, |
99 | | } |
100 | | |
101 | | /// A data structure containing the necessary era data for constructing a |
102 | | /// [`Japanese`](crate::japanese::Japanese) calendar object |
103 | | /// |
104 | | /// <div class="stab unstable"> |
105 | | /// π§ This code is considered unstable; it may change at any time, in breaking or non-breaking ways, |
106 | | /// including in SemVer minor releases. While the serde representation of data structs is guaranteed |
107 | | /// to be stable, their Rust representation might not be. Use with caution. |
108 | | /// </div> |
109 | 0 | #[icu_provider::data_struct( |
110 | 0 | marker(JapaneseErasV1Marker, "calendar/japanese@1", singleton), |
111 | 0 | marker(JapaneseExtendedErasV1Marker, "calendar/japanext@1", singleton) |
112 | 0 | )] Unexecuted instantiation: <icu_calendar::provider::JapaneseErasV1 as yoke::yokeable::Yokeable>::transform Unexecuted instantiation: <icu_calendar::provider::JapaneseErasV1 as zerofrom::zero_from::ZeroFrom<icu_calendar::provider::JapaneseErasV1>>::zero_from Unexecuted instantiation: <icu_calendar::provider::JapaneseErasV1 as yoke::yokeable::Yokeable>::transform_owned Unexecuted instantiation: <icu_calendar::provider::JapaneseErasV1 as yoke::yokeable::Yokeable>::transform_mut::<_> |
113 | | #[derive(Debug, PartialEq, Clone, Default)] |
114 | | #[cfg_attr( |
115 | | feature = "datagen", |
116 | | derive(serde::Serialize, databake::Bake), |
117 | | databake(path = icu_calendar::provider), |
118 | | )] |
119 | | #[cfg_attr(feature = "serde", derive(serde::Deserialize))] |
120 | | pub struct JapaneseErasV1<'data> { |
121 | | /// A map from era start dates to their era codes |
122 | | #[cfg_attr(feature = "serde", serde(borrow))] |
123 | | pub dates_to_eras: ZeroVec<'data, (EraStartDate, TinyStr16)>, |
124 | | } |
125 | | |
126 | | impl FromStr for EraStartDate { |
127 | | type Err = (); |
128 | 0 | fn from_str(mut s: &str) -> Result<Self, Self::Err> { |
129 | 0 | let sign = if let Some(suffix) = s.strip_prefix('-') { |
130 | 0 | s = suffix; |
131 | 0 | -1 |
132 | | } else { |
133 | 0 | 1 |
134 | | }; |
135 | | |
136 | 0 | let mut split = s.split('-'); |
137 | 0 | let year = split.next().ok_or(())?.parse::<i32>().map_err(|_| ())? * sign; |
138 | 0 | let month = split.next().ok_or(())?.parse().map_err(|_| ())?; |
139 | 0 | let day = split.next().ok_or(())?.parse().map_err(|_| ())?; |
140 | | |
141 | 0 | Ok(EraStartDate { year, month, day }) |
142 | 0 | } |
143 | | } |
144 | | |
145 | | /// An ICU4X mapping to a subset of CLDR weekData. |
146 | | /// See CLDR-JSON's weekData.json for more context. |
147 | | /// |
148 | | /// <div class="stab unstable"> |
149 | | /// π§ This code is considered unstable; it may change at any time, in breaking or non-breaking ways, |
150 | | /// including in SemVer minor releases. While the serde representation of data structs is guaranteed |
151 | | /// to be stable, their Rust representation might not be. Use with caution. |
152 | | /// </div> |
153 | 0 | #[icu_provider::data_struct(marker( |
154 | 0 | WeekDataV1Marker, |
155 | 0 | "datetime/week_data@1", |
156 | 0 | fallback_by = "region" |
157 | 0 | ))] Unexecuted instantiation: <icu_calendar::provider::WeekDataV1 as yoke::yokeable::Yokeable>::make Unexecuted instantiation: <icu_calendar::provider::WeekDataV1 as yoke::yokeable::Yokeable>::transform Unexecuted instantiation: <icu_calendar::provider::WeekDataV1 as zerofrom::zero_from::ZeroFrom<icu_calendar::provider::WeekDataV1>>::zero_from Unexecuted instantiation: <icu_calendar::provider::WeekDataV1 as yoke::yokeable::Yokeable>::transform Unexecuted instantiation: <icu_calendar::provider::WeekDataV1 as yoke::yokeable::Yokeable>::transform_owned Unexecuted instantiation: <icu_calendar::provider::WeekDataV1 as yoke::yokeable::Yokeable>::make Unexecuted instantiation: <icu_calendar::provider::WeekDataV1 as yoke::yokeable::Yokeable>::transform_mut::<_> |
158 | | #[derive(Clone, Copy, Debug, PartialEq)] |
159 | | #[cfg_attr( |
160 | | feature = "datagen", |
161 | | derive(serde::Serialize, databake::Bake), |
162 | | databake(path = icu_calendar::provider), |
163 | | )] |
164 | | #[cfg_attr(feature = "serde", derive(serde::Deserialize))] |
165 | | #[allow(clippy::exhaustive_structs)] // used in data provider |
166 | | pub struct WeekDataV1 { |
167 | | /// The first day of a week. |
168 | | pub first_weekday: IsoWeekday, |
169 | | /// For a given week, the minimum number of that week's days present in a given month or year for the week to be considered part of that month or year. |
170 | | pub min_week_days: u8, |
171 | | } |
172 | | |
173 | | /// An ICU4X mapping to a subset of CLDR weekData. |
174 | | /// See CLDR-JSON's weekData.json for more context. |
175 | | /// |
176 | | /// <div class="stab unstable"> |
177 | | /// π§ This code is considered unstable; it may change at any time, in breaking or non-breaking ways, |
178 | | /// including in SemVer minor releases. While the serde representation of data structs is guaranteed |
179 | | /// to be stable, their Rust representation might not be. Use with caution. |
180 | | /// </div> |
181 | 0 | #[icu_provider::data_struct(marker( |
182 | 0 | WeekDataV2Marker, |
183 | 0 | "datetime/week_data@2", |
184 | 0 | fallback_by = "region" |
185 | 0 | ))] Unexecuted instantiation: <icu_calendar::provider::WeekDataV2 as yoke::yokeable::Yokeable>::make Unexecuted instantiation: <icu_calendar::provider::WeekDataV2 as yoke::yokeable::Yokeable>::transform Unexecuted instantiation: <icu_calendar::provider::WeekDataV2 as zerofrom::zero_from::ZeroFrom<icu_calendar::provider::WeekDataV2>>::zero_from Unexecuted instantiation: <icu_calendar::provider::WeekDataV2 as yoke::yokeable::Yokeable>::transform_owned Unexecuted instantiation: <icu_calendar::provider::WeekDataV2 as yoke::yokeable::Yokeable>::make Unexecuted instantiation: <icu_calendar::provider::WeekDataV2 as yoke::yokeable::Yokeable>::transform_mut::<_> |
186 | | #[derive(Clone, Copy, Debug, PartialEq)] |
187 | | #[cfg_attr(feature = "datagen", derive(serde::Serialize, databake::Bake), databake(path = icu_calendar::provider))] |
188 | | #[cfg_attr(feature = "serde", derive(serde::Deserialize))] |
189 | | #[allow(clippy::exhaustive_structs)] // used in data provider |
190 | | pub struct WeekDataV2 { |
191 | | /// The first day of a week. |
192 | | pub first_weekday: IsoWeekday, |
193 | | /// For a given week, the minimum number of that week's days present in a given month or year for the week to be considered part of that month or year. |
194 | | pub min_week_days: u8, |
195 | | /// Bitset representing weekdays that are part of the 'weekend', for calendar purposes. |
196 | | /// The number of days can be different between locales, and may not be contiguous. |
197 | | pub weekend: WeekdaySet, |
198 | | } |
199 | | |
200 | | /// Bitset representing weekdays. |
201 | | // |
202 | | // This Bitset uses an [u8] to represent the weekend, thus leaving one bit free. |
203 | | // Each bit represents a day in the following order: |
204 | | // |
205 | | // ββ·Mon |
206 | | // βββ·Tue |
207 | | // ββββ·Wed |
208 | | // βββββ·Thu |
209 | | // ββββ ββ·Fri |
210 | | // ββββ βββ·Sat |
211 | | // ββββ ββββ·Sun |
212 | | // ββββ βββ |
213 | | // 0b0000_1010 |
214 | | // |
215 | | // Please note that this is not a range, this are the discrete days representing a weekend. Other examples: |
216 | | // 0b0101_1000 -> Tue, Thu, Fri |
217 | | // 0b0000_0110 -> Sat, Sun |
218 | | #[derive(Clone, Copy, Debug, PartialEq)] |
219 | | pub struct WeekdaySet(u8); |
220 | | |
221 | | impl WeekdaySet { |
222 | | /// Returns whether the set contains the day. |
223 | 0 | pub const fn contains(&self, day: IsoWeekday) -> bool { |
224 | 0 | self.0 & day.bit_value() != 0 |
225 | 0 | } |
226 | | } |
227 | | |
228 | | impl WeekdaySet { |
229 | | /// Creates a new [WeekdaySet] using the provided days. |
230 | 0 | pub const fn new(days: &[IsoWeekday]) -> Self { |
231 | 0 | let mut i = 0; |
232 | 0 | let mut w = 0; |
233 | | #[allow(clippy::indexing_slicing)] |
234 | 0 | while i < days.len() { |
235 | 0 | w |= days[i].bit_value(); |
236 | 0 | i += 1; |
237 | 0 | } |
238 | 0 | Self(w) |
239 | 0 | } |
240 | | } |
241 | | |
242 | | impl IsoWeekday { |
243 | | /// Defines the bit order used for encoding and reading weekend days. |
244 | 0 | const fn bit_value(&self) -> u8 { |
245 | 0 | match self { |
246 | 0 | IsoWeekday::Monday => 1 << 6, |
247 | 0 | IsoWeekday::Tuesday => 1 << 5, |
248 | 0 | IsoWeekday::Wednesday => 1 << 4, |
249 | 0 | IsoWeekday::Thursday => 1 << 3, |
250 | 0 | IsoWeekday::Friday => 1 << 2, |
251 | 0 | IsoWeekday::Saturday => 1 << 1, |
252 | 0 | IsoWeekday::Sunday => 1 << 0, |
253 | | } |
254 | 0 | } |
255 | | } |
256 | | |
257 | | #[cfg(feature = "datagen")] |
258 | | impl databake::Bake for WeekdaySet { |
259 | | fn bake(&self, ctx: &databake::CrateEnv) -> databake::TokenStream { |
260 | | ctx.insert("icu_calendar"); |
261 | | let days = |
262 | | crate::week_of::WeekdaySetIterator::new(IsoWeekday::Monday, *self).map(|d| d.bake(ctx)); |
263 | | databake::quote! { |
264 | | icu_calendar::provider::WeekdaySet::new(&[#(#days),*]) |
265 | | } |
266 | | } |
267 | | } |
268 | | |
269 | | #[cfg(feature = "datagen")] |
270 | | impl serde::Serialize for WeekdaySet { |
271 | | fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> |
272 | | where |
273 | | S: serde::Serializer, |
274 | | { |
275 | | if serializer.is_human_readable() { |
276 | | crate::week_of::WeekdaySetIterator::new(IsoWeekday::Monday, *self) |
277 | | .collect::<alloc::vec::Vec<_>>() |
278 | | .serialize(serializer) |
279 | | } else { |
280 | | self.0.serialize(serializer) |
281 | | } |
282 | | } |
283 | | } |
284 | | |
285 | | #[cfg(feature = "serde")] |
286 | | impl<'de> serde::Deserialize<'de> for WeekdaySet { |
287 | | fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> |
288 | | where |
289 | | D: serde::Deserializer<'de>, |
290 | | { |
291 | | if deserializer.is_human_readable() { |
292 | | alloc::vec::Vec::<IsoWeekday>::deserialize(deserializer).map(|s| Self::new(&s)) |
293 | | } else { |
294 | | u8::deserialize(deserializer).map(Self) |
295 | | } |
296 | | } |
297 | | } |
298 | | |
299 | | #[test] |
300 | | fn test_weekdayset_bake() { |
301 | | databake::test_bake!( |
302 | | WeekdaySet, |
303 | | const: crate::provider::WeekdaySet::new( |
304 | | &[crate::types::IsoWeekday::Monday, crate::types::IsoWeekday::Wednesday, crate::types::IsoWeekday::Friday]), |
305 | | icu_calendar |
306 | | ); |
307 | | } |
308 | | |
309 | | #[test] |
310 | | fn test_weekdayset_new() { |
311 | | use IsoWeekday::*; |
312 | | |
313 | | let sat_sun_bitmap = Saturday.bit_value() | Sunday.bit_value(); |
314 | | let sat_sun_weekend = WeekdaySet::new(&[Saturday, Sunday]); |
315 | | assert_eq!(sat_sun_bitmap, sat_sun_weekend.0); |
316 | | |
317 | | let fri_sat_bitmap = Friday.bit_value() | Saturday.bit_value(); |
318 | | let fri_sat_weekend = WeekdaySet::new(&[Friday, Saturday]); |
319 | | assert_eq!(fri_sat_bitmap, fri_sat_weekend.0); |
320 | | |
321 | | let fri_sun_bitmap = Friday.bit_value() | Sunday.bit_value(); |
322 | | let fri_sun_weekend = WeekdaySet::new(&[Friday, Sunday]); |
323 | | assert_eq!(fri_sun_bitmap, fri_sun_weekend.0); |
324 | | |
325 | | let fri_bitmap = Friday.bit_value(); |
326 | | let fri_weekend = WeekdaySet::new(&[Friday, Friday]); |
327 | | assert_eq!(fri_bitmap, fri_weekend.0); |
328 | | |
329 | | let sun_mon_bitmap = Sunday.bit_value() | Monday.bit_value(); |
330 | | let sun_mon_weekend = WeekdaySet::new(&[Sunday, Monday]); |
331 | | assert_eq!(sun_mon_bitmap, sun_mon_weekend.0); |
332 | | |
333 | | let mon_sun_bitmap = Monday.bit_value() | Sunday.bit_value(); |
334 | | let mon_sun_weekend = WeekdaySet::new(&[Monday, Sunday]); |
335 | | assert_eq!(mon_sun_bitmap, mon_sun_weekend.0); |
336 | | |
337 | | let mon_bitmap = Monday.bit_value(); |
338 | | let mon_weekend = WeekdaySet::new(&[Monday]); |
339 | | assert_eq!(mon_bitmap, mon_weekend.0); |
340 | | } |