1#![allow(clippy::exhaustive_structs, clippy::exhaustive_enums)]
17
18pub mod chinese_based;
19pub mod hijri;
20pub use chinese_based::{CalendarChineseV1, CalendarDangiV1};
21pub use hijri::CalendarHijriSimulatedMeccaV1;
22
23use crate::types::Weekday;
24use icu_provider::fallback::{LocaleFallbackConfig, LocaleFallbackPriority};
25use icu_provider::prelude::*;
26use tinystr::TinyStr16;
27use zerovec::ZeroVec;
28
29#[cfg(feature = "compiled_data")]
30#[derive(Debug)]
31pub struct Baked;
39
40#[cfg(feature = "compiled_data")]
41#[allow(unused_imports)]
42const _: () = {
43 use icu_calendar_data::*;
44 pub mod icu {
45 pub use crate as calendar;
46 pub use icu_locale as locale;
47 }
48 make_provider!(Baked);
49 impl_calendar_chinese_v1!(Baked);
50 impl_calendar_dangi_v1!(Baked);
51 impl_calendar_hijri_simulated_mecca_v1!(Baked);
52 impl_calendar_japanese_modern_v1!(Baked);
53 impl_calendar_japanese_extended_v1!(Baked);
54 impl_calendar_week_v1!(Baked);
55};
56
57icu_provider::data_marker!(
58 CalendarJapaneseModernV1,
60 "calendar/japanese/modern/v1",
61 JapaneseEras<'static>,
62 is_singleton = true
63);
64icu_provider::data_marker!(
65 CalendarJapaneseExtendedV1,
67 "calendar/japanese/extended/v1",
68 JapaneseEras<'static>,
69 is_singleton = true
70);
71icu_provider::data_marker!(
72 CalendarWeekV1,
74 "calendar/week/v1",
75 WeekData,
76 fallback_config = {
77 let mut config = LocaleFallbackConfig::default();
78 config.priority = LocaleFallbackPriority::Region;
79 config
80 },
81);
82
83#[cfg(feature = "datagen")]
84pub const MARKERS: &[DataMarkerInfo] = &[
86 CalendarChineseV1::INFO,
87 CalendarDangiV1::INFO,
88 CalendarHijriSimulatedMeccaV1::INFO,
89 CalendarJapaneseModernV1::INFO,
90 CalendarJapaneseExtendedV1::INFO,
91 CalendarWeekV1::INFO,
92];
93
94#[zerovec::make_ule(EraStartDateULE)]
104#[derive(
105 Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Debug, yoke::Yokeable, zerofrom::ZeroFrom,
106)]
107#[cfg_attr(feature = "datagen", derive(serde::Serialize, databake::Bake))]
108#[cfg_attr(feature = "datagen", databake(path = icu_calendar::provider))]
109#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
110pub struct EraStartDate {
111 pub year: i32,
113 pub month: u8,
115 pub day: u8,
117}
118
119#[derive(Debug, PartialEq, Clone, Default, yoke::Yokeable, zerofrom::ZeroFrom)]
128#[cfg_attr(feature = "datagen", derive(serde::Serialize, databake::Bake))]
129#[cfg_attr(feature = "datagen", databake(path = icu_calendar::provider))]
130#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
131pub struct JapaneseEras<'data> {
132 #[cfg_attr(feature = "serde", serde(borrow))]
134 pub dates_to_eras: ZeroVec<'data, (EraStartDate, TinyStr16)>,
135}
136
137icu_provider::data_struct!(
138 JapaneseEras<'_>,
139 #[cfg(feature = "datagen")]
140);
141
142#[derive(Clone, Copy, Debug, PartialEq, yoke::Yokeable, zerofrom::ZeroFrom)]
151#[cfg_attr(feature = "datagen", derive(serde::Serialize, databake::Bake))]
152#[cfg_attr(feature = "datagen", databake(path = icu_calendar::provider))]
153#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
154#[allow(clippy::exhaustive_structs)] pub struct WeekData {
156 pub first_weekday: Weekday,
158 pub weekend: WeekdaySet,
161}
162
163icu_provider::data_struct!(
164 WeekData,
165 #[cfg(feature = "datagen")]
166);
167
168#[derive(Clone, Copy, Debug, PartialEq)]
187pub struct WeekdaySet(u8);
188
189impl WeekdaySet {
190 pub const fn contains(&self, day: Weekday) -> bool {
192 self.0 & day.bit_value() != 0
193 }
194}
195
196impl WeekdaySet {
197 pub const fn new(days: &[Weekday]) -> Self {
199 let mut i = 0;
200 let mut w = 0;
201 #[allow(clippy::indexing_slicing)]
202 while i < days.len() {
203 w |= days[i].bit_value();
204 i += 1;
205 }
206 Self(w)
207 }
208}
209
210impl Weekday {
211 const fn bit_value(self) -> u8 {
213 match self {
214 Weekday::Monday => 1 << 6,
215 Weekday::Tuesday => 1 << 5,
216 Weekday::Wednesday => 1 << 4,
217 Weekday::Thursday => 1 << 3,
218 Weekday::Friday => 1 << 2,
219 Weekday::Saturday => 1 << 1,
220 Weekday::Sunday => 1 << 0,
221 }
222 }
223}
224
225#[cfg(feature = "datagen")]
226impl databake::Bake for WeekdaySet {
227 fn bake(&self, ctx: &databake::CrateEnv) -> databake::TokenStream {
228 ctx.insert("icu_calendar");
229 let days =
230 crate::week::WeekdaySetIterator::new(Weekday::Monday, *self).map(|d| d.bake(ctx));
231 databake::quote! {
232 icu_calendar::provider::WeekdaySet::new(&[#(#days),*])
233 }
234 }
235}
236
237#[cfg(feature = "datagen")]
238impl databake::BakeSize for WeekdaySet {
239 fn borrows_size(&self) -> usize {
240 0
241 }
242}
243
244#[cfg(feature = "datagen")]
245impl serde::Serialize for WeekdaySet {
246 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
247 where
248 S: serde::Serializer,
249 {
250 if serializer.is_human_readable() {
251 use serde::ser::SerializeSeq;
252
253 let mut seq = serializer.serialize_seq(None)?;
254 for day in crate::week::WeekdaySetIterator::new(Weekday::Monday, *self) {
255 seq.serialize_element(&day)?;
256 }
257 seq.end()
258 } else {
259 self.0.serialize(serializer)
260 }
261 }
262}
263
264#[cfg(feature = "serde")]
265impl<'de> serde::Deserialize<'de> for WeekdaySet {
266 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
267 where
268 D: serde::Deserializer<'de>,
269 {
270 if deserializer.is_human_readable() {
271 use core::marker::PhantomData;
272
273 struct Visitor<'de>(PhantomData<&'de ()>);
274 impl<'de> serde::de::Visitor<'de> for Visitor<'de> {
275 type Value = WeekdaySet;
276 fn expecting(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
277 core::write!(f, "a sequence of Weekdays")
278 }
279 fn visit_seq<A: serde::de::SeqAccess<'de>>(
280 self,
281 mut seq: A,
282 ) -> Result<Self::Value, A::Error> {
283 let mut set = WeekdaySet::new(&[]);
284 while let Some(day) = seq.next_element::<Weekday>()? {
285 set.0 |= day.bit_value();
286 }
287 Ok(set)
288 }
289 }
290 deserializer.deserialize_seq(Visitor(PhantomData))
291 } else {
292 u8::deserialize(deserializer).map(Self)
293 }
294 }
295}
296
297#[test]
298fn test_weekdayset_bake() {
299 databake::test_bake!(
300 WeekdaySet,
301 const,
302 crate::provider::WeekdaySet::new(&[
303 crate::types::Weekday::Monday,
304 crate::types::Weekday::Wednesday,
305 crate::types::Weekday::Friday
306 ]),
307 icu_calendar
308 );
309}
310
311#[test]
312fn test_weekdayset_new() {
313 use Weekday::*;
314
315 let sat_sun_bitmap = Saturday.bit_value() | Sunday.bit_value();
316 let sat_sun_weekend = WeekdaySet::new(&[Saturday, Sunday]);
317 assert_eq!(sat_sun_bitmap, sat_sun_weekend.0);
318
319 let fri_sat_bitmap = Friday.bit_value() | Saturday.bit_value();
320 let fri_sat_weekend = WeekdaySet::new(&[Friday, Saturday]);
321 assert_eq!(fri_sat_bitmap, fri_sat_weekend.0);
322
323 let fri_sun_bitmap = Friday.bit_value() | Sunday.bit_value();
324 let fri_sun_weekend = WeekdaySet::new(&[Friday, Sunday]);
325 assert_eq!(fri_sun_bitmap, fri_sun_weekend.0);
326
327 let fri_bitmap = Friday.bit_value();
328 let fri_weekend = WeekdaySet::new(&[Friday, Friday]);
329 assert_eq!(fri_bitmap, fri_weekend.0);
330
331 let sun_mon_bitmap = Sunday.bit_value() | Monday.bit_value();
332 let sun_mon_weekend = WeekdaySet::new(&[Sunday, Monday]);
333 assert_eq!(sun_mon_bitmap, sun_mon_weekend.0);
334
335 let mon_sun_bitmap = Monday.bit_value() | Sunday.bit_value();
336 let mon_sun_weekend = WeekdaySet::new(&[Monday, Sunday]);
337 assert_eq!(mon_sun_bitmap, mon_sun_weekend.0);
338
339 let mon_bitmap = Monday.bit_value();
340 let mon_weekend = WeekdaySet::new(&[Monday]);
341 assert_eq!(mon_bitmap, mon_weekend.0);
342}