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