icu_datetime/provider/neo/
mod.rs

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//! Data structs and markers for semantic skeletons and datetime names.
6
7use crate::provider::pattern::runtime;
8use crate::size_test_macro::size_test;
9use alloc::borrow::Cow;
10use icu_pattern::SinglePlaceholderPattern;
11use icu_provider::prelude::*;
12use potential_utf::PotentialUtf8;
13use zerovec::{ule::tuplevar::Tuple2VarULE, VarZeroCow, VarZeroSlice, VarZeroVec};
14
15/// Helpers involving the data marker attributes used for date names.
16///
17/// <div class="stab unstable">
18/// 🚧 This code is considered unstable; it may change at any time, in breaking or non-breaking ways,
19/// including in SemVer minor releases. While the serde representation of data structs is guaranteed
20/// to be stable, their Rust representation might not be. Use with caution.
21/// </div>
22#[allow(missing_docs)]
23pub mod marker_attrs {
24    use icu_provider::DataMarkerAttributes;
25
26    pub const NUMERIC: &DataMarkerAttributes = DataMarkerAttributes::from_str_or_panic("1");
27    pub const ABBR: &DataMarkerAttributes = DataMarkerAttributes::from_str_or_panic("3");
28    pub const NARROW: &DataMarkerAttributes = DataMarkerAttributes::from_str_or_panic("4");
29    pub const WIDE: &DataMarkerAttributes = DataMarkerAttributes::from_str_or_panic("5");
30    pub const SHORT: &DataMarkerAttributes = DataMarkerAttributes::from_str_or_panic("6");
31    pub const ABBR_STANDALONE: &DataMarkerAttributes =
32        DataMarkerAttributes::from_str_or_panic("3s");
33    pub const NARROW_STANDALONE: &DataMarkerAttributes =
34        DataMarkerAttributes::from_str_or_panic("4s");
35    pub const WIDE_STANDALONE: &DataMarkerAttributes =
36        DataMarkerAttributes::from_str_or_panic("5s");
37    pub const SHORT_STANDALONE: &DataMarkerAttributes =
38        DataMarkerAttributes::from_str_or_panic("6s");
39
40    pub const PATTERN_LONG: &DataMarkerAttributes = DataMarkerAttributes::from_str_or_panic("l");
41    pub const PATTERN_MEDIUM: &DataMarkerAttributes = DataMarkerAttributes::from_str_or_panic("m");
42    pub const PATTERN_SHORT: &DataMarkerAttributes = DataMarkerAttributes::from_str_or_panic("s");
43
44    // TODO: The 12-hour and 24-hour DataMarkerAttributes can probably be deleted
45
46    pub const PATTERN_LONG12: &DataMarkerAttributes =
47        DataMarkerAttributes::from_str_or_panic("l12");
48    pub const PATTERN_MEDIUM12: &DataMarkerAttributes =
49        DataMarkerAttributes::from_str_or_panic("m12");
50    pub const PATTERN_SHORT12: &DataMarkerAttributes =
51        DataMarkerAttributes::from_str_or_panic("s12");
52
53    pub const PATTERN_LONG24: &DataMarkerAttributes =
54        DataMarkerAttributes::from_str_or_panic("l24");
55    pub const PATTERN_MEDIUM24: &DataMarkerAttributes =
56        DataMarkerAttributes::from_str_or_panic("m24");
57    pub const PATTERN_SHORT24: &DataMarkerAttributes =
58        DataMarkerAttributes::from_str_or_panic("s24");
59
60    pub const PATTERN_LONG_DT: &DataMarkerAttributes =
61        DataMarkerAttributes::from_str_or_panic("ldt");
62    pub const PATTERN_MEDIUM_DT: &DataMarkerAttributes =
63        DataMarkerAttributes::from_str_or_panic("mdt");
64    pub const PATTERN_SHORT_DT: &DataMarkerAttributes =
65        DataMarkerAttributes::from_str_or_panic("sdt");
66
67    pub const PATTERN_LONG_DZ: &DataMarkerAttributes =
68        DataMarkerAttributes::from_str_or_panic("ldz");
69    pub const PATTERN_MEDIUM_DZ: &DataMarkerAttributes =
70        DataMarkerAttributes::from_str_or_panic("mdz");
71    pub const PATTERN_SHORT_DZ: &DataMarkerAttributes =
72        DataMarkerAttributes::from_str_or_panic("sdz");
73
74    pub const PATTERN_LONG_TZ: &DataMarkerAttributes =
75        DataMarkerAttributes::from_str_or_panic("ltz");
76    pub const PATTERN_MEDIUM_TZ: &DataMarkerAttributes =
77        DataMarkerAttributes::from_str_or_panic("mtz");
78    pub const PATTERN_SHORT_TZ: &DataMarkerAttributes =
79        DataMarkerAttributes::from_str_or_panic("stz");
80
81    pub const PATTERN_LONG_DTZ: &DataMarkerAttributes =
82        DataMarkerAttributes::from_str_or_panic("ldtz");
83    pub const PATTERN_MEDIUM_DTZ: &DataMarkerAttributes =
84        DataMarkerAttributes::from_str_or_panic("mdtz");
85    pub const PATTERN_SHORT_DTZ: &DataMarkerAttributes =
86        DataMarkerAttributes::from_str_or_panic("sdtz");
87
88    pub const NUMERIC_STR: &str = NUMERIC.as_str();
89    pub const ABBR_STR: &str = ABBR.as_str();
90    pub const NARROW_STR: &str = NARROW.as_str();
91    pub const WIDE_STR: &str = WIDE.as_str();
92    pub const SHORT_STR: &str = SHORT.as_str();
93    pub const ABBR_STANDALONE_STR: &str = ABBR_STANDALONE.as_str();
94    pub const NARROW_STANDALONE_STR: &str = NARROW_STANDALONE.as_str();
95    pub const WIDE_STANDALONE_STR: &str = WIDE_STANDALONE.as_str();
96    pub const SHORT_STANDALONE_STR: &str = SHORT_STANDALONE.as_str();
97
98    pub const PATTERN_LONG_STR: &str = PATTERN_LONG.as_str();
99    pub const PATTERN_MEDIUM_STR: &str = PATTERN_MEDIUM.as_str();
100    pub const PATTERN_SHORT_STR: &str = PATTERN_SHORT.as_str();
101
102    pub const PATTERN_LONG12_STR: &str = PATTERN_LONG12.as_str();
103    pub const PATTERN_MEDIUM12_STR: &str = PATTERN_MEDIUM12.as_str();
104    pub const PATTERN_SHORT12_STR: &str = PATTERN_SHORT12.as_str();
105
106    pub const PATTERN_LONG24_STR: &str = PATTERN_LONG24.as_str();
107    pub const PATTERN_MEDIUM24_STR: &str = PATTERN_MEDIUM24.as_str();
108    pub const PATTERN_SHORT24_STR: &str = PATTERN_SHORT24.as_str();
109
110    pub const PATTERN_LONG_DT_STR: &str = PATTERN_LONG_DT.as_str();
111    pub const PATTERN_MEDIUM_DT_STR: &str = PATTERN_MEDIUM_DT.as_str();
112    pub const PATTERN_SHORT_DT_STR: &str = PATTERN_SHORT_DT.as_str();
113
114    pub const PATTERN_LONG_DZ_STR: &str = PATTERN_LONG_DZ.as_str();
115    pub const PATTERN_MEDIUM_DZ_STR: &str = PATTERN_MEDIUM_DZ.as_str();
116    pub const PATTERN_SHORT_DZ_STR: &str = PATTERN_SHORT_DZ.as_str();
117
118    pub const PATTERN_LONG_TZ_STR: &str = PATTERN_LONG_TZ.as_str();
119    pub const PATTERN_MEDIUM_TZ_STR: &str = PATTERN_MEDIUM_TZ.as_str();
120    pub const PATTERN_SHORT_TZ_STR: &str = PATTERN_SHORT_TZ.as_str();
121
122    pub const PATTERN_LONG_DTZ_STR: &str = PATTERN_LONG_DTZ.as_str();
123    pub const PATTERN_MEDIUM_DTZ_STR: &str = PATTERN_MEDIUM_DTZ.as_str();
124    pub const PATTERN_SHORT_DTZ_STR: &str = PATTERN_SHORT_DTZ.as_str();
125
126    /// Field lengths supported in data marker attribute.
127    ///
128    /// For a stable version of this enum, use one of the length enums in [`pattern`].
129    ///
130    /// <div class="stab unstable">
131    /// 🚧 This code is considered unstable; it may change at any time, in breaking or non-breaking ways,
132    /// including in SemVer minor releases. While the serde representation of data structs is guaranteed
133    /// to be stable, their Rust representation might not be. Use with caution.
134    /// </div>
135    ///
136    /// [`pattern`]: crate::pattern
137    #[derive(Copy, Clone, Debug, PartialEq, Eq)]
138    #[allow(clippy::exhaustive_enums)] // documented as unstable
139    pub enum Length {
140        Abbr,
141        Narrow,
142        Wide,
143        Short,
144        Numeric,
145    }
146
147    /// Pattern lengths supported in data marker attributes.
148    ///
149    /// For a stable version of this enum, use [`Length`].
150    ///
151    /// <div class="stab unstable">
152    /// 🚧 This code is considered unstable; it may change at any time, in breaking or non-breaking ways,
153    /// including in SemVer minor releases. While the serde representation of data structs is guaranteed
154    /// to be stable, their Rust representation might not be. Use with caution.
155    /// </div>
156    ///
157    /// [`Length`]: crate::options::Length
158    #[derive(Copy, Clone, Debug, PartialEq, Eq)]
159    pub enum PatternLength {
160        Long,
161        Medium,
162        Short,
163    }
164
165    /// Field contexts supported in data marker attributes.
166    ///
167    /// For a stable version of this enum, use one of the specific field symbol enums in [`fields`].
168    ///
169    /// <div class="stab unstable">
170    /// 🚧 This code is considered unstable; it may change at any time, in breaking or non-breaking ways,
171    /// including in SemVer minor releases. While the serde representation of data structs is guaranteed
172    /// to be stable, their Rust representation might not be. Use with caution.
173    /// </div>
174    ///
175    /// [`fields`]: crate::provider::fields
176    #[derive(Copy, Clone, Debug, PartialEq, Eq)]
177    #[allow(clippy::exhaustive_enums)] // documented as unstable
178    pub enum Context {
179        Format,
180        Standalone,
181    }
182
183    /// Date, time, and time zone combinations supported in data marker attributes.
184    ///
185    /// <div class="stab unstable">
186    /// 🚧 This code is considered unstable; it may change at any time, in breaking or non-breaking ways,
187    /// including in SemVer minor releases. While the serde representation of data structs is guaranteed
188    /// to be stable, their Rust representation might not be. Use with caution.
189    /// </div>
190    ///
191    /// [`fields`]: crate::provider::fields
192    #[derive(Copy, Clone, Debug, PartialEq, Eq)]
193    #[allow(clippy::exhaustive_enums)] // documented as unstable
194    pub enum GlueType {
195        DateTime,
196        DateZone,
197        TimeZone,
198        DateTimeZone,
199    }
200
201    /// Parses a name data marker attribute to enum values.
202    ///
203    /// <div class="stab unstable">
204    /// 🚧 This code is considered unstable; it may change at any time, in breaking or non-breaking ways,
205    /// including in SemVer minor releases. While the serde representation of data structs is guaranteed
206    /// to be stable, their Rust representation might not be. Use with caution.
207    /// </div>
208    pub fn name_marker_attr_info(marker_attr: &DataMarkerAttributes) -> Option<(Context, Length)> {
209        use {Context::*, Length::*};
210        match &**marker_attr {
211            NUMERIC_STR => Some((Format, Numeric)),
212            ABBR_STR => Some((Format, Abbr)),
213            NARROW_STR => Some((Format, Narrow)),
214            WIDE_STR => Some((Format, Wide)),
215            SHORT_STR => Some((Format, Short)),
216            ABBR_STANDALONE_STR => Some((Standalone, Abbr)),
217            NARROW_STANDALONE_STR => Some((Standalone, Narrow)),
218            WIDE_STANDALONE_STR => Some((Standalone, Wide)),
219            SHORT_STANDALONE_STR => Some((Standalone, Short)),
220            _ => None,
221        }
222    }
223
224    /// Parses a pattern data marker attribute to enum values.
225    ///
226    /// <div class="stab unstable">
227    /// 🚧 This code is considered unstable; it may change at any time, in breaking or non-breaking ways,
228    /// including in SemVer minor releases. While the serde representation of data structs is guaranteed
229    /// to be stable, their Rust representation might not be. Use with caution.
230    /// </div>
231    pub fn pattern_marker_attr_info_for_glue(
232        marker_attr: &DataMarkerAttributes,
233    ) -> Option<(PatternLength, GlueType)> {
234        use {GlueType::*, PatternLength::*};
235        match &**marker_attr {
236            PATTERN_LONG_DT_STR => Some((Long, DateTime)),
237            PATTERN_MEDIUM_DT_STR => Some((Medium, DateTime)),
238            PATTERN_SHORT_DT_STR => Some((Short, DateTime)),
239
240            PATTERN_LONG_DZ_STR => Some((Long, DateZone)),
241            PATTERN_MEDIUM_DZ_STR => Some((Medium, DateZone)),
242            PATTERN_SHORT_DZ_STR => Some((Short, DateZone)),
243
244            PATTERN_LONG_TZ_STR => Some((Long, TimeZone)),
245            PATTERN_MEDIUM_TZ_STR => Some((Medium, TimeZone)),
246            PATTERN_SHORT_TZ_STR => Some((Short, TimeZone)),
247
248            PATTERN_LONG_DTZ_STR => Some((Long, DateTimeZone)),
249            PATTERN_MEDIUM_DTZ_STR => Some((Medium, DateTimeZone)),
250            PATTERN_SHORT_DTZ_STR => Some((Short, DateTimeZone)),
251
252            _ => None,
253        }
254    }
255
256    /// Creates a name data marker attribute from the enum values.
257    ///
258    /// <div class="stab unstable">
259    /// 🚧 This code is considered unstable; it may change at any time, in breaking or non-breaking ways,
260    /// including in SemVer minor releases. While the serde representation of data structs is guaranteed
261    /// to be stable, their Rust representation might not be. Use with caution.
262    /// </div>
263    pub fn name_attr_for(context: Context, length: Length) -> &'static DataMarkerAttributes {
264        use {Context::*, Length::*};
265        match (context, length) {
266            (Format, Numeric) => NUMERIC,
267            (Format, Abbr) => ABBR,
268            (Format, Narrow) => NARROW,
269            (Format, Wide) => WIDE,
270            (Format, Short) => SHORT,
271            (Standalone, Numeric) => NUMERIC,
272            (Standalone, Abbr) => ABBR_STANDALONE,
273            (Standalone, Narrow) => NARROW_STANDALONE,
274            (Standalone, Wide) => WIDE_STANDALONE,
275            (Standalone, Short) => SHORT_STANDALONE,
276        }
277    }
278
279    pub fn pattern_marker_attr_for_glue(
280        length: PatternLength,
281        glue_type: GlueType,
282    ) -> &'static DataMarkerAttributes {
283        use {GlueType::*, PatternLength::*};
284        match (length, glue_type) {
285            (Long, DateTime) => PATTERN_LONG_DT,
286            (Medium, DateTime) => PATTERN_MEDIUM_DT,
287            (Short, DateTime) => PATTERN_SHORT_DT,
288
289            (Long, DateZone) => PATTERN_LONG_DZ,
290            (Medium, DateZone) => PATTERN_MEDIUM_DZ,
291            (Short, DateZone) => PATTERN_SHORT_DZ,
292
293            (Long, TimeZone) => PATTERN_LONG_TZ,
294            (Medium, TimeZone) => PATTERN_MEDIUM_TZ,
295            (Short, TimeZone) => PATTERN_SHORT_TZ,
296
297            (Long, DateTimeZone) => PATTERN_LONG_DTZ,
298            (Medium, DateTimeZone) => PATTERN_MEDIUM_DTZ,
299            (Short, DateTimeZone) => PATTERN_SHORT_DTZ,
300        }
301    }
302}
303
304icu_provider::data_marker!(
305    /// `DatetimeNamesYearBuddhistV1`
306    DatetimeNamesYearBuddhistV1,
307    YearNames<'static>,
308    #[cfg(feature = "datagen")]
309    attributes_domain = "datetime_year_length"
310);
311icu_provider::data_marker!(
312    /// `DatetimeNamesYearChineseV1`
313    DatetimeNamesYearChineseV1,
314    YearNames<'static>,
315    #[cfg(feature = "datagen")]
316    attributes_domain = "datetime_year_length"
317);
318icu_provider::data_marker!(
319    /// `DatetimeNamesYearCopticV1`
320    DatetimeNamesYearCopticV1,
321    YearNames<'static>,
322    #[cfg(feature = "datagen")]
323    attributes_domain = "datetime_year_length"
324);
325icu_provider::data_marker!(
326    /// `DatetimeNamesYearDangiV1`
327    DatetimeNamesYearDangiV1,
328    YearNames<'static>,
329    #[cfg(feature = "datagen")]
330    attributes_domain = "datetime_year_length"
331);
332icu_provider::data_marker!(
333    /// `DatetimeNamesYearEthiopianV1`
334    DatetimeNamesYearEthiopianV1,
335    YearNames<'static>,
336    #[cfg(feature = "datagen")]
337    attributes_domain = "datetime_year_length"
338);
339icu_provider::data_marker!(
340    /// `DatetimeNamesYearGregorianV1`
341    DatetimeNamesYearGregorianV1,
342    YearNames<'static>,
343    #[cfg(feature = "datagen")]
344    attributes_domain = "datetime_year_length"
345);
346icu_provider::data_marker!(
347    /// `DatetimeNamesYearHebrewV1`
348    DatetimeNamesYearHebrewV1,
349    YearNames<'static>,
350    #[cfg(feature = "datagen")]
351    attributes_domain = "datetime_year_length"
352);
353icu_provider::data_marker!(
354    /// `DatetimeNamesYearIndianV1`
355    DatetimeNamesYearIndianV1,
356    YearNames<'static>,
357    #[cfg(feature = "datagen")]
358    attributes_domain = "datetime_year_length"
359);
360icu_provider::data_marker!(
361    /// `DatetimeNamesYearHijriV1`
362    DatetimeNamesYearHijriV1,
363    YearNames<'static>,
364    #[cfg(feature = "datagen")]
365    attributes_domain = "datetime_year_length"
366);
367icu_provider::data_marker!(
368    /// `DatetimeNamesYearJapaneseV1`
369    DatetimeNamesYearJapaneseV1,
370    YearNames<'static>,
371    #[cfg(feature = "datagen")]
372    attributes_domain = "datetime_year_length"
373);
374icu_provider::data_marker!(
375    /// `DatetimeNamesYearJapanextV1`
376    DatetimeNamesYearJapanextV1,
377    YearNames<'static>,
378    #[cfg(feature = "datagen")]
379    attributes_domain = "datetime_year_length"
380);
381icu_provider::data_marker!(
382    /// `DatetimeNamesYearPersianV1`
383    DatetimeNamesYearPersianV1,
384    YearNames<'static>,
385    #[cfg(feature = "datagen")]
386    attributes_domain = "datetime_year_length"
387);
388icu_provider::data_marker!(
389    /// `DatetimeNamesYearRocV1`
390    DatetimeNamesYearRocV1,
391    YearNames<'static>,
392    #[cfg(feature = "datagen")]
393    attributes_domain = "datetime_year_length"
394);
395
396icu_provider::data_marker!(
397    /// `DatetimeNamesMonthBuddhistV1`
398    DatetimeNamesMonthBuddhistV1,
399    MonthNames<'static>,
400    #[cfg(feature = "datagen")]
401    attributes_domain = "datetime_month_length"
402);
403icu_provider::data_marker!(
404    /// `DatetimeNamesMonthChineseV1`
405    DatetimeNamesMonthChineseV1,
406    MonthNames<'static>,
407    #[cfg(feature = "datagen")]
408    attributes_domain = "datetime_month_length"
409);
410icu_provider::data_marker!(
411    /// `DatetimeNamesMonthCopticV1`
412    DatetimeNamesMonthCopticV1,
413    MonthNames<'static>,
414    #[cfg(feature = "datagen")]
415    attributes_domain = "datetime_month_length"
416);
417icu_provider::data_marker!(
418    /// `DatetimeNamesMonthDangiV1`
419    DatetimeNamesMonthDangiV1,
420    MonthNames<'static>,
421    #[cfg(feature = "datagen")]
422    attributes_domain = "datetime_month_length"
423);
424icu_provider::data_marker!(
425    /// `DatetimeNamesMonthEthiopianV1`
426    DatetimeNamesMonthEthiopianV1,
427    MonthNames<'static>,
428    #[cfg(feature = "datagen")]
429    attributes_domain = "datetime_month_length"
430);
431icu_provider::data_marker!(
432    /// `DatetimeNamesMonthGregorianV1`
433    DatetimeNamesMonthGregorianV1,
434    MonthNames<'static>,
435    #[cfg(feature = "datagen")]
436    attributes_domain = "datetime_month_length"
437);
438icu_provider::data_marker!(
439    /// `DatetimeNamesMonthHebrewV1`
440    DatetimeNamesMonthHebrewV1,
441    MonthNames<'static>,
442    #[cfg(feature = "datagen")]
443    attributes_domain = "datetime_month_length"
444);
445icu_provider::data_marker!(
446    /// `DatetimeNamesMonthIndianV1`
447    DatetimeNamesMonthIndianV1,
448    MonthNames<'static>,
449    #[cfg(feature = "datagen")]
450    attributes_domain = "datetime_month_length"
451);
452icu_provider::data_marker!(
453    /// `DatetimeNamesMonthHijriV1`
454    DatetimeNamesMonthHijriV1,
455    MonthNames<'static>,
456    #[cfg(feature = "datagen")]
457    attributes_domain = "datetime_month_length"
458);
459icu_provider::data_marker!(
460    /// `DatetimeNamesMonthJapaneseV1`
461    DatetimeNamesMonthJapaneseV1,
462    MonthNames<'static>,
463    #[cfg(feature = "datagen")]
464    attributes_domain = "datetime_month_length"
465);
466icu_provider::data_marker!(
467    /// `DatetimeNamesMonthJapanextV1`
468    DatetimeNamesMonthJapanextV1,
469    MonthNames<'static>,
470    #[cfg(feature = "datagen")]
471    attributes_domain = "datetime_month_length"
472);
473icu_provider::data_marker!(
474    /// `DatetimeNamesMonthPersianV1`
475    DatetimeNamesMonthPersianV1,
476    MonthNames<'static>,
477    #[cfg(feature = "datagen")]
478    attributes_domain = "datetime_month_length"
479);
480icu_provider::data_marker!(
481    /// `DatetimeNamesMonthRocV1`
482    DatetimeNamesMonthRocV1,
483    MonthNames<'static>,
484    #[cfg(feature = "datagen")]
485    attributes_domain = "datetime_month_length"
486);
487
488icu_provider::data_marker!(
489    /// `DatetimeNamesWeekdayV1`
490    DatetimeNamesWeekdayV1,
491    LinearNames<'static>,
492);
493icu_provider::data_marker!(
494    /// `DatetimeNamesDayperiodV1`
495    DatetimeNamesDayperiodV1,
496    LinearNames<'static>,
497);
498// We're not producing or using day names yet, but this is where they would go
499icu_provider::data_marker!(
500    /// `DatetimeNamesDayChineseV1`
501    DatetimeNamesDayChineseV1,
502    LinearNames<'static>,
503);
504icu_provider::data_marker!(
505    /// `DatetimeNamesDayDangiV1`
506    DatetimeNamesDayDangiV1,
507    LinearNames<'static>,
508);
509// for calendars that don't use day names
510icu_provider::data_marker!(
511    /// `DatetimeNamesDayPlaceholderV1`
512    DatetimeNamesDayPlaceholderV1,
513    LinearNames<'static>,
514);
515
516icu_provider::data_marker!(
517    /// `DatetimePatternsGlueV1`
518    DatetimePatternsGlueV1,
519    GluePattern<'static>
520);
521
522size_test!(YearNames, year_names_v1_size, 32);
523
524/// Names used for representing the year.
525///
526/// This uses a data marker attribute for length. The value is simply the number of
527/// characters in the equivalent CLDR field syntax name, plus "s" for standalone contexts. For example,
528/// "abbreviated" (e.g. `MMM`) is `3` or `3s` depending on whether it is format or standalone
529/// respectively.
530///
531/// The full list is:
532/// - 3 is "abbreviated"
533/// - 4 is "narrow"
534/// - 5 is "wide"
535/// - 6 is "short" (weekdays only)
536#[doc = year_names_v1_size!()]
537///
538/// <div class="stab unstable">
539/// 🚧 This code is considered unstable; it may change at any time, in breaking or non-breaking ways,
540/// including in SemVer minor releases. While the serde representation of data structs is guaranteed
541/// to be stable, their Rust representation might not be. Use with caution.
542/// </div>
543#[derive(Debug, PartialEq, Clone, yoke::Yokeable, zerofrom::ZeroFrom)]
544#[cfg_attr(feature = "datagen", derive(serde::Serialize, databake::Bake))]
545#[cfg_attr(feature = "datagen", databake(path = icu_datetime::provider::neo))]
546#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
547#[yoke(prove_covariance_manually)]
548pub enum YearNames<'data> {
549    /// This calendar has a small, fixed set of eras with numeric years, this stores the era names in chronological order.
550    ///
551    /// See FormattableEra for a definition of what chronological order is in this context.
552    FixedEras(#[cfg_attr(feature = "serde", serde(borrow))] VarZeroVec<'data, str>),
553    /// This calendar has a variable set of eras with numeric years, this stores the era names mapped from
554    /// era code to the name.
555    ///
556    /// Only the Japanese calendars need this
557    VariableEras(#[cfg_attr(feature = "serde", serde(borrow))] YearNamesMap<'data>),
558    /// This calendar is cyclic (Chinese, Dangi), so it uses cyclic year names without any eras
559    Cyclic(#[cfg_attr(feature = "serde", serde(borrow))] VarZeroVec<'data, str>),
560}
561
562icu_provider::data_struct!(
563    YearNames<'_>,
564    #[cfg(feature = "datagen")]
565);
566
567type YearNamesMap<'data> =
568    VarZeroCow<'data, Tuple2VarULE<VarZeroSlice<PotentialUtf8>, VarZeroSlice<str>>>;
569
570pub(crate) fn get_year_name_from_map<'a>(
571    map: &'a YearNamesMap<'_>,
572    year: &PotentialUtf8,
573) -> Option<&'a str> {
574    let idx = map.a().binary_search_by(|x| x.cmp(year)).ok()?;
575    map.b().get(idx)
576}
577
578size_test!(MonthNames, month_names_v1_size, 32);
579
580/// Names used for representing the month.
581///
582/// This uses a data marker attribute for length. See [`YearNames`] for more information on the scheme. This
583/// has an additional `1` value used for numeric names, only found for calendars with leap months.
584#[doc = month_names_v1_size!()]
585///
586/// <div class="stab unstable">
587/// 🚧 This code is considered unstable; it may change at any time, in breaking or non-breaking ways,
588/// including in SemVer minor releases. While the serde representation of data structs is guaranteed
589/// to be stable, their Rust representation might not be. Use with caution.
590/// </div>
591#[derive(Debug, PartialEq, Clone, yoke::Yokeable, zerofrom::ZeroFrom)]
592#[cfg_attr(feature = "datagen", derive(serde::Serialize, databake::Bake))]
593#[cfg_attr(feature = "datagen", databake(path = icu_datetime::provider::neo))]
594#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
595#[yoke(prove_covariance_manually)]
596pub enum MonthNames<'data> {
597    /// Month codes M01, M02, M03, .. (can allow for M13 onwards)
598    ///
599    /// Found for solar and pure lunar calendars
600    Linear(#[cfg_attr(feature = "serde", serde(borrow))] VarZeroVec<'data, str>),
601    /// Month codes M01, M02, M03, .. M01L, M02L, ...
602    ///
603    /// Empty entries for non-present month codes. Will have an equal number of leap and non-leap
604    /// entries.
605    ///
606    /// Found for lunisolar and lunisidereal calendars
607    LeapLinear(#[cfg_attr(feature = "serde", serde(borrow))] VarZeroVec<'data, str>),
608
609    /// This represents the formatting to apply to numeric values to produce the corresponding
610    /// leap month symbol.
611    ///
612    /// For numeric formatting only, on calendars with leap months
613    LeapNumeric(
614        #[cfg_attr(
615            feature = "serde",
616            serde(
617                borrow,
618                deserialize_with = "icu_pattern::deserialize_borrowed_cow::<icu_pattern::SinglePlaceholder, _>"
619            )
620        )]
621        Cow<'data, SinglePlaceholderPattern>,
622    ),
623}
624
625icu_provider::data_struct!(
626    MonthNames<'_>,
627    #[cfg(feature = "datagen")]
628);
629
630size_test!(LinearNames, linear_names_v1_size, 24);
631
632/// Names that can be stored as a simple linear array.
633///
634/// - For weekdays, element 0 is Sunday
635/// - For dayperiods, the elements are in order: AM, PM, (noon), (midnight), where the latter two are optional.
636///   In the case noon is missing but midnight is present, the noon value can be the empty string. This is unlikely.
637/// - For day names element 0 is the first day of the month
638///
639/// This uses a data marker attribute for length. See [`YearNames`] for more information on the scheme.
640#[doc = linear_names_v1_size!()]
641///
642/// <div class="stab unstable">
643/// 🚧 This code is considered unstable; it may change at any time, in breaking or non-breaking ways,
644/// including in SemVer minor releases. While the serde representation of data structs is guaranteed
645/// to be stable, their Rust representation might not be. Use with caution.
646/// </div>
647#[derive(Debug, PartialEq, Clone, yoke::Yokeable, zerofrom::ZeroFrom)]
648#[cfg_attr(feature = "datagen", derive(serde::Serialize, databake::Bake))]
649#[cfg_attr(feature = "datagen", databake(path = icu_datetime::provider::neo))]
650#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
651#[yoke(prove_covariance_manually)]
652pub struct LinearNames<'data> {
653    #[cfg_attr(feature = "serde", serde(borrow))]
654    /// The names, in order. Order specified on the struct docs.
655    // This uses a VarZeroVec rather than a fixed-size array for weekdays to save stack space
656    pub names: VarZeroVec<'data, str>,
657}
658
659icu_provider::data_struct!(
660    LinearNames<'_>,
661    #[cfg(feature = "datagen")]
662);
663
664impl LinearNames<'_> {
665    /// Gets the 'am' name assuming this struct contains day period data.
666    pub(crate) fn am(&self) -> Option<&str> {
667        self.names.get(0)
668    }
669    /// Gets the 'pm' name assuming this struct contains day period data.
670    pub(crate) fn pm(&self) -> Option<&str> {
671        self.names.get(1)
672    }
673    /// Gets the 'noon' name assuming this struct contains day period data.
674    pub(crate) fn noon(&self) -> Option<&str> {
675        self.names
676            .get(2)
677            .and_then(|s| if s.is_empty() { None } else { Some(s) })
678    }
679    /// Gets the 'midnight' name assuming this struct contains day period data.
680    pub(crate) fn midnight(&self) -> Option<&str> {
681        self.names.get(3)
682    }
683}
684
685// TODO: We may need to support plural forms here. Something like
686// pub enum NeoPatternPlurals<'data> {
687//     SingleDate(runtime::Pattern<'data>),
688//     WeekPlurals(ZeroMap<'data, PluralCategory, runtime::PatternULE>),
689// }
690
691size_test!(GluePattern, glue_pattern_v1_size, 24);
692
693/// The default per-length patterns used for combining dates, times, and timezones into formatted strings.
694#[doc = glue_pattern_v1_size!()]
695///
696/// <div class="stab unstable">
697/// 🚧 This code is considered unstable; it may change at any time, in breaking or non-breaking ways,
698/// including in SemVer minor releases. While the serde representation of data structs is guaranteed
699/// to be stable, their Rust representation might not be. Use with caution.
700/// </div>
701#[derive(Debug, PartialEq, Clone, yoke::Yokeable, zerofrom::ZeroFrom)]
702#[cfg_attr(feature = "datagen", derive(serde::Serialize, databake::Bake))]
703#[cfg_attr(feature = "datagen", databake(path = icu_datetime::provider::neo))]
704#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
705#[yoke(prove_covariance_manually)]
706pub struct GluePattern<'data> {
707    /// The pattern
708    #[cfg_attr(feature = "serde", serde(borrow))]
709    pub pattern: runtime::GenericPattern<'data>,
710}
711
712icu_provider::data_struct!(
713    GluePattern<'_>,
714    #[cfg(feature = "datagen")]
715);
716
717/// Calendar-agnostic year name data marker
718#[derive(Debug)]
719pub struct YearNamesV1;
720impl DynamicDataMarker for YearNamesV1 {
721    type DataStruct = YearNames<'static>;
722}
723
724/// Calendar-agnostic month name data marker
725#[derive(Debug)]
726pub struct MonthNamesV1;
727impl DynamicDataMarker for MonthNamesV1 {
728    type DataStruct = MonthNames<'static>;
729}
730
731/// Re-export of weekday names marker for more consistency
732pub use DatetimeNamesWeekdayV1 as WeekdayNamesV1;
733
734/// Re-export of day period names marker for more consistency
735pub use DatetimeNamesDayperiodV1 as DayPeriodNamesV1;