Coverage Report

Created: 2025-07-11 06:39

/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
}