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