• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

zbraniecki / icu4x / 12020603084

23 Nov 2024 08:43PM UTC coverage: 75.71% (+0.2%) from 75.477%
12020603084

push

github

sffc
Touch Cargo.lock

55589 of 73424 relevant lines covered (75.71%)

644270.14 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

53.12
/components/datetime/src/pattern/names.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
use super::{
6
    DateTimePattern, DateTimePatternFormatter, GetNameForDayPeriodError, GetNameForMonthError,
7
    GetNameForWeekdayError, GetSymbolForCyclicYearError, GetSymbolForEraError,
8
    MonthPlaceholderValue, PatternLoadError,
9
};
10
use crate::fields::{self, FieldLength, FieldSymbol};
11
use crate::fieldsets::enums::CompositeDateTimeFieldSet;
12
use crate::input;
13
use crate::provider::neo::*;
14
use crate::provider::pattern::PatternItem;
15
use crate::provider::time_zones::tz;
16
use crate::scaffold::*;
17
use crate::size_test_macro::size_test;
18
use crate::{external_loaders::*, DateTimeFormatterPreferences};
19
use core::fmt;
20
use core::marker::PhantomData;
21
use core::num::NonZeroU8;
22
use icu_calendar::types::FormattingEra;
23
use icu_calendar::types::MonthCode;
24
use icu_decimal::options::FixedDecimalFormatterOptions;
25
use icu_decimal::options::GroupingStrategy;
26
use icu_decimal::provider::{DecimalDigitsV1Marker, DecimalSymbolsV2Marker};
27
use icu_decimal::FixedDecimalFormatter;
28
use icu_provider::prelude::*;
29

30
pub struct EmptyDataProvider;
31

32
impl<M> DataProvider<M> for EmptyDataProvider
33
where
34
    M: DataMarker,
35
{
36
    fn load(&self, base_req: DataRequest) -> Result<DataResponse<M>, DataError> {
37
        Err(DataErrorKind::MarkerNotFound.with_req(M::INFO, base_req))
38
    }
39
}
40

41
size_test!(
42
    TypedDateTimeNames<icu_calendar::Gregorian>,
43
    typed_date_time_names_size,
44
    328
45
);
46

47
/// A low-level type that formats datetime patterns with localized names.
48
/// The calendar should be chosen at compile time.
49
#[doc = typed_date_time_names_size!()]
50
///
51
/// Type parameters:
52
///
53
/// 1. The calendar chosen at compile time for additional type safety
54
/// 2. A components object type containing the fields that might be formatted
55
///
56
/// By default, the components object is set to [`CompositeDateTimeFieldSet`],
57
/// meaning that dates and times, but not time zones, are supported. A smaller
58
/// components object results in smaller stack size.
59
///
60
/// To support all fields including time zones, use [`CompositeFieldSet`].
61
///
62
/// [`CompositeFieldSet`]: crate::fieldsets::enums::CompositeFieldSet
63
/// [`CompositeDateTimeFieldSet`]: crate::fieldsets::enums::CompositeDateTimeFieldSet
64
///
65
/// # Examples
66
///
67
/// ```
68
/// use icu::calendar::Gregorian;
69
/// use icu::calendar::DateTime;
70
/// use icu::datetime::pattern::TypedDateTimeNames;
71
/// use icu::datetime::fields::FieldLength;
72
/// use icu::datetime::fields;
73
/// use icu::datetime::pattern::DateTimePattern;
74
/// use icu::locale::locale;
75
/// use writeable::assert_try_writeable_eq;
76
///
77
/// // Create an instance that can format abbreviated month, weekday, and day period names:
78
/// let mut names: TypedDateTimeNames<Gregorian> =
79
///     TypedDateTimeNames::try_new(locale!("uk").into()).unwrap();
80
/// names
81
///     .include_month_names(fields::Month::Format, FieldLength::Three)
82
///     .unwrap()
83
///     .include_weekday_names(fields::Weekday::Format, FieldLength::Three)
84
///     .unwrap()
85
///     .include_day_period_names(FieldLength::Three)
86
///     .unwrap();
87
///
88
/// // Create a pattern from a pattern string (note: K is the hour with h11 hour cycle):
89
/// let pattern_str = "E MMM d y -- K:mm a";
90
/// let pattern: DateTimePattern = pattern_str.parse().unwrap();
91
///
92
/// // Test it:
93
/// let datetime = DateTime::try_new_gregorian(2023, 11, 20, 12, 35, 3).unwrap();
94
/// assert_try_writeable_eq!(names.with_pattern_unchecked(&pattern).format(&datetime), "пн лист. 20 2023 -- 0:35 пп");
95
/// ```
96
///
97
/// If the correct data is not loaded, and error will occur:
98
///
99
/// ```
100
/// use icu::calendar::Gregorian;
101
/// use icu::calendar::{Date, Time};
102
/// use icu::datetime::DateTimeWriteError;
103
/// use icu::datetime::pattern::TypedDateTimeNames;
104
/// use icu::datetime::fields::{Field, FieldLength, FieldSymbol, Weekday};
105
/// use icu::datetime::pattern::{DateTimePattern, PatternLoadError};
106
/// use icu::datetime::fieldsets::enums::CompositeFieldSet;
107
/// use icu::locale::locale;
108
/// use icu::timezone::{TimeZoneInfo, IxdtfParser};
109
/// use icu_provider_adapters::empty::EmptyDataProvider;
110
/// use writeable::{Part, assert_try_writeable_parts_eq};
111
///
112
/// // Create an instance that can format all fields (CompositeFieldSet):
113
/// let mut names: TypedDateTimeNames<Gregorian, CompositeFieldSet> =
114
///     TypedDateTimeNames::try_new(locale!("en").into()).unwrap();
115
///
116
/// // Create a pattern from a pattern string:
117
/// let pattern_str = "'It is:' E MMM d y G 'at' h:mm:ssSSS a zzzz";
118
/// let pattern: DateTimePattern = pattern_str.parse().unwrap();
119
///
120
/// // The pattern string contains lots of symbols including "E", "MMM", and "a",
121
/// // but we did not load any data!
122
///
123
/// let mut dtz = IxdtfParser::new().try_from_str("2023-11-20T11:35:03+00:00[Europe/London]").unwrap().to_calendar(Gregorian);
124
///
125
/// // Missing data is filled in on a best-effort basis, and an error is signaled.
126
/// assert_try_writeable_parts_eq!(
127
///     names.with_pattern_unchecked(&pattern).format(&dtz),
128
///     "It is: mon M11 20 2023 CE at 11:35:03.000 AM +0000",
129
///     Err(DateTimeWriteError::NamesNotLoaded(Field { symbol: FieldSymbol::Weekday(Weekday::Format), length: FieldLength::One })),
130
///     [
131
///         (7, 10, Part::ERROR), // mon
132
///         (11, 14, Part::ERROR), // M11
133
///         (23, 25, Part::ERROR), // CE
134
///         (42, 44, Part::ERROR), // AM
135
///         (45, 50, Part::ERROR), // +0000
136
///     ]
137
/// );
138
///
139
/// // To make the error occur sooner, one can use an EmptyDataProvider:
140
/// let empty = EmptyDataProvider::new();
141
/// assert!(matches!(
142
///     names.load_for_pattern(&empty, &pattern),
143
///     Err(PatternLoadError::Data(_, Field { symbol: FieldSymbol::Weekday(_), .. })),
144
/// ));
145
/// ```
146
///
147
/// If the pattern contains fields inconsistent with the receiver, an error will occur:
148
///
149
/// ```
150
/// use icu::calendar::Gregorian;
151
/// use icu::calendar::DateTime;
152
/// use icu::datetime::DateTimeWriteError;
153
/// use icu::datetime::pattern::TypedDateTimeNames;
154
/// use icu::datetime::fields::{Field, FieldLength, FieldSymbol, Weekday};
155
/// use icu::datetime::pattern::DateTimePattern;
156
/// use icu::datetime::fieldsets::O;
157
/// use icu::locale::locale;
158
/// use icu::timezone::TimeZoneInfo;
159
/// use writeable::{Part, assert_try_writeable_parts_eq};
160
///
161
/// // Create an instance that can format abbreviated month, weekday, and day period names:
162
/// let mut names: TypedDateTimeNames<Gregorian, O> =
163
///     TypedDateTimeNames::try_new(locale!("en").into()).unwrap();
164
///
165
/// // Create a pattern from a pattern string:
166
/// let pattern_str = "'It is:' E MMM d y G 'at' h:mm:ssSSS a zzzz";
167
/// let pattern: DateTimePattern = pattern_str.parse().unwrap();
168
///
169
/// // The pattern string contains lots of symbols including "E", "MMM", and "a",
170
/// // but the `TypedDateTimeNames` is configured to format only time zones!
171
/// // Further, the time zone we provide doesn't contain any offset into!
172
/// // Missing data is filled in on a best-effort basis, and an error is signaled.
173
/// assert_try_writeable_parts_eq!(
174
///     names.with_pattern_unchecked(&pattern).format(&TimeZoneInfo::unknown()),
175
///     "It is: {E} {M} {d} {y} {G} at {h}:{m}:{s} {a} {z}",
176
///     Err(DateTimeWriteError::MissingInputField("iso_weekday")),
177
///     [
178
///         (7, 10, Part::ERROR), // {E}
179
///         (11, 14, Part::ERROR), // {M}
180
///         (15, 18, Part::ERROR), // {d}
181
///         (19, 22, Part::ERROR), // {y}
182
///         (23, 26, Part::ERROR), // {G}
183
///         (30, 33, Part::ERROR), // {h}
184
///         (34, 37, Part::ERROR), // {m}
185
///         (38, 41, Part::ERROR), // {s}
186
///         (42, 45, Part::ERROR), // {a}
187
///         (46, 49, Part::ERROR), // {z}
188
///     ]
189
/// );
190
/// ```
191
#[derive(Debug)]
192
pub struct TypedDateTimeNames<
193
    C: CldrCalendar,
194
    FSet: DateTimeNamesMarker = CompositeDateTimeFieldSet,
195
> {
196
    prefs: DateTimeFormatterPreferences,
197
    inner: RawDateTimeNames<FSet>,
198
    _calendar: PhantomData<C>,
199
}
200

201
pub(crate) struct RawDateTimeNames<FSet: DateTimeNamesMarker> {
202
    year_names:
203
        <FSet::YearNames as DateTimeNamesHolderTrait<YearNamesV1Marker>>::Container<FieldLength>,
204
    month_names: <FSet::MonthNames as DateTimeNamesHolderTrait<MonthNamesV1Marker>>::Container<(
205
        fields::Month,
206
        FieldLength,
207
    )>,
208
    weekday_names:
209
        <FSet::WeekdayNames as DateTimeNamesHolderTrait<WeekdayNamesV1Marker>>::Container<(
210
            fields::Weekday,
211
            FieldLength,
212
        )>,
213
    dayperiod_names:
214
        <FSet::DayPeriodNames as DateTimeNamesHolderTrait<DayPeriodNamesV1Marker>>::Container<
215
            FieldLength,
216
        >,
217
    zone_essentials:
218
        <FSet::ZoneEssentials as DateTimeNamesHolderTrait<tz::EssentialsV1Marker>>::Container<()>,
219
    locations_root:
220
        <FSet::ZoneLocations as DateTimeNamesHolderTrait<tz::LocationsV1Marker>>::Container<()>,
221
    locations:
222
        <FSet::ZoneLocations as DateTimeNamesHolderTrait<tz::LocationsV1Marker>>::Container<()>,
223
    mz_generic_long: <FSet::ZoneGenericLong as DateTimeNamesHolderTrait<
224
        tz::MzGenericLongV1Marker,
225
    >>::Container<()>,
226
    mz_generic_short: <FSet::ZoneGenericShort as DateTimeNamesHolderTrait<
227
        tz::MzGenericShortV1Marker,
228
    >>::Container<()>,
229
    mz_specific_long: <FSet::ZoneSpecificLong as DateTimeNamesHolderTrait<
230
        tz::MzSpecificLongV1Marker,
231
    >>::Container<()>,
232
    mz_specific_short: <FSet::ZoneSpecificShort as DateTimeNamesHolderTrait<
233
        tz::MzSpecificShortV1Marker,
234
    >>::Container<()>,
235
    mz_periods:
236
        <FSet::MetazoneLookup as DateTimeNamesHolderTrait<tz::MzPeriodV1Marker>>::Container<()>,
237
    // TODO(#4340): Make the FixedDecimalFormatter optional
238
    fixed_decimal_formatter: Option<FixedDecimalFormatter>,
239
    _marker: PhantomData<FSet>,
240
}
241

242
// Need a custom impl because not all of the associated types impl Debug
243
impl<FSet: DateTimeNamesMarker> fmt::Debug for RawDateTimeNames<FSet> {
244
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
245
        f.debug_struct("RawDateTimeNames")
246
            .field("year_names", &self.year_names)
247
            .field("month_names", &self.month_names)
248
            .field("weekday_names", &self.weekday_names)
249
            .field("dayperiod_names", &self.dayperiod_names)
250
            .field("zone_essentials", &self.zone_essentials)
251
            .field("locations", &self.locations)
252
            .field("mz_generic_long", &self.mz_generic_long)
253
            .field("mz_generic_short", &self.mz_generic_short)
254
            .field("mz_specific_long", &self.mz_specific_long)
255
            .field("mz_specific_short", &self.mz_specific_short)
256
            .field("fixed_decimal_formatter", &self.fixed_decimal_formatter)
257
            .finish()
258
    }
259
}
260

261
#[derive(Debug, Copy, Clone)]
×
262
pub(crate) struct RawDateTimeNamesBorrowed<'l> {
263
    year_names: OptionalNames<FieldLength, &'l YearNamesV1<'l>>,
264
    month_names: OptionalNames<(fields::Month, FieldLength), &'l MonthNamesV1<'l>>,
×
265
    weekday_names: OptionalNames<(fields::Weekday, FieldLength), &'l LinearNamesV1<'l>>,
×
266
    dayperiod_names: OptionalNames<FieldLength, &'l LinearNamesV1<'l>>,
×
267
    zone_essentials: OptionalNames<(), &'l tz::EssentialsV1<'l>>,
×
268
    locations_root: OptionalNames<(), &'l tz::LocationsV1<'l>>,
×
269
    locations: OptionalNames<(), &'l tz::LocationsV1<'l>>,
×
270
    mz_generic_long: OptionalNames<(), &'l tz::MzGenericV1<'l>>,
×
271
    mz_generic_short: OptionalNames<(), &'l tz::MzGenericV1<'l>>,
×
272
    mz_specific_long: OptionalNames<(), &'l tz::MzSpecificV1<'l>>,
×
273
    mz_specific_short: OptionalNames<(), &'l tz::MzSpecificV1<'l>>,
×
274
    mz_periods: OptionalNames<(), &'l tz::MzPeriodV1<'l>>,
×
275
    pub(crate) fixed_decimal_formatter: Option<&'l FixedDecimalFormatter>,
×
276
}
277

278
impl<C: CldrCalendar, FSet: DateTimeNamesMarker> TypedDateTimeNames<C, FSet> {
279
    /// Constructor that takes a selected locale and creates an empty instance.
280
    ///
281
    /// For an example, see [`TypedDateTimeNames`].
282
    ///
283
    /// ✨ *Enabled with the `compiled_data` Cargo feature.*
284
    ///
285
    /// [📚 Help choosing a constructor](icu_provider::constructors)
286
    #[cfg(feature = "compiled_data")]
287
    pub fn try_new(prefs: DateTimeFormatterPreferences) -> Result<Self, DataError> {
36✔
288
        let mut names = Self {
36✔
289
            prefs,
290
            inner: RawDateTimeNames::new_without_number_formatting(),
36✔
291
            _calendar: PhantomData,
292
        };
293
        names.include_fixed_decimal_formatter()?;
36✔
294
        Ok(names)
36✔
295
    }
36✔
296

297
    #[doc = icu_provider::gen_any_buffer_unstable_docs!(UNSTABLE, Self::try_new)]
298
    pub fn try_new_unstable<P>(
299
        provider: &P,
300
        prefs: DateTimeFormatterPreferences,
301
    ) -> Result<Self, DataError>
302
    where
303
        P: DataProvider<DecimalSymbolsV2Marker> + DataProvider<DecimalDigitsV1Marker> + ?Sized,
304
    {
305
        let mut names = Self {
306
            prefs,
307
            inner: RawDateTimeNames::new_without_number_formatting(),
308
            _calendar: PhantomData,
309
        };
310
        names.load_fixed_decimal_formatter(provider)?;
311
        Ok(names)
312
    }
313

314
    /// Creates a completely empty instance, not even with number formatting.
315
    ///
316
    /// # Examples
317
    ///
318
    /// Errors occur if a number formatter is not loaded but one is required:
319
    ///
320
    /// ```
321
    /// use icu::calendar::Gregorian;
322
    /// use icu::calendar::Date;
323
    /// use icu::datetime::DateTimeWriteError;
324
    /// use icu::datetime::pattern::TypedDateTimeNames;
325
    /// use icu::datetime::fields::{Field, FieldLength, FieldSymbol, Weekday};
326
    /// use icu::datetime::pattern::DateTimePattern;
327
    /// use icu::datetime::fieldsets::enums::DateFieldSet;
328
    /// use icu::locale::locale;
329
    /// use writeable::{Part, assert_try_writeable_parts_eq};
330
    ///
331
    /// // Create an instance that can format only date fields:
332
    /// let names: TypedDateTimeNames<Gregorian, DateFieldSet> =
333
    ///     TypedDateTimeNames::new_without_number_formatting(locale!("en").into());
334
    ///
335
    /// // Create a pattern from a pattern string:
336
    /// let pattern_str = "'It is:' y-MM-dd";
337
    /// let pattern: DateTimePattern = pattern_str.parse().unwrap();
338
    ///
339
    /// // The pattern string contains lots of numeric symbols,
340
    /// // but we did not load any data!
341
    ///
342
    /// let date = Date::try_new_gregorian(2024, 7, 1).unwrap();
343
    ///
344
    /// // Missing data is filled in on a best-effort basis, and an error is signaled.
345
    /// // (note that the padding is ignored in this fallback mode)
346
    /// assert_try_writeable_parts_eq!(
347
    ///     names.with_pattern_unchecked(&pattern).format(&date),
348
    ///     "It is: 2024-07-01",
349
    ///     Err(DateTimeWriteError::FixedDecimalFormatterNotLoaded),
350
    ///     [
351
    ///         (7, 11, Part::ERROR), // 2024
352
    ///         (12, 14, Part::ERROR), // 07
353
    ///         (15, 17, Part::ERROR), // 01
354
    ///     ]
355
    /// );
356
    /// ```
357
    pub fn new_without_number_formatting(prefs: DateTimeFormatterPreferences) -> Self {
358
        Self {
359
            prefs,
360
            inner: RawDateTimeNames::new_without_number_formatting(),
361
            _calendar: PhantomData,
362
        }
363
    }
364

365
    /// Loads year (era or cycle) names for the specified length.
366
    ///
367
    /// Does not support multiple field symbols or lengths. See #4337
368
    pub fn load_year_names<P>(
6✔
369
        &mut self,
370
        provider: &P,
371
        field_length: FieldLength,
372
    ) -> Result<&mut Self, PatternLoadError>
373
    where
374
        P: DataProvider<C::YearNamesV1Marker> + ?Sized,
375
    {
376
        self.inner.load_year_names(
12✔
377
            &C::YearNamesV1Marker::bind(provider),
6✔
378
            self.prefs,
6✔
379
            field_length,
380
        )?;
×
381
        Ok(self)
6✔
382
    }
6✔
383

384
    /// Includes year (era or cycle) names for the specified length.
385
    ///
386
    /// Does not support multiple field symbols or lengths. See #4337
387
    ///
388
    /// # Examples
389
    ///
390
    /// ```
391
    /// use icu::calendar::Gregorian;
392
    /// use icu::datetime::fields::FieldLength;
393
    /// use icu::datetime::pattern::PatternLoadError;
394
    /// use icu::datetime::pattern::TypedDateTimeNames;
395
    /// use icu::locale::locale;
396
    ///
397
    /// let mut names =
398
    ///     TypedDateTimeNames::<Gregorian>::try_new(locale!("und").into())
399
    ///         .unwrap();
400
    ///
401
    /// // First length is successful:
402
    /// names.include_year_names(FieldLength::Four).unwrap();
403
    ///
404
    /// // Attempting to load the first length a second time will succeed:
405
    /// names.include_year_names(FieldLength::Four).unwrap();
406
    ///
407
    /// // But loading a new length fails:
408
    /// assert!(matches!(
409
    ///     names.include_year_names(FieldLength::Three),
410
    ///     Err(PatternLoadError::ConflictingField(_))
411
    /// ));
412
    /// ```
413
    #[cfg(feature = "compiled_data")]
414
    pub fn include_year_names(
415
        &mut self,
416
        field_length: FieldLength,
417
    ) -> Result<&mut Self, PatternLoadError>
418
    where
419
        crate::provider::Baked: icu_provider::DataProvider<<C as CldrCalendar>::YearNamesV1Marker>,
420
    {
421
        self.load_year_names(&crate::provider::Baked, field_length)
422
    }
423

424
    /// Loads month names for the specified symbol and length.
425
    ///
426
    /// Does not support multiple field symbols or lengths. See #4337
427
    pub fn load_month_names<P>(
7✔
428
        &mut self,
429
        provider: &P,
430
        field_symbol: fields::Month,
431
        field_length: FieldLength,
432
    ) -> Result<&mut Self, PatternLoadError>
433
    where
434
        P: DataProvider<C::MonthNamesV1Marker> + ?Sized,
435
    {
436
        self.inner.load_month_names(
14✔
437
            &C::MonthNamesV1Marker::bind(provider),
7✔
438
            self.prefs,
7✔
439
            field_symbol,
440
            field_length,
441
        )?;
×
442
        Ok(self)
7✔
443
    }
7✔
444

445
    /// Includes month names for the specified symbol and length.
446
    ///
447
    /// Does not support multiple field symbols or lengths. See #4337
448
    ///
449
    /// # Examples
450
    ///
451
    /// ```
452
    /// use icu::calendar::Gregorian;
453
    /// use icu::datetime::fields::FieldLength;
454
    /// use icu::datetime::pattern::PatternLoadError;
455
    /// use icu::datetime::pattern::TypedDateTimeNames;
456
    /// use icu::locale::locale;
457
    ///
458
    /// let mut names =
459
    ///     TypedDateTimeNames::<Gregorian>::try_new(locale!("und").into())
460
    ///         .unwrap();
461
    /// let field_symbol = icu::datetime::fields::Month::Format;
462
    /// let alt_field_symbol = icu::datetime::fields::Month::StandAlone;
463
    ///
464
    /// // First length is successful:
465
    /// names
466
    ///     .include_month_names(field_symbol, FieldLength::Four)
467
    ///     .unwrap();
468
    ///
469
    /// // Attempting to load the first length a second time will succeed:
470
    /// names
471
    ///     .include_month_names(field_symbol, FieldLength::Four)
472
    ///     .unwrap();
473
    ///
474
    /// // But loading a new symbol or length fails:
475
    /// assert!(matches!(
476
    ///     names.include_month_names(alt_field_symbol, FieldLength::Four),
477
    ///     Err(PatternLoadError::ConflictingField(_))
478
    /// ));
479
    /// assert!(matches!(
480
    ///     names.include_month_names(field_symbol, FieldLength::Three),
481
    ///     Err(PatternLoadError::ConflictingField(_))
482
    /// ));
483
    /// ```
484
    #[cfg(feature = "compiled_data")]
485
    pub fn include_month_names(
486
        &mut self,
487
        field_symbol: fields::Month,
488
        field_length: FieldLength,
489
    ) -> Result<&mut Self, PatternLoadError>
490
    where
491
        crate::provider::Baked: icu_provider::DataProvider<<C as CldrCalendar>::MonthNamesV1Marker>,
492
    {
493
        self.load_month_names(&crate::provider::Baked, field_symbol, field_length)
494
    }
495

496
    /// Loads day period names for the specified length.
497
    ///
498
    /// Does not support multiple field symbols or lengths. See #4337
499
    pub fn load_day_period_names<P>(
11✔
500
        &mut self,
501
        provider: &P,
502
        field_length: FieldLength,
503
    ) -> Result<&mut Self, PatternLoadError>
504
    where
505
        P: DataProvider<DayPeriodNamesV1Marker> + ?Sized,
506
    {
507
        let provider = DayPeriodNamesV1Marker::bind(provider);
11✔
508
        self.inner
22✔
509
            .load_day_period_names(&provider, self.prefs, field_length)?;
11✔
510
        Ok(self)
11✔
511
    }
11✔
512

513
    /// Includes day period names for the specified length.
514
    ///
515
    /// Does not support multiple field symbols or lengths. See #4337
516
    ///
517
    /// # Examples
518
    ///
519
    /// ```
520
    /// use icu::calendar::Gregorian;
521
    /// use icu::datetime::fields::FieldLength;
522
    /// use icu::datetime::pattern::PatternLoadError;
523
    /// use icu::datetime::pattern::TypedDateTimeNames;
524
    /// use icu::locale::locale;
525
    ///
526
    /// let mut names =
527
    ///     TypedDateTimeNames::<Gregorian>::try_new(locale!("und").into())
528
    ///         .unwrap();
529
    ///
530
    /// // First length is successful:
531
    /// names.include_day_period_names(FieldLength::Four).unwrap();
532
    ///
533
    /// // Attempting to load the first length a second time will succeed:
534
    /// names.include_day_period_names(FieldLength::Four).unwrap();
535
    ///
536
    /// // But loading a new length fails:
537
    /// assert!(matches!(
538
    ///     names.include_day_period_names(FieldLength::Three),
539
    ///     Err(PatternLoadError::ConflictingField(_))
540
    /// ));
541
    /// ```
542
    #[cfg(feature = "compiled_data")]
543
    pub fn include_day_period_names(
544
        &mut self,
545
        field_length: FieldLength,
546
    ) -> Result<&mut Self, PatternLoadError>
547
    where
548
        crate::provider::Baked: icu_provider::DataProvider<DayPeriodNamesV1Marker>,
549
    {
550
        self.load_day_period_names(&crate::provider::Baked, field_length)
551
    }
552

553
    /// Loads weekday names for the specified symbol and length.
554
    ///
555
    /// Does not support multiple field symbols or lengths. See #4337
556
    pub fn load_weekday_names<P>(
15✔
557
        &mut self,
558
        provider: &P,
559
        field_symbol: fields::Weekday,
560
        field_length: FieldLength,
561
    ) -> Result<&mut Self, PatternLoadError>
562
    where
563
        P: DataProvider<WeekdayNamesV1Marker> + ?Sized,
564
    {
565
        self.inner.load_weekday_names(
30✔
566
            &WeekdayNamesV1Marker::bind(provider),
15✔
567
            self.prefs,
15✔
568
            field_symbol,
569
            field_length,
570
        )?;
×
571
        Ok(self)
15✔
572
    }
15✔
573

574
    /// Includes weekday names for the specified symbol and length.
575
    ///
576
    /// Does not support multiple field symbols or lengths. See #4337
577
    ///
578
    /// # Examples
579
    ///
580
    /// ```
581
    /// use icu::calendar::Gregorian;
582
    /// use icu::datetime::fields::FieldLength;
583
    /// use icu::datetime::pattern::PatternLoadError;
584
    /// use icu::datetime::pattern::TypedDateTimeNames;
585
    /// use icu::locale::locale;
586
    ///
587
    /// let mut names =
588
    ///     TypedDateTimeNames::<Gregorian>::try_new(locale!("und").into())
589
    ///         .unwrap();
590
    /// let field_symbol = icu::datetime::fields::Weekday::Format;
591
    /// let alt_field_symbol = icu::datetime::fields::Weekday::StandAlone;
592
    ///
593
    /// // First length is successful:
594
    /// names
595
    ///     .include_weekday_names(field_symbol, FieldLength::Four)
596
    ///     .unwrap();
597
    ///
598
    /// // Attempting to load the first length a second time will succeed:
599
    /// names
600
    ///     .include_weekday_names(field_symbol, FieldLength::Four)
601
    ///     .unwrap();
602
    ///
603
    /// // But loading a new symbol or length fails:
604
    /// assert!(matches!(
605
    ///     names.include_weekday_names(alt_field_symbol, FieldLength::Four),
606
    ///     Err(PatternLoadError::ConflictingField(_))
607
    /// ));
608
    /// assert!(matches!(
609
    ///     names.include_weekday_names(field_symbol, FieldLength::Three),
610
    ///     Err(PatternLoadError::ConflictingField(_))
611
    /// ));
612
    /// ```
613
    #[cfg(feature = "compiled_data")]
614
    pub fn include_weekday_names(
615
        &mut self,
616
        field_symbol: fields::Weekday,
617
        field_length: FieldLength,
618
    ) -> Result<&mut Self, PatternLoadError>
619
    where
620
        crate::provider::Baked: icu_provider::DataProvider<WeekdayNamesV1Marker>,
621
    {
622
        self.load_weekday_names(&crate::provider::Baked, field_symbol, field_length)
623
    }
624

625
    /// Loads shared essential patterns for time zone formatting.
626
    pub fn load_time_zone_essentials<P>(
627
        &mut self,
628
        provider: &P,
629
    ) -> Result<&mut Self, PatternLoadError>
630
    where
631
        P: DataProvider<tz::EssentialsV1Marker> + ?Sized,
632
    {
633
        self.inner
634
            .load_time_zone_essentials(&tz::EssentialsV1Marker::bind(provider), self.prefs)?;
635
        Ok(self)
636
    }
637

638
    /// Includes shared essential patterns for time zone formatting.
639
    ///
640
    /// This data should always be loaded when performing time zone formatting.
641
    /// By itself, it allows localized offset formats.
642
    ///
643
    /// # Examples
644
    ///
645
    /// ```
646
    /// use icu::calendar::Gregorian;
647
    /// use icu::datetime::fieldsets::enums::ZoneFieldSet;
648
    /// use icu::datetime::pattern::DateTimePattern;
649
    /// use icu::datetime::pattern::TypedDateTimeNames;
650
    /// use icu::locale::locale;
651
    /// use icu::timezone::IxdtfParser;
652
    /// use writeable::assert_try_writeable_eq;
653
    ///
654
    /// let mut zone_london_winter = IxdtfParser::new()
655
    ///     .try_from_str("2024-01-01T00:00:00+00:00[Europe/London]")
656
    ///     .unwrap()
657
    ///     .zone;
658
    /// let mut zone_london_summer = IxdtfParser::new()
659
    ///     .try_from_str("2024-07-01T00:00:00+01:00[Europe/London]")
660
    ///     .unwrap()
661
    ///     .zone;
662
    ///
663
    /// let mut names = TypedDateTimeNames::<Gregorian, ZoneFieldSet>::try_new(
664
    ///     locale!("en-GB").into(),
665
    /// )
666
    /// .unwrap();
667
    ///
668
    /// names.include_time_zone_essentials().unwrap();
669
    ///
670
    /// // Create a pattern with symbol `OOOO`:
671
    /// let pattern_str = "'Your time zone is:' OOOO";
672
    /// let pattern: DateTimePattern = pattern_str.parse().unwrap();
673
    ///
674
    /// assert_try_writeable_eq!(
675
    ///     names
676
    ///         .with_pattern_unchecked(&pattern)
677
    ///         .format(&zone_london_winter),
678
    ///     "Your time zone is: GMT",
679
    /// );
680
    /// assert_try_writeable_eq!(
681
    ///     names
682
    ///         .with_pattern_unchecked(&pattern)
683
    ///         .format(&zone_london_summer),
684
    ///     "Your time zone is: GMT+01:00",
685
    /// );
686
    ///
687
    /// // Now try `V`:
688
    /// let pattern_str = "'Your time zone is:' V";
689
    /// let pattern: DateTimePattern = pattern_str.parse().unwrap();
690
    ///
691
    /// assert_try_writeable_eq!(
692
    ///     names
693
    ///         .with_pattern_unchecked(&pattern)
694
    ///         .format(&zone_london_winter),
695
    ///     "Your time zone is: gblon",
696
    /// );
697
    ///
698
    /// // Now try `Z`:
699
    /// let pattern_str = "'Your time zone is:' Z";
700
    /// let pattern: DateTimePattern = pattern_str.parse().unwrap();
701
    ///
702
    /// assert_try_writeable_eq!(
703
    ///     names
704
    ///         .with_pattern_unchecked(&pattern)
705
    ///         .format(&zone_london_winter),
706
    ///     "Your time zone is: +0000",
707
    /// );
708
    ///
709
    /// // Now try `ZZZZZ`:
710
    /// let pattern_str = "'Your time zone is:' ZZZZZ";
711
    /// let pattern: DateTimePattern = pattern_str.parse().unwrap();
712
    ///
713
    /// assert_try_writeable_eq!(
714
    ///     names
715
    ///         .with_pattern_unchecked(&pattern)
716
    ///         .format(&zone_london_winter),
717
    ///     "Your time zone is: Z",
718
    /// );
719
    /// assert_try_writeable_eq!(
720
    ///     names
721
    ///         .with_pattern_unchecked(&pattern)
722
    ///         .format(&zone_london_summer),
723
    ///     "Your time zone is: +01:00",
724
    /// );
725
    /// ```
726
    #[cfg(feature = "compiled_data")]
727
    pub fn include_time_zone_essentials(&mut self) -> Result<&mut Self, PatternLoadError>
728
    where
729
        crate::provider::Baked: icu_provider::DataProvider<tz::EssentialsV1Marker>,
730
    {
731
        self.load_time_zone_essentials(&crate::provider::Baked)
732
    }
733

734
    /// Loads location names for time zone formatting.
735
    pub fn load_time_zone_location_names<P>(
736
        &mut self,
737
        provider: &P,
738
    ) -> Result<&mut Self, PatternLoadError>
739
    where
740
        P: DataProvider<tz::LocationsV1Marker> + ?Sized,
741
    {
742
        self.inner
743
            .load_time_zone_location_names(&tz::LocationsV1Marker::bind(provider), self.prefs)?;
744
        Ok(self)
745
    }
746

747
    /// Includes location names for time zone formatting.
748
    ///
749
    /// Important: When performing manual time zone data loading, in addition to the
750
    /// specific time zone format data, also call either:
751
    ///
752
    /// - [`TypedDateTimeNames::include_time_zone_essentials`]
753
    /// - [`TypedDateTimeNames::load_time_zone_essentials`]
754
    ///
755
    /// # Examples
756
    ///
757
    /// ```
758
    /// use icu::calendar::Gregorian;
759
    /// use icu::datetime::fieldsets::enums::ZoneFieldSet;
760
    /// use icu::datetime::pattern::DateTimePattern;
761
    /// use icu::datetime::pattern::TypedDateTimeNames;
762
    /// use icu::locale::locale;
763
    /// use icu::timezone::IxdtfParser;
764
    /// use writeable::assert_try_writeable_eq;
765
    ///
766
    /// let mut zone_london_winter = IxdtfParser::new()
767
    ///     .try_from_str("2024-01-01T00:00:00+00:00[Europe/London]")
768
    ///     .unwrap()
769
    ///     .zone;
770
    ///
771
    /// let mut names = TypedDateTimeNames::<Gregorian, ZoneFieldSet>::try_new(
772
    ///     locale!("en-GB").into(),
773
    /// )
774
    /// .unwrap();
775
    ///
776
    /// names.include_time_zone_essentials().unwrap();
777
    /// names.include_time_zone_location_names().unwrap();
778
    ///
779
    /// // Try `VVVV`:
780
    /// let pattern_str = "'Your time zone is:' VVVV";
781
    /// let pattern: DateTimePattern = pattern_str.parse().unwrap();
782
    ///
783
    /// assert_try_writeable_eq!(
784
    ///     names
785
    ///         .with_pattern_unchecked(&pattern)
786
    ///         .format(&zone_london_winter),
787
    ///     "Your time zone is: UK Time",
788
    /// );
789
    /// ```
790
    #[cfg(feature = "compiled_data")]
791
    pub fn include_time_zone_location_names(&mut self) -> Result<&mut Self, PatternLoadError>
792
    where
793
        crate::provider::Baked: icu_provider::DataProvider<tz::MzGenericShortV1Marker>,
794
    {
795
        self.load_time_zone_location_names(&crate::provider::Baked)
796
    }
797

798
    /// Loads generic non-location long time zone names.
799
    pub fn load_time_zone_generic_long_names<P>(
800
        &mut self,
801
        provider: &P,
802
    ) -> Result<&mut Self, PatternLoadError>
803
    where
804
        P: DataProvider<tz::MzGenericLongV1Marker> + DataProvider<tz::MzPeriodV1Marker> + ?Sized,
805
    {
806
        self.inner.load_time_zone_generic_long_names(
807
            &tz::MzGenericLongV1Marker::bind(provider),
808
            &tz::MzPeriodV1Marker::bind(provider),
809
            self.prefs,
810
        )?;
811
        Ok(self)
812
    }
813

814
    /// Includes generic non-location long time zone names.
815
    ///
816
    /// Important: When performing manual time zone data loading, in addition to the
817
    /// specific time zone format data, also call either:
818
    ///
819
    /// - [`TypedDateTimeNames::include_time_zone_essentials`]
820
    /// - [`TypedDateTimeNames::load_time_zone_essentials`]
821
    ///
822
    /// # Examples
823
    ///
824
    /// ```
825
    /// use icu::calendar::Gregorian;
826
    /// use icu::datetime::fieldsets::enums::ZoneFieldSet;
827
    /// use icu::datetime::pattern::DateTimePattern;
828
    /// use icu::datetime::pattern::TypedDateTimeNames;
829
    /// use icu::locale::locale;
830
    /// use icu::timezone::IxdtfParser;
831
    /// use writeable::assert_try_writeable_eq;
832
    ///
833
    /// let mut zone_london_winter = IxdtfParser::new()
834
    ///     .try_from_str("2024-01-01T00:00:00+00:00[Europe/London]")
835
    ///     .unwrap()
836
    ///     .zone;
837
    /// let mut zone_london_summer = IxdtfParser::new()
838
    ///     .try_from_str("2024-07-01T00:00:00+01:00[Europe/London]")
839
    ///     .unwrap()
840
    ///     .zone;
841
    ///
842
    /// let mut names = TypedDateTimeNames::<Gregorian, ZoneFieldSet>::try_new(
843
    ///     locale!("en-GB").into(),
844
    /// )
845
    /// .unwrap();
846
    ///
847
    /// names.include_time_zone_essentials().unwrap();
848
    /// names.include_time_zone_generic_long_names().unwrap();
849
    ///
850
    /// // Create a pattern with symbol `vvvv`:
851
    /// let pattern_str = "'Your time zone is:' vvvv";
852
    /// let pattern: DateTimePattern = pattern_str.parse().unwrap();
853
    ///
854
    /// assert_try_writeable_eq!(
855
    ///     names
856
    ///         .with_pattern_unchecked(&pattern)
857
    ///         .format(&zone_london_winter),
858
    ///     "Your time zone is: Greenwich Mean Time",
859
    /// );
860
    /// assert_try_writeable_eq!(
861
    ///     names
862
    ///         .with_pattern_unchecked(&pattern)
863
    ///         .format(&zone_london_summer),
864
    ///     "Your time zone is: Greenwich Mean Time", // TODO
865
    /// );
866
    /// ```
867
    #[cfg(feature = "compiled_data")]
868
    pub fn include_time_zone_generic_long_names(&mut self) -> Result<&mut Self, PatternLoadError>
869
    where
870
        crate::provider::Baked: icu_provider::DataProvider<tz::MzGenericLongV1Marker>,
871
    {
872
        self.load_time_zone_generic_long_names(&crate::provider::Baked)
873
    }
874

875
    /// Loads generic non-location short time zone names.
876
    pub fn load_time_zone_generic_short_names<P>(
877
        &mut self,
878
        provider: &P,
879
    ) -> Result<&mut Self, PatternLoadError>
880
    where
881
        P: DataProvider<tz::MzGenericShortV1Marker> + DataProvider<tz::MzPeriodV1Marker> + ?Sized,
882
    {
883
        self.inner.load_time_zone_generic_short_names(
884
            &tz::MzGenericShortV1Marker::bind(provider),
885
            &tz::MzPeriodV1Marker::bind(provider),
886
            self.prefs,
887
        )?;
888
        Ok(self)
889
    }
890

891
    /// Includes generic non-location short time zone names.
892
    ///
893
    /// Important: When performing manual time zone data loading, in addition to the
894
    /// specific time zone format data, also call either:
895
    ///
896
    /// - [`TypedDateTimeNames::include_time_zone_essentials`]
897
    /// - [`TypedDateTimeNames::load_time_zone_essentials`]
898
    ///
899
    /// # Examples
900
    ///
901
    /// ```
902
    /// use icu::calendar::Gregorian;
903
    /// use icu::datetime::fieldsets::enums::ZoneFieldSet;
904
    /// use icu::datetime::pattern::DateTimePattern;
905
    /// use icu::datetime::pattern::TypedDateTimeNames;
906
    /// use icu::locale::locale;
907
    /// use icu::timezone::IxdtfParser;
908
    /// use writeable::assert_try_writeable_eq;
909
    ///
910
    /// let mut zone_london_winter = IxdtfParser::new()
911
    ///     .try_from_str("2024-01-01T00:00:00+00:00[Europe/London]")
912
    ///     .unwrap()
913
    ///     .zone;
914
    /// let mut zone_london_summer = IxdtfParser::new()
915
    ///     .try_from_str("2024-07-01T00:00:00+01:00[Europe/London]")
916
    ///     .unwrap()
917
    ///     .zone;
918
    ///
919
    /// let mut names = TypedDateTimeNames::<Gregorian, ZoneFieldSet>::try_new(
920
    ///     locale!("en-GB").into(),
921
    /// )
922
    /// .unwrap();
923
    ///
924
    /// names.include_time_zone_essentials().unwrap();
925
    /// names.include_time_zone_generic_short_names().unwrap();
926
    ///
927
    /// // Create a pattern with symbol `v`:
928
    /// let pattern_str = "'Your time zone is:' v";
929
    /// let pattern: DateTimePattern = pattern_str.parse().unwrap();
930
    ///
931
    /// assert_try_writeable_eq!(
932
    ///     names
933
    ///         .with_pattern_unchecked(&pattern)
934
    ///         .format(&zone_london_winter),
935
    ///     "Your time zone is: GMT",
936
    /// );
937
    /// assert_try_writeable_eq!(
938
    ///     names
939
    ///         .with_pattern_unchecked(&pattern)
940
    ///         .format(&zone_london_summer),
941
    ///     "Your time zone is: GMT", // TODO
942
    /// );
943
    /// ```
944
    #[cfg(feature = "compiled_data")]
945
    pub fn include_time_zone_generic_short_names(&mut self) -> Result<&mut Self, PatternLoadError>
946
    where
947
        crate::provider::Baked: icu_provider::DataProvider<tz::MzGenericShortV1Marker>,
948
    {
949
        self.load_time_zone_generic_short_names(&crate::provider::Baked)
950
    }
951

952
    /// Loads specific non-location long time zone names.
953
    pub fn load_time_zone_specific_long_names<P>(
954
        &mut self,
955
        provider: &P,
956
    ) -> Result<&mut Self, PatternLoadError>
957
    where
958
        P: DataProvider<tz::MzSpecificLongV1Marker> + DataProvider<tz::MzPeriodV1Marker> + ?Sized,
959
    {
960
        self.inner.load_time_zone_specific_long_names(
961
            &tz::MzSpecificLongV1Marker::bind(provider),
962
            &tz::MzPeriodV1Marker::bind(provider),
963
            self.prefs,
964
        )?;
965
        Ok(self)
966
    }
967

968
    /// Includes specific non-location long time zone names.
969
    ///
970
    /// Important: When performing manual time zone data loading, in addition to the
971
    /// specific time zone format data, also call either:
972
    ///
973
    /// - [`TypedDateTimeNames::include_time_zone_essentials`]
974
    /// - [`TypedDateTimeNames::load_time_zone_essentials`]
975
    ///
976
    /// # Examples
977
    ///
978
    /// ```
979
    /// use icu::calendar::Gregorian;
980
    /// use icu::datetime::fieldsets::enums::ZoneFieldSet;
981
    /// use icu::datetime::pattern::DateTimePattern;
982
    /// use icu::datetime::pattern::TypedDateTimeNames;
983
    /// use icu::locale::locale;
984
    /// use icu::timezone::IxdtfParser;
985
    /// use writeable::assert_try_writeable_eq;
986
    ///
987
    /// let mut zone_london_winter = IxdtfParser::new()
988
    ///     .try_from_str("2024-01-01T00:00:00+00:00[Europe/London]")
989
    ///     .unwrap()
990
    ///     .zone;
991
    /// let mut zone_london_summer = IxdtfParser::new()
992
    ///     .try_from_str("2024-07-01T00:00:00+01:00[Europe/London]")
993
    ///     .unwrap()
994
    ///     .zone;
995
    ///
996
    /// let mut names = TypedDateTimeNames::<Gregorian, ZoneFieldSet>::try_new(
997
    ///     locale!("en-GB").into(),
998
    /// )
999
    /// .unwrap();
1000
    ///
1001
    /// names.include_time_zone_essentials().unwrap();
1002
    /// names.include_time_zone_specific_long_names().unwrap();
1003
    ///
1004
    /// // Create a pattern with symbol `zzzz`:
1005
    /// let pattern_str = "'Your time zone is:' zzzz";
1006
    /// let pattern: DateTimePattern = pattern_str.parse().unwrap();
1007
    ///
1008
    /// assert_try_writeable_eq!(
1009
    ///     names
1010
    ///         .with_pattern_unchecked(&pattern)
1011
    ///         .format(&zone_london_winter),
1012
    ///     "Your time zone is: Greenwich Mean Time",
1013
    /// );
1014
    /// assert_try_writeable_eq!(
1015
    ///     names
1016
    ///         .with_pattern_unchecked(&pattern)
1017
    ///         .format(&zone_london_summer),
1018
    ///     "Your time zone is: British Summer Time",
1019
    /// );
1020
    /// ```
1021
    #[cfg(feature = "compiled_data")]
1022
    pub fn include_time_zone_specific_long_names(&mut self) -> Result<&mut Self, PatternLoadError>
1023
    where
1024
        crate::provider::Baked: icu_provider::DataProvider<tz::MzSpecificLongV1Marker>,
1025
    {
1026
        self.load_time_zone_specific_long_names(&crate::provider::Baked)
1027
    }
1028

1029
    /// Loads specific non-location short time zone names.
1030
    pub fn load_time_zone_specific_short_names<P>(
1031
        &mut self,
1032
        provider: &P,
1033
    ) -> Result<&mut Self, PatternLoadError>
1034
    where
1035
        P: DataProvider<tz::MzSpecificShortV1Marker> + DataProvider<tz::MzPeriodV1Marker> + ?Sized,
1036
    {
1037
        self.inner.load_time_zone_specific_short_names(
1038
            &tz::MzSpecificShortV1Marker::bind(provider),
1039
            &tz::MzPeriodV1Marker::bind(provider),
1040
            self.prefs,
1041
        )?;
1042
        Ok(self)
1043
    }
1044

1045
    /// Includes specific non-location short time zone names.
1046
    ///
1047
    /// Important: When performing manual time zone data loading, in addition to the
1048
    /// specific time zone format data, also call either:
1049
    ///
1050
    /// - [`TypedDateTimeNames::include_time_zone_essentials`]
1051
    /// - [`TypedDateTimeNames::load_time_zone_essentials`]
1052
    ///
1053
    /// # Examples
1054
    ///
1055
    /// ```
1056
    /// use icu::calendar::Gregorian;
1057
    /// use icu::datetime::fieldsets::enums::ZoneFieldSet;
1058
    /// use icu::datetime::pattern::DateTimePattern;
1059
    /// use icu::datetime::pattern::TypedDateTimeNames;
1060
    /// use icu::locale::locale;
1061
    /// use icu::timezone::IxdtfParser;
1062
    /// use writeable::assert_try_writeable_eq;
1063
    ///
1064
    /// let mut zone_london_winter = IxdtfParser::new()
1065
    ///     .try_from_str("2024-01-01T00:00:00+00:00[Europe/London]")
1066
    ///     .unwrap()
1067
    ///     .zone;
1068
    /// let mut zone_london_summer = IxdtfParser::new()
1069
    ///     .try_from_str("2024-07-01T00:00:00+01:00[Europe/London]")
1070
    ///     .unwrap()
1071
    ///     .zone;
1072
    ///
1073
    /// let mut names = TypedDateTimeNames::<Gregorian, ZoneFieldSet>::try_new(
1074
    ///     locale!("en-GB").into(),
1075
    /// )
1076
    /// .unwrap();
1077
    ///
1078
    /// names.include_time_zone_essentials().unwrap();
1079
    /// names.include_time_zone_specific_short_names().unwrap();
1080
    ///
1081
    /// // Create a pattern with symbol `z`:
1082
    /// let pattern_str = "'Your time zone is:' z";
1083
    /// let pattern: DateTimePattern = pattern_str.parse().unwrap();
1084
    ///
1085
    /// assert_try_writeable_eq!(
1086
    ///     names
1087
    ///         .with_pattern_unchecked(&pattern)
1088
    ///         .format(&zone_london_winter),
1089
    ///     "Your time zone is: GMT",
1090
    /// );
1091
    /// assert_try_writeable_eq!(
1092
    ///     names
1093
    ///         .with_pattern_unchecked(&pattern)
1094
    ///         .format(&zone_london_summer),
1095
    ///     "Your time zone is: BST",
1096
    /// );
1097
    /// ```
1098
    #[cfg(feature = "compiled_data")]
1099
    pub fn include_time_zone_specific_short_names(&mut self) -> Result<&mut Self, PatternLoadError>
1100
    where
1101
        crate::provider::Baked: icu_provider::DataProvider<tz::MzSpecificShortV1Marker>,
1102
    {
1103
        self.load_time_zone_specific_short_names(&crate::provider::Baked)
1104
    }
1105

1106
    /// Loads a [`FixedDecimalFormatter`] from a data provider.
1107
    #[inline]
1108
    pub fn load_fixed_decimal_formatter<P>(&mut self, provider: &P) -> Result<&mut Self, DataError>
1109
    where
1110
        P: DataProvider<DecimalSymbolsV2Marker> + DataProvider<DecimalDigitsV1Marker> + ?Sized,
1111
    {
1112
        self.inner
1113
            .load_fixed_decimal_formatter(&ExternalLoaderUnstable(provider), self.prefs)?;
1114
        Ok(self)
1115
    }
1116

1117
    /// Loads a [`FixedDecimalFormatter`] with compiled data.
1118
    ///
1119
    /// # Examples
1120
    ///
1121
    /// ```
1122
    /// use icu::calendar::Time;
1123
    /// use icu::datetime::fieldsets::enums::TimeFieldSet;
1124
    /// use icu::datetime::pattern::DateTimePattern;
1125
    /// use icu::datetime::pattern::TypedDateTimeNames;
1126
    /// use icu::locale::locale;
1127
    /// use writeable::assert_try_writeable_eq;
1128
    ///
1129
    /// let mut names =
1130
    ///     TypedDateTimeNames::<(), TimeFieldSet>::try_new(locale!("bn").into())
1131
    ///         .unwrap();
1132
    /// names.include_fixed_decimal_formatter();
1133
    ///
1134
    /// // Create a pattern for the time, which is all numbers
1135
    /// let pattern_str = "'The current 24-hour time is:' HH:mm";
1136
    /// let pattern: DateTimePattern = pattern_str.parse().unwrap();
1137
    ///
1138
    /// let time = Time::try_new(6, 40, 33, 0).unwrap();
1139
    ///
1140
    /// assert_try_writeable_eq!(
1141
    ///     names.with_pattern_unchecked(&pattern).format(&time),
1142
    ///     "The current 24-hour time is: ০৬:৪০",
1143
    /// );
1144
    /// ```
1145
    #[cfg(feature = "compiled_data")]
1146
    #[inline]
1147
    pub fn include_fixed_decimal_formatter(&mut self) -> Result<&mut Self, DataError> {
36✔
1148
        self.inner
72✔
1149
            .load_fixed_decimal_formatter(&ExternalLoaderCompiledData, self.prefs)?;
36✔
1150
        Ok(self)
36✔
1151
    }
36✔
1152

1153
    /// Associates this [`TypedDateTimeNames`] with a pattern
1154
    /// without checking that all necessary data is loaded.
1155
    #[inline]
1156
    pub fn with_pattern_unchecked<'l>(
36✔
1157
        &'l self,
1158
        pattern: &'l DateTimePattern,
1159
    ) -> DateTimePatternFormatter<'l, C, FSet> {
1160
        DateTimePatternFormatter::new(pattern.as_borrowed(), self.inner.as_borrowed())
36✔
1161
    }
36✔
1162

1163
    /// Associates this [`TypedDateTimeNames`] with a datetime pattern
1164
    /// and loads all data required for that pattern.
1165
    ///
1166
    /// Does not duplicate textual field symbols. See #4337
1167
    pub fn load_for_pattern<'l, P>(
1168
        &'l mut self,
1169
        provider: &P,
1170
        pattern: &'l DateTimePattern,
1171
    ) -> Result<DateTimePatternFormatter<'l, C, FSet>, PatternLoadError>
1172
    where
1173
        P: DataProvider<C::YearNamesV1Marker>
1174
            + DataProvider<C::MonthNamesV1Marker>
1175
            + DataProvider<WeekdayNamesV1Marker>
1176
            + DataProvider<DayPeriodNamesV1Marker>
1177
            + DataProvider<tz::EssentialsV1Marker>
1178
            + DataProvider<tz::LocationsV1Marker>
1179
            + DataProvider<tz::MzGenericLongV1Marker>
1180
            + DataProvider<tz::MzGenericShortV1Marker>
1181
            + DataProvider<tz::MzSpecificLongV1Marker>
1182
            + DataProvider<tz::MzSpecificShortV1Marker>
1183
            + DataProvider<tz::MzPeriodV1Marker>
1184
            + DataProvider<DecimalSymbolsV2Marker>
1185
            + DataProvider<DecimalDigitsV1Marker>
1186
            + ?Sized,
1187
    {
1188
        let locale = self.prefs;
1189
        self.inner.load_for_pattern(
1190
            &C::YearNamesV1Marker::bind(provider),
1191
            &C::MonthNamesV1Marker::bind(provider),
1192
            &WeekdayNamesV1Marker::bind(provider),
1193
            &DayPeriodNamesV1Marker::bind(provider),
1194
            // TODO: Consider making time zone name loading optional here (lots of data)
1195
            &tz::EssentialsV1Marker::bind(provider),
1196
            &tz::LocationsV1Marker::bind(provider),
1197
            &tz::MzGenericLongV1Marker::bind(provider),
1198
            &tz::MzGenericShortV1Marker::bind(provider),
1199
            &tz::MzSpecificLongV1Marker::bind(provider),
1200
            &tz::MzSpecificShortV1Marker::bind(provider),
1201
            &tz::MzPeriodV1Marker::bind(provider),
1202
            &ExternalLoaderUnstable(provider),
1203
            locale,
1204
            pattern.iter_items(),
1205
        )?;
1206
        Ok(DateTimePatternFormatter::new(
1207
            pattern.as_borrowed(),
1208
            self.inner.as_borrowed(),
1209
        ))
1210
    }
1211

1212
    /// Associates this [`TypedDateTimeNames`] with a pattern
1213
    /// and includes all data required for that pattern.
1214
    ///
1215
    /// Does not support duplicate textual field symbols. See #4337
1216
    ///
1217
    /// # Examples
1218
    ///
1219
    /// ```
1220
    /// use icu::calendar::DateTime;
1221
    /// use icu::calendar::Gregorian;
1222
    /// use icu::datetime::pattern::DateTimePattern;
1223
    /// use icu::datetime::pattern::TypedDateTimeNames;
1224
    /// use icu::locale::locale;
1225
    /// use writeable::assert_try_writeable_eq;
1226
    ///
1227
    /// let mut names =
1228
    ///     TypedDateTimeNames::<Gregorian>::try_new(locale!("en").into()).unwrap();
1229
    ///
1230
    /// // Create a pattern from a pattern string:
1231
    /// let pattern_str = "MMM d (EEEE) 'of year' y G 'at' h:mm a";
1232
    /// let pattern: DateTimePattern = pattern_str.parse().unwrap();
1233
    ///
1234
    /// // Load data for the pattern and format:
1235
    /// let datetime =
1236
    ///     DateTime::try_new_gregorian(2023, 12, 5, 17, 43, 12).unwrap();
1237
    /// assert_try_writeable_eq!(
1238
    ///     names
1239
    ///         .include_for_pattern(&pattern)
1240
    ///         .unwrap()
1241
    ///         .format(&datetime),
1242
    ///     "Dec 5 (Tuesday) of year 2023 AD at 5:43 PM"
1243
    /// );
1244
    /// ```
1245
    #[cfg(feature = "compiled_data")]
1246
    pub fn include_for_pattern<'l>(
1247
        &'l mut self,
1248
        pattern: &'l DateTimePattern,
1249
    ) -> Result<DateTimePatternFormatter<'l, C, FSet>, PatternLoadError>
1250
    where
1251
        crate::provider::Baked: DataProvider<C::YearNamesV1Marker>
1252
            + DataProvider<C::MonthNamesV1Marker>
1253
            + DataProvider<WeekdayNamesV1Marker>
1254
            + DataProvider<DayPeriodNamesV1Marker>
1255
            + DataProvider<tz::EssentialsV1Marker>
1256
            + DataProvider<tz::MzGenericShortV1Marker>,
1257
    {
1258
        let locale = self.prefs;
1259
        self.inner.load_for_pattern(
1260
            &C::YearNamesV1Marker::bind(&crate::provider::Baked),
1261
            &C::MonthNamesV1Marker::bind(&crate::provider::Baked),
1262
            &WeekdayNamesV1Marker::bind(&crate::provider::Baked),
1263
            &DayPeriodNamesV1Marker::bind(&crate::provider::Baked),
1264
            &tz::EssentialsV1Marker::bind(&crate::provider::Baked),
1265
            &tz::LocationsV1Marker::bind(&crate::provider::Baked),
1266
            &tz::MzGenericLongV1Marker::bind(&crate::provider::Baked),
1267
            &tz::MzGenericShortV1Marker::bind(&crate::provider::Baked),
1268
            &tz::MzSpecificLongV1Marker::bind(&crate::provider::Baked),
1269
            &tz::MzSpecificShortV1Marker::bind(&crate::provider::Baked),
1270
            &tz::MzPeriodV1Marker::bind(&crate::provider::Baked),
1271
            &ExternalLoaderCompiledData,
1272
            locale,
1273
            pattern.iter_items(),
1274
        )?;
1275
        Ok(DateTimePatternFormatter::new(
1276
            pattern.as_borrowed(),
1277
            self.inner.as_borrowed(),
1278
        ))
1279
    }
1280
}
1281

1282
impl<FSet: DateTimeNamesMarker> RawDateTimeNames<FSet> {
1283
    pub(crate) fn new_without_number_formatting() -> Self {
36✔
1284
        Self {
36✔
1285
            year_names: <FSet::YearNames as DateTimeNamesHolderTrait<YearNamesV1Marker>>::Container::<_>::new_empty(),
36✔
1286
            month_names: <FSet::MonthNames as DateTimeNamesHolderTrait<MonthNamesV1Marker>>::Container::<_>::new_empty(),
36✔
1287
            weekday_names: <FSet::WeekdayNames as DateTimeNamesHolderTrait<WeekdayNamesV1Marker>>::Container::<_>::new_empty(),
36✔
1288
            dayperiod_names: <FSet::DayPeriodNames as DateTimeNamesHolderTrait<DayPeriodNamesV1Marker>>::Container::<_>::new_empty(),
36✔
1289
            zone_essentials: <FSet::ZoneEssentials as DateTimeNamesHolderTrait<tz::EssentialsV1Marker>>::Container::<_>::new_empty(),
36✔
1290
            locations_root: <FSet::ZoneLocations as DateTimeNamesHolderTrait<tz::LocationsV1Marker>>::Container::<_>::new_empty(),
36✔
1291
            locations: <FSet::ZoneLocations as DateTimeNamesHolderTrait<tz::LocationsV1Marker>>::Container::<_>::new_empty(),
36✔
1292
            mz_generic_long: <FSet::ZoneGenericLong as DateTimeNamesHolderTrait<tz::MzGenericLongV1Marker>>::Container::<_>::new_empty(),
36✔
1293
            mz_generic_short: <FSet::ZoneGenericShort as DateTimeNamesHolderTrait<tz::MzGenericShortV1Marker>>::Container::<_>::new_empty(),
36✔
1294
            mz_specific_long: <FSet::ZoneSpecificLong as DateTimeNamesHolderTrait<tz::MzSpecificLongV1Marker>>::Container::<_>::new_empty(),
36✔
1295
            mz_specific_short: <FSet::ZoneSpecificShort as DateTimeNamesHolderTrait<tz::MzSpecificShortV1Marker>>::Container::<_>::new_empty(),
36✔
1296
            mz_periods: <FSet::MetazoneLookup as DateTimeNamesHolderTrait<tz::MzPeriodV1Marker>>::Container::<_>::new_empty(),
36✔
1297
            fixed_decimal_formatter: None,
36✔
1298
            _marker: PhantomData,
1299
        }
×
1300
    }
36✔
1301

1302
    pub(crate) fn as_borrowed(&self) -> RawDateTimeNamesBorrowed {
36✔
1303
        RawDateTimeNamesBorrowed {
36✔
1304
            year_names: self.year_names.get().inner,
36✔
1305
            month_names: self.month_names.get().inner,
36✔
1306
            weekday_names: self.weekday_names.get().inner,
36✔
1307
            dayperiod_names: self.dayperiod_names.get().inner,
36✔
1308
            zone_essentials: self.zone_essentials.get().inner,
36✔
1309
            locations_root: self.locations_root.get().inner,
36✔
1310
            locations: self.locations.get().inner,
36✔
1311
            mz_generic_long: self.mz_generic_long.get().inner,
36✔
1312
            mz_generic_short: self.mz_generic_short.get().inner,
36✔
1313
            mz_specific_long: self.mz_specific_long.get().inner,
36✔
1314
            mz_specific_short: self.mz_specific_short.get().inner,
36✔
1315
            mz_periods: self.mz_periods.get().inner,
36✔
1316
            fixed_decimal_formatter: self.fixed_decimal_formatter.as_ref(),
36✔
1317
        }
1318
    }
36✔
1319

1320
    pub(crate) fn load_year_names<P>(
6✔
1321
        &mut self,
1322
        provider: &P,
1323
        prefs: DateTimeFormatterPreferences,
1324
        field_length: FieldLength,
1325
    ) -> Result<(), PatternLoadError>
1326
    where
1327
        P: BoundDataProvider<YearNamesV1Marker> + ?Sized,
1328
    {
1329
        let locale = provider.bound_marker().make_locale(prefs.locale_prefs);
6✔
1330
        let field = fields::Field {
6✔
1331
            symbol: FieldSymbol::Era,
6✔
1332
            length: field_length,
1333
        };
1334
        // UTS 35 says that "G..GGG" are all Abbreviated
1335
        let field_length = field_length.numeric_to_abbr();
6✔
1336
        let variables = field_length;
1337
        let req = DataRequest {
6✔
1338
            id: DataIdentifierBorrowed::for_marker_attributes_and_locale(
6✔
1339
                marker_attrs::name_attr_for(
6✔
1340
                    marker_attrs::Context::Format,
6✔
1341
                    match field_length {
6✔
1342
                        FieldLength::Three => marker_attrs::Length::Abbr,
3✔
1343
                        FieldLength::Five => marker_attrs::Length::Narrow,
2✔
1344
                        FieldLength::Four => marker_attrs::Length::Wide,
1✔
1345
                        _ => return Err(PatternLoadError::UnsupportedLength(field)),
×
1346
                    },
1347
                ),
1348
                &locale,
1349
            ),
1350
            ..Default::default()
6✔
1351
        };
1352
        self.year_names
12✔
1353
            .load_put(provider, req, variables)
1354
            .map_err(|e| MaybePayloadError::into_load_error(e, field))?
×
1355
            .map_err(|e| PatternLoadError::Data(e, field))?;
×
1356
        Ok(())
6✔
1357
    }
6✔
1358

1359
    pub(crate) fn load_month_names<P>(
7✔
1360
        &mut self,
1361
        provider: &P,
1362
        prefs: DateTimeFormatterPreferences,
1363
        field_symbol: fields::Month,
1364
        field_length: FieldLength,
1365
    ) -> Result<(), PatternLoadError>
1366
    where
1367
        P: BoundDataProvider<MonthNamesV1Marker> + ?Sized,
1368
    {
1369
        let locale = provider.bound_marker().make_locale(prefs.locale_prefs);
7✔
1370
        let field = fields::Field {
7✔
1371
            symbol: FieldSymbol::Month(field_symbol),
7✔
1372
            length: field_length,
1373
        };
1374
        let variables = (field_symbol, field_length);
7✔
1375
        let req = DataRequest {
7✔
1376
            id: DataIdentifierBorrowed::for_marker_attributes_and_locale(
7✔
1377
                marker_attrs::name_attr_for(
7✔
1378
                    match field_symbol {
7✔
1379
                        fields::Month::Format => marker_attrs::Context::Format,
4✔
1380
                        fields::Month::StandAlone => marker_attrs::Context::Standalone,
3✔
1381
                    },
1382
                    match field_length {
7✔
1383
                        FieldLength::Three => marker_attrs::Length::Abbr,
2✔
1384
                        FieldLength::Five => marker_attrs::Length::Narrow,
2✔
1385
                        FieldLength::Four => marker_attrs::Length::Wide,
3✔
1386
                        _ => return Err(PatternLoadError::UnsupportedLength(field)),
×
1387
                    },
1388
                ),
1389
                &locale,
1390
            ),
1391
            ..Default::default()
7✔
1392
        };
1393
        self.month_names
14✔
1394
            .load_put(provider, req, variables)
1395
            .map_err(|e| MaybePayloadError::into_load_error(e, field))?
×
1396
            .map_err(|e| PatternLoadError::Data(e, field))?;
×
1397
        Ok(())
7✔
1398
    }
7✔
1399

1400
    pub(crate) fn load_day_period_names<P>(
11✔
1401
        &mut self,
1402
        provider: &P,
1403
        prefs: DateTimeFormatterPreferences,
1404
        field_length: FieldLength,
1405
    ) -> Result<(), PatternLoadError>
1406
    where
1407
        P: BoundDataProvider<DayPeriodNamesV1Marker> + ?Sized,
1408
    {
1409
        let locale = provider.bound_marker().make_locale(prefs.locale_prefs);
11✔
1410
        let field = fields::Field {
11✔
1411
            // Names for 'a' and 'b' are stored in the same data marker
1412
            symbol: FieldSymbol::DayPeriod(fields::DayPeriod::NoonMidnight),
11✔
1413
            length: field_length,
1414
        };
1415
        // UTS 35 says that "a..aaa" are all Abbreviated
1416
        let field_length = field_length.numeric_to_abbr();
11✔
1417
        let variables = field_length;
1418
        let req = DataRequest {
11✔
1419
            id: DataIdentifierBorrowed::for_marker_attributes_and_locale(
11✔
1420
                marker_attrs::name_attr_for(
11✔
1421
                    marker_attrs::Context::Format,
11✔
1422
                    match field_length {
11✔
1423
                        FieldLength::Three => marker_attrs::Length::Abbr,
7✔
1424
                        FieldLength::Five => marker_attrs::Length::Narrow,
2✔
1425
                        FieldLength::Four => marker_attrs::Length::Wide,
2✔
1426
                        _ => return Err(PatternLoadError::UnsupportedLength(field)),
×
1427
                    },
1428
                ),
1429
                &locale,
1430
            ),
1431
            ..Default::default()
11✔
1432
        };
1433
        self.dayperiod_names
22✔
1434
            .load_put(provider, req, variables)
1435
            .map_err(|e| MaybePayloadError::into_load_error(e, field))?
×
1436
            .map_err(|e| PatternLoadError::Data(e, field))?;
×
1437
        Ok(())
11✔
1438
    }
11✔
1439

1440
    pub(crate) fn load_weekday_names<P>(
15✔
1441
        &mut self,
1442
        provider: &P,
1443
        prefs: DateTimeFormatterPreferences,
1444
        field_symbol: fields::Weekday,
1445
        field_length: FieldLength,
1446
    ) -> Result<(), PatternLoadError>
1447
    where
1448
        P: BoundDataProvider<WeekdayNamesV1Marker> + ?Sized,
1449
    {
1450
        let locale = provider.bound_marker().make_locale(prefs.locale_prefs);
15✔
1451
        let field = fields::Field {
15✔
1452
            symbol: FieldSymbol::Weekday(field_symbol),
15✔
1453
            length: field_length,
1454
        };
1455
        // UTS 35 says that "E..EEE" are all Abbreviated
1456
        // However, this doesn't apply to "e" and "c".
1457
        let field_length = if matches!(field_symbol, fields::Weekday::Format) {
15✔
1458
            field_length.numeric_to_abbr()
11✔
1459
        } else {
1460
            field_length
4✔
1461
        };
1462
        let variables = (field_symbol, field_length);
15✔
1463
        let req = DataRequest {
15✔
1464
            id: DataIdentifierBorrowed::for_marker_attributes_and_locale(
15✔
1465
                marker_attrs::name_attr_for(
15✔
1466
                    match field_symbol {
15✔
1467
                        // UTS 35 says that "e" and "E" have the same non-numeric names
1468
                        fields::Weekday::Format | fields::Weekday::Local => {
1469
                            marker_attrs::Context::Format
11✔
1470
                        }
1471
                        fields::Weekday::StandAlone => marker_attrs::Context::Standalone,
4✔
1472
                    },
1473
                    match field_length {
15✔
1474
                        FieldLength::Three => marker_attrs::Length::Abbr,
6✔
1475
                        FieldLength::Five => marker_attrs::Length::Narrow,
3✔
1476
                        FieldLength::Four => marker_attrs::Length::Wide,
3✔
1477
                        FieldLength::Six => marker_attrs::Length::Short,
3✔
1478
                        _ => return Err(PatternLoadError::UnsupportedLength(field)),
×
1479
                    },
1480
                ),
1481
                &locale,
1482
            ),
1483
            ..Default::default()
15✔
1484
        };
1485
        self.weekday_names
30✔
1486
            .load_put(provider, req, variables)
1487
            .map_err(|e| MaybePayloadError::into_load_error(e, field))?
×
1488
            .map_err(|e| PatternLoadError::Data(e, field))?;
×
1489
        Ok(())
15✔
1490
    }
15✔
1491

1492
    pub(crate) fn load_time_zone_essentials<P>(
×
1493
        &mut self,
1494
        provider: &P,
1495
        prefs: DateTimeFormatterPreferences,
1496
    ) -> Result<(), PatternLoadError>
1497
    where
1498
        P: BoundDataProvider<tz::EssentialsV1Marker> + ?Sized,
1499
    {
1500
        let locale = provider.bound_marker().make_locale(prefs.locale_prefs);
×
1501
        let field = fields::Field {
×
1502
            symbol: FieldSymbol::TimeZone(fields::TimeZone::LocalizedOffset),
×
1503
            length: FieldLength::Four,
×
1504
        };
1505
        let variables = ();
1506
        let req = DataRequest {
×
1507
            id: DataIdentifierBorrowed::for_locale(&locale),
×
1508
            ..Default::default()
×
1509
        };
1510
        self.zone_essentials
×
1511
            .load_put(provider, req, variables)
1512
            .map_err(|e| MaybePayloadError::into_load_error(e, field))?
×
1513
            .map_err(|e| PatternLoadError::Data(e, field))?;
×
1514
        Ok(())
×
1515
    }
×
1516

1517
    pub(crate) fn load_time_zone_location_names<P>(
×
1518
        &mut self,
1519
        provider: &P,
1520
        prefs: DateTimeFormatterPreferences,
1521
    ) -> Result<(), PatternLoadError>
1522
    where
1523
        P: BoundDataProvider<tz::LocationsV1Marker> + ?Sized,
1524
    {
1525
        let locale = provider.bound_marker().make_locale(prefs.locale_prefs);
×
1526
        let field = fields::Field {
×
1527
            symbol: FieldSymbol::TimeZone(fields::TimeZone::Location),
×
1528
            length: FieldLength::Four,
×
1529
        };
1530
        let variables = ();
1531
        let req = DataRequest {
×
1532
            id: DataIdentifierBorrowed::for_locale(&locale),
×
1533
            ..Default::default()
×
1534
        };
1535
        self.locations_root
×
1536
            .load_put(provider, Default::default(), variables)
×
1537
            .map_err(|e| MaybePayloadError::into_load_error(e, field))?
×
1538
            .map_err(|e| PatternLoadError::Data(e, field))?;
×
1539
        self.locations
×
1540
            .load_put(provider, req, variables)
1541
            .map_err(|e| MaybePayloadError::into_load_error(e, field))?
×
1542
            .map_err(|e| PatternLoadError::Data(e, field))?;
×
1543
        Ok(())
×
1544
    }
×
1545

1546
    fn load_mz_periods<P>(
×
1547
        &mut self,
1548
        provider: &P,
1549
        field: fields::Field,
1550
    ) -> Result<(), PatternLoadError>
1551
    where
1552
        P: BoundDataProvider<tz::MzPeriodV1Marker> + ?Sized,
1553
    {
1554
        let variables = ();
1555
        self.mz_periods
×
1556
            .load_put(provider, Default::default(), variables)
×
1557
            .map_err(|e| MaybePayloadError::into_load_error(e, field))?
×
1558
            .map_err(|e| PatternLoadError::Data(e, field))?;
×
1559
        Ok(())
×
1560
    }
×
1561

1562
    pub(crate) fn load_time_zone_generic_long_names(
×
1563
        &mut self,
1564
        provider: &(impl BoundDataProvider<tz::MzGenericLongV1Marker> + ?Sized),
1565
        mz_period_provider: &(impl BoundDataProvider<tz::MzPeriodV1Marker> + ?Sized),
1566
        prefs: DateTimeFormatterPreferences,
1567
    ) -> Result<(), PatternLoadError> {
1568
        let locale = provider.bound_marker().make_locale(prefs.locale_prefs);
×
1569
        let field = fields::Field {
×
1570
            symbol: FieldSymbol::TimeZone(fields::TimeZone::GenericNonLocation),
×
1571
            length: FieldLength::Four,
×
1572
        };
1573
        let variables = ();
1574
        let req = DataRequest {
×
1575
            id: DataIdentifierBorrowed::for_locale(&locale),
×
1576
            ..Default::default()
×
1577
        };
1578
        self.mz_generic_long
×
1579
            .load_put(provider, req, variables)
1580
            .map_err(|e| MaybePayloadError::into_load_error(e, field))?
×
1581
            .map_err(|e| PatternLoadError::Data(e, field))?;
×
1582
        self.load_mz_periods(mz_period_provider, field)?;
×
1583
        Ok(())
×
1584
    }
×
1585

1586
    pub(crate) fn load_time_zone_generic_short_names(
×
1587
        &mut self,
1588
        provider: &(impl BoundDataProvider<tz::MzGenericShortV1Marker> + ?Sized),
1589
        mz_period_provider: &(impl BoundDataProvider<tz::MzPeriodV1Marker> + ?Sized),
1590
        prefs: DateTimeFormatterPreferences,
1591
    ) -> Result<(), PatternLoadError> {
1592
        let locale = provider.bound_marker().make_locale(prefs.locale_prefs);
×
1593
        let field = fields::Field {
×
1594
            symbol: FieldSymbol::TimeZone(fields::TimeZone::GenericNonLocation),
×
1595
            length: FieldLength::One,
×
1596
        };
1597
        let variables = ();
1598
        let req = DataRequest {
×
1599
            id: DataIdentifierBorrowed::for_locale(&locale),
×
1600
            ..Default::default()
×
1601
        };
1602
        self.mz_generic_short
×
1603
            .load_put(provider, req, variables)
1604
            .map_err(|e| MaybePayloadError::into_load_error(e, field))?
×
1605
            .map_err(|e| PatternLoadError::Data(e, field))?;
×
1606
        self.load_mz_periods(mz_period_provider, field)?;
×
1607
        Ok(())
×
1608
    }
×
1609

1610
    pub(crate) fn load_time_zone_specific_long_names(
×
1611
        &mut self,
1612
        provider: &(impl BoundDataProvider<tz::MzSpecificLongV1Marker> + ?Sized),
1613
        mz_period_provider: &(impl BoundDataProvider<tz::MzPeriodV1Marker> + ?Sized),
1614
        prefs: DateTimeFormatterPreferences,
1615
    ) -> Result<(), PatternLoadError> {
1616
        let locale = provider.bound_marker().make_locale(prefs.locale_prefs);
×
1617
        let field = fields::Field {
×
1618
            symbol: FieldSymbol::TimeZone(fields::TimeZone::SpecificNonLocation),
×
1619
            length: FieldLength::Four,
×
1620
        };
1621
        let variables = ();
1622
        let req = DataRequest {
×
1623
            id: DataIdentifierBorrowed::for_locale(&locale),
×
1624
            ..Default::default()
×
1625
        };
1626
        self.mz_specific_long
×
1627
            .load_put(provider, req, variables)
1628
            .map_err(|e| MaybePayloadError::into_load_error(e, field))?
×
1629
            .map_err(|e| PatternLoadError::Data(e, field))?;
×
1630
        self.load_mz_periods(mz_period_provider, field)?;
×
1631
        Ok(())
×
1632
    }
×
1633

1634
    pub(crate) fn load_time_zone_specific_short_names(
×
1635
        &mut self,
1636
        provider: &(impl BoundDataProvider<tz::MzSpecificShortV1Marker> + ?Sized),
1637
        mz_period_provider: &(impl BoundDataProvider<tz::MzPeriodV1Marker> + ?Sized),
1638
        prefs: DateTimeFormatterPreferences,
1639
    ) -> Result<(), PatternLoadError> {
1640
        let locale = provider.bound_marker().make_locale(prefs.locale_prefs);
×
1641
        let field = fields::Field {
×
1642
            symbol: FieldSymbol::TimeZone(fields::TimeZone::SpecificNonLocation),
×
1643
            length: FieldLength::One,
×
1644
        };
1645
        let variables = ();
1646
        let req = DataRequest {
×
1647
            id: DataIdentifierBorrowed::for_locale(&locale),
×
1648
            ..Default::default()
×
1649
        };
1650
        self.mz_specific_short
×
1651
            .load_put(provider, req, variables)
1652
            .map_err(|e| MaybePayloadError::into_load_error(e, field))?
×
1653
            .map_err(|e| PatternLoadError::Data(e, field))?;
×
1654
        self.load_mz_periods(mz_period_provider, field)?;
×
1655
        Ok(())
×
1656
    }
×
1657

1658
    pub(crate) fn load_fixed_decimal_formatter(
36✔
1659
        &mut self,
1660
        loader: &impl FixedDecimalFormatterLoader,
1661
        prefs: DateTimeFormatterPreferences,
1662
    ) -> Result<(), DataError> {
1663
        if self.fixed_decimal_formatter.is_some() {
36✔
1664
            return Ok(());
×
1665
        }
1666
        let mut options = FixedDecimalFormatterOptions::default();
36✔
1667
        options.grouping_strategy = GroupingStrategy::Never;
36✔
1668
        self.fixed_decimal_formatter = Some(FixedDecimalFormatterLoader::load(
36✔
1669
            loader,
1670
            (&prefs).into(),
36✔
1671
            options,
36✔
1672
        )?);
×
1673
        Ok(())
36✔
1674
    }
36✔
1675

1676
    /// Loads all data required for formatting the given [`PatternItem`]s.
1677
    ///
1678
    /// This function has a lot of arguments because many of the arguments are generic,
1679
    /// and pulling them out to an options struct would be cumbersome.
1680
    #[allow(clippy::too_many_arguments)]
1681
    pub(crate) fn load_for_pattern(
×
1682
        &mut self,
1683
        year_provider: &(impl BoundDataProvider<YearNamesV1Marker> + ?Sized),
1684
        month_provider: &(impl BoundDataProvider<MonthNamesV1Marker> + ?Sized),
1685
        weekday_provider: &(impl BoundDataProvider<WeekdayNamesV1Marker> + ?Sized),
1686
        dayperiod_provider: &(impl BoundDataProvider<DayPeriodNamesV1Marker> + ?Sized),
1687
        zone_essentials_provider: &(impl BoundDataProvider<tz::EssentialsV1Marker> + ?Sized),
1688
        locations_provider: &(impl BoundDataProvider<tz::LocationsV1Marker> + ?Sized),
1689
        mz_generic_long_provider: &(impl BoundDataProvider<tz::MzGenericLongV1Marker> + ?Sized),
1690
        mz_generic_short_provider: &(impl BoundDataProvider<tz::MzGenericShortV1Marker> + ?Sized),
1691
        mz_specific_long_provider: &(impl BoundDataProvider<tz::MzSpecificLongV1Marker> + ?Sized),
1692
        mz_specific_short_provider: &(impl BoundDataProvider<tz::MzSpecificShortV1Marker> + ?Sized),
1693
        mz_period_provider: &(impl BoundDataProvider<tz::MzPeriodV1Marker> + ?Sized),
1694
        fixed_decimal_formatter_loader: &impl FixedDecimalFormatterLoader,
1695
        prefs: DateTimeFormatterPreferences,
1696
        pattern_items: impl Iterator<Item = PatternItem>,
1697
    ) -> Result<(), PatternLoadError> {
1698
        let mut numeric_field = None;
×
1699

1700
        for item in pattern_items {
×
1701
            let PatternItem::Field(field) = item else {
×
1702
                continue;
1703
            };
1704

1705
            use fields::*;
1706
            use FieldLength::*;
1707
            use FieldSymbol as FS;
1708

1709
            match (field.symbol, field.length) {
×
1710
                ///// Textual symbols /////
1711

1712
                // G..GGGGG
1713
                (FS::Era, One | Two | Three | Four | Five) => {
1714
                    self.load_year_names(year_provider, prefs, field.length)?;
×
1715
                }
1716

1717
                // U..UUUUU
1718
                (FS::Year(Year::Cyclic), One | Two | Three | Four | Five) => {
1719
                    numeric_field = Some(field);
×
1720
                    self.load_year_names(year_provider, prefs, field.length)?;
×
1721
                }
1722

1723
                // MMM..MMMMM
1724
                (FS::Month(Month::Format), Three | Four | Five) => {
1725
                    self.load_month_names(month_provider, prefs, Month::Format, field.length)?;
×
1726
                }
1727

1728
                // LLL..LLLLL
1729
                (FS::Month(Month::StandAlone), Three | Four | Five) => {
1730
                    self.load_month_names(month_provider, prefs, Month::StandAlone, field.length)?;
×
1731
                }
1732

1733
                // E..EE
1734
                (FS::Weekday(Weekday::Format), One | Two) => {
1735
                    self.load_weekday_names(
×
1736
                        weekday_provider,
1737
                        prefs,
1738
                        Weekday::Format,
×
1739
                        field.length,
×
1740
                    )?;
×
1741
                }
1742
                // EEE..EEEEEE, eee..eeeeee, ccc..cccccc
1743
                (FS::Weekday(symbol), Three | Four | Five | Six) => {
×
1744
                    self.load_weekday_names(weekday_provider, prefs, symbol, field.length)?;
×
1745
                }
1746

1747
                // a..aaaaa, b..bbbbb
1748
                (FS::DayPeriod(_), One | Two | Three | Four | Five) => {
1749
                    self.load_day_period_names(dayperiod_provider, prefs, field.length)?;
×
1750
                }
1751

1752
                ///// Time zone symbols /////
1753

1754
                // z..zzz
1755
                (FS::TimeZone(TimeZone::SpecificNonLocation), One | Two | Three) => {
1756
                    numeric_field = Some(field);
×
1757
                    self.load_time_zone_essentials(zone_essentials_provider, prefs)?;
×
1758
                    self.load_time_zone_specific_short_names(
×
1759
                        mz_specific_short_provider,
1760
                        mz_period_provider,
1761
                        prefs,
1762
                    )?;
×
1763
                }
1764
                // zzzz
1765
                (FS::TimeZone(TimeZone::SpecificNonLocation), Four) => {
1766
                    numeric_field = Some(field);
×
1767
                    self.load_time_zone_essentials(zone_essentials_provider, prefs)?;
×
1768
                    self.load_time_zone_specific_long_names(
×
1769
                        mz_specific_long_provider,
1770
                        mz_period_provider,
1771
                        prefs,
1772
                    )?;
×
1773
                    self.load_time_zone_location_names(locations_provider, prefs)?;
×
1774
                }
1775

1776
                // v
1777
                (FS::TimeZone(TimeZone::GenericNonLocation), One) => {
1778
                    numeric_field = Some(field);
×
1779
                    self.load_time_zone_essentials(zone_essentials_provider, prefs)?;
×
1780
                    self.load_time_zone_generic_short_names(
×
1781
                        mz_generic_short_provider,
1782
                        mz_period_provider,
1783
                        prefs,
1784
                    )?;
×
1785
                    // For fallback:
1786
                    self.load_time_zone_location_names(locations_provider, prefs)?;
×
1787
                }
1788
                // vvvv
1789
                (FS::TimeZone(TimeZone::GenericNonLocation), Four) => {
1790
                    numeric_field = Some(field);
×
1791
                    self.load_time_zone_essentials(zone_essentials_provider, prefs)?;
×
1792
                    self.load_time_zone_generic_long_names(
×
1793
                        mz_generic_long_provider,
1794
                        mz_period_provider,
1795
                        prefs,
1796
                    )?;
×
1797
                    // For fallback:
1798
                    self.load_time_zone_location_names(locations_provider, prefs)?;
×
1799
                }
1800

1801
                // V
1802
                (FS::TimeZone(TimeZone::Location), One) => {
1803
                    // no data required
1804
                }
1805
                // VVVV
1806
                (FS::TimeZone(TimeZone::Location), Four) => {
1807
                    numeric_field = Some(field);
×
1808
                    self.load_time_zone_essentials(zone_essentials_provider, prefs)?;
×
1809
                    self.load_time_zone_location_names(locations_provider, prefs)?;
×
1810
                }
1811

1812
                // O, OOOO
1813
                (FS::TimeZone(TimeZone::LocalizedOffset), One | Four) => {
×
1814
                    self.load_time_zone_essentials(zone_essentials_provider, prefs)?;
×
1815
                    numeric_field = Some(field);
×
1816
                }
1817

1818
                // X..XXXXX, x..xxxxx
1819
                (
1820
                    FS::TimeZone(TimeZone::IsoWithZ | TimeZone::Iso),
1821
                    One | Two | Three | Four | Five,
1822
                ) => {
1823
                    // no data required
1824
                }
1825

1826
                ///// Numeric symbols /////
1827

1828
                // y+
1829
                (FS::Year(Year::Calendar), _) => numeric_field = Some(field),
×
1830
                // r+
1831
                (FS::Year(Year::RelatedIso), _) => {
1832
                    // always formats as ASCII
1833
                }
1834

1835
                // M..MM, L..LL
1836
                (FS::Month(_), One | Two) => numeric_field = Some(field),
×
1837

1838
                // e..ee, c..cc
1839
                (FS::Weekday(Weekday::Local | Weekday::StandAlone), One | Two) => {
1840
                    // TODO(#5643): Requires locale-aware day-of-week calculation
1841
                    return Err(PatternLoadError::UnsupportedLength(field));
×
1842
                }
1843

1844
                // d..dd
1845
                (FS::Day(Day::DayOfMonth), One | Two) => numeric_field = Some(field),
×
1846
                // D..DDD
1847
                (FS::Day(Day::DayOfYear), One | Two | Three) => numeric_field = Some(field),
×
1848
                // F
1849
                (FS::Day(Day::DayOfWeekInMonth), One) => numeric_field = Some(field),
×
1850

1851
                // K..KK, h..hh, H..HH, k..kk
1852
                (FS::Hour(_), One | Two) => numeric_field = Some(field),
×
1853

1854
                // m..mm
1855
                (FS::Minute, One | Two) => numeric_field = Some(field),
×
1856

1857
                // s..ss
1858
                (FS::Second(Second::Second), One | Two) => numeric_field = Some(field),
×
1859

1860
                // A+
1861
                (FS::Second(Second::MillisInDay), _) => numeric_field = Some(field),
×
1862

1863
                // s.S+, ss.S+ (s is modelled by length, S+ by symbol)
1864
                (FS::DecimalSecond(_), One | Two) => numeric_field = Some(field),
×
1865

1866
                ///// Unsupported symbols /////
1867
                _ => {
1868
                    return Err(PatternLoadError::UnsupportedLength(field));
×
1869
                }
1870
            }
1871
        }
×
1872

1873
        if let Some(field) = numeric_field {
×
1874
            self.load_fixed_decimal_formatter(fixed_decimal_formatter_loader, prefs)
×
1875
                .map_err(|e| PatternLoadError::Data(e, field))?;
×
1876
        }
1877

1878
        Ok(())
×
1879
    }
×
1880
}
1881

1882
impl<'data> RawDateTimeNamesBorrowed<'data> {
1883
    pub(crate) fn get_name_for_month(
688✔
1884
        &self,
1885
        field_symbol: fields::Month,
1886
        field_length: FieldLength,
1887
        code: MonthCode,
1888
    ) -> Result<MonthPlaceholderValue, GetNameForMonthError> {
1889
        let month_names = self
1,376✔
1890
            .month_names
1891
            .get_with_variables((field_symbol, field_length))
1892
            .ok_or(GetNameForMonthError::NotLoaded)?;
688✔
1893
        let Some((month_number, is_leap)) = code.parsed() else {
686✔
1894
            return Err(GetNameForMonthError::Invalid);
×
1895
        };
1896
        let Some(month_index) = month_number.checked_sub(1) else {
686✔
1897
            return Err(GetNameForMonthError::Invalid);
×
1898
        };
1899
        let month_index = usize::from(month_index);
686✔
1900
        let name = match month_names {
686✔
1901
            MonthNamesV1::Linear(linear) => {
572✔
1902
                if is_leap {
572✔
1903
                    None
×
1904
                } else {
1905
                    linear.get(month_index)
572✔
1906
                }
1907
            }
1908
            MonthNamesV1::LeapLinear(leap_linear) => {
114✔
1909
                let num_months = leap_linear.len() / 2;
114✔
1910
                if is_leap {
114✔
1911
                    leap_linear.get(month_index + num_months)
39✔
1912
                } else if month_index < num_months {
75✔
1913
                    leap_linear.get(month_index)
75✔
1914
                } else {
1915
                    None
×
1916
                }
1917
            }
1918
            MonthNamesV1::LeapNumeric(leap_numeric) => {
×
1919
                if is_leap {
×
1920
                    return Ok(MonthPlaceholderValue::NumericPattern(leap_numeric));
×
1921
                } else {
1922
                    return Ok(MonthPlaceholderValue::Numeric);
×
1923
                }
1924
            }
1925
        };
1926
        // Note: Always return `false` for the second argument since neo MonthNames
1927
        // knows how to handle leap months and we don't need the fallback logic
1928
        name.map(MonthPlaceholderValue::PlainString)
1,372✔
1929
            .ok_or(GetNameForMonthError::Invalid)
686✔
1930
    }
688✔
1931

1932
    pub(crate) fn get_name_for_weekday(
576✔
1933
        &self,
1934
        field_symbol: fields::Weekday,
1935
        field_length: FieldLength,
1936
        day: input::IsoWeekday,
1937
    ) -> Result<&str, GetNameForWeekdayError> {
1938
        // UTS 35 says that "e" and "E" have the same non-numeric names
1939
        let field_symbol = field_symbol.to_format_symbol();
576✔
1940
        // UTS 35 says that "E..EEE" are all Abbreviated
1941
        // However, this doesn't apply to "e" and "c".
1942
        let field_length = if matches!(field_symbol, fields::Weekday::Format) {
576✔
1943
            field_length.numeric_to_abbr()
518✔
1944
        } else {
1945
            field_length
58✔
1946
        };
1947
        let weekday_names = self
1,152✔
1948
            .weekday_names
1949
            .get_with_variables((field_symbol, field_length))
576✔
1950
            .ok_or(GetNameForWeekdayError::NotLoaded)?;
576✔
1951
        weekday_names
1,148✔
1952
            .names
1953
            .get((day as usize) % 7)
574✔
1954
            // TODO: make weekday_names length 7 in the type system
1955
            .ok_or(GetNameForWeekdayError::NotLoaded)
1956
    }
576✔
1957

1958
    /// Gets the era symbol, or `None` if data is loaded but symbol isn't found.
1959
    ///
1960
    /// `None` should fall back to the era code directly, if, for example,
1961
    /// a japanext datetime is formatted with a `DateTimeFormat<Japanese>`
1962
    pub(crate) fn get_name_for_era(
458✔
1963
        &self,
1964
        field_length: FieldLength,
1965
        era: FormattingEra,
1966
    ) -> Result<&str, GetSymbolForEraError> {
1967
        // UTS 35 says that "G..GGG" are all Abbreviated
1968
        let field_length = field_length.numeric_to_abbr();
458✔
1969
        let year_names = self
916✔
1970
            .year_names
1971
            .get_with_variables(field_length)
1972
            .ok_or(GetSymbolForEraError::NotLoaded)?;
458✔
1973

1974
        match (year_names, era) {
456✔
1975
            (YearNamesV1::VariableEras(era_names), FormattingEra::Code(era_code)) => era_names
54✔
1976
                .get(era_code.0.as_str().into())
18✔
1977
                .ok_or(GetSymbolForEraError::Invalid),
18✔
1978
            (YearNamesV1::FixedEras(era_names), FormattingEra::Index(index, _fallback)) => {
438✔
1979
                era_names
1,314✔
1980
                    .get(index.into())
438✔
1981
                    .ok_or(GetSymbolForEraError::Invalid)
438✔
1982
            }
1983
            _ => Err(GetSymbolForEraError::Invalid),
×
1984
        }
1985
    }
458✔
1986

1987
    pub(crate) fn get_name_for_cyclic(
63✔
1988
        &self,
1989
        field_length: FieldLength,
1990
        cyclic: NonZeroU8,
1991
    ) -> Result<&str, GetSymbolForCyclicYearError> {
1992
        // UTS 35 says that "U..UUU" are all Abbreviated
1993
        let field_length = field_length.numeric_to_abbr();
63✔
1994
        let year_names = self
126✔
1995
            .year_names
1996
            .get_with_variables(field_length)
1997
            .ok_or(GetSymbolForCyclicYearError::NotLoaded)?;
63✔
1998

1999
        let YearNamesV1::Cyclic(cyclics) = year_names else {
63✔
2000
            return Err(GetSymbolForCyclicYearError::Invalid { max: 0 });
×
2001
        };
2002

2003
        cyclics
189✔
2004
            .get((cyclic.get() as usize) - 1)
63✔
2005
            .ok_or(GetSymbolForCyclicYearError::Invalid {
63✔
2006
                max: cyclics.len() + 1,
63✔
2007
            })
2008
    }
63✔
2009

2010
    pub(crate) fn get_name_for_day_period(
610✔
2011
        &self,
2012
        field_symbol: fields::DayPeriod,
2013
        field_length: FieldLength,
2014
        hour: input::IsoHour,
2015
        is_top_of_hour: bool,
2016
    ) -> Result<&str, GetNameForDayPeriodError> {
2017
        use fields::DayPeriod::NoonMidnight;
2018
        // UTS 35 says that "a..aaa" are all Abbreviated
2019
        let field_length = field_length.numeric_to_abbr();
610✔
2020
        let dayperiod_names = self
610✔
2021
            .dayperiod_names
2022
            .get_with_variables(field_length)
2023
            .ok_or(GetNameForDayPeriodError::NotLoaded)?;
610✔
2024
        let option_value: Option<&str> = match (field_symbol, u8::from(hour), is_top_of_hour) {
608✔
2025
            (NoonMidnight, 00, true) => dayperiod_names.midnight().or_else(|| dayperiod_names.am()),
64✔
2026
            (NoonMidnight, 12, true) => dayperiod_names.noon().or_else(|| dayperiod_names.pm()),
74✔
2027
            (_, hour, _) if hour < 12 => dayperiod_names.am(),
490✔
2028
            _ => dayperiod_names.pm(),
238✔
2029
        };
2030
        option_value.ok_or(GetNameForDayPeriodError::NotLoaded)
608✔
2031
    }
610✔
2032
}
2033

2034
/// A container contains all data payloads for time zone formatting (borrowed version).
2035
#[derive(Debug, Copy, Clone, Default)]
×
2036
pub(crate) struct TimeZoneDataPayloadsBorrowed<'a> {
2037
    /// The data that contains meta information about how to display content.
2038
    pub(crate) essentials: Option<&'a tz::EssentialsV1<'a>>,
×
2039
    /// The root location names, e.g. Toronto
2040
    pub(crate) locations_root: Option<&'a tz::LocationsV1<'a>>,
×
2041
    /// The language specific location names, e.g. Italy
2042
    pub(crate) locations: Option<&'a tz::LocationsV1<'a>>,
×
2043
    /// The generic long metazone names, e.g. Pacific Time
2044
    pub(crate) mz_generic_long: Option<&'a tz::MzGenericV1<'a>>,
×
2045
    /// The generic short metazone names, e.g. PT
2046
    pub(crate) mz_generic_short: Option<&'a tz::MzGenericV1<'a>>,
×
2047
    /// The specific long metazone names, e.g. Pacific Daylight Time
2048
    pub(crate) mz_specific_long: Option<&'a tz::MzSpecificV1<'a>>,
×
2049
    /// The specific short metazone names, e.g. Pacific Daylight Time
2050
    pub(crate) mz_specific_short: Option<&'a tz::MzSpecificV1<'a>>,
×
2051
    /// The metazone lookup
2052
    pub(crate) mz_periods: Option<&'a tz::MzPeriodV1<'a>>,
×
2053
}
2054

2055
impl<'data> RawDateTimeNamesBorrowed<'data> {
2056
    pub(crate) fn get_payloads(&self) -> TimeZoneDataPayloadsBorrowed<'data> {
716✔
2057
        TimeZoneDataPayloadsBorrowed {
716✔
2058
            essentials: self.zone_essentials.get_option(),
716✔
2059
            locations_root: self.locations_root.get_option(),
716✔
2060
            locations: self.locations.get_option(),
716✔
2061
            mz_generic_long: self.mz_generic_long.get_option(),
716✔
2062
            mz_generic_short: self.mz_generic_short.get_option(),
716✔
2063
            mz_specific_long: self.mz_specific_long.get_option(),
716✔
2064
            mz_specific_short: self.mz_specific_short.get_option(),
716✔
2065
            mz_periods: self.mz_periods.get_option(),
716✔
2066
        }
2067
    }
716✔
2068
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc