use super::{
DateTimePattern, DateTimePatternFormatter, GetNameForDayPeriodError, GetNameForMonthError,
GetNameForWeekdayError, GetSymbolForCyclicYearError, GetSymbolForEraError,
MonthPlaceholderValue, PatternLoadError,
};
use crate::fields::{self, FieldLength, FieldSymbol};
use crate::fieldsets::enums::CompositeDateTimeFieldSet;
use crate::input;
use crate::provider::neo::*;
use crate::provider::pattern::PatternItem;
use crate::provider::time_zones::tz;
use crate::scaffold::*;
use crate::size_test_macro::size_test;
use crate::{external_loaders::*, DateTimeFormatterPreferences};
use core::fmt;
use core::marker::PhantomData;
use core::num::NonZeroU8;
use icu_calendar::types::FormattingEra;
use icu_calendar::types::MonthCode;
use icu_decimal::options::FixedDecimalFormatterOptions;
use icu_decimal::options::GroupingStrategy;
use icu_decimal::provider::{DecimalDigitsV1Marker, DecimalSymbolsV2Marker};
use icu_decimal::FixedDecimalFormatter;
use icu_provider::prelude::*;
pub struct EmptyDataProvider;
impl<M> DataProvider<M> for EmptyDataProvider
where
M: DataMarker,
{
fn load(&self, base_req: DataRequest) -> Result<DataResponse<M>, DataError> {
Err(DataErrorKind::MarkerNotFound.with_req(M::INFO, base_req))
}
}
size_test!(
TypedDateTimeNames<icu_calendar::Gregorian>,
typed_date_time_names_size,
328
);
#[doc = typed_date_time_names_size!()]
#[derive(Debug)]
pub struct TypedDateTimeNames<
C: CldrCalendar,
FSet: DateTimeNamesMarker = CompositeDateTimeFieldSet,
> {
prefs: DateTimeFormatterPreferences,
inner: RawDateTimeNames<FSet>,
_calendar: PhantomData<C>,
}
pub(crate) struct RawDateTimeNames<FSet: DateTimeNamesMarker> {
year_names:
<FSet::YearNames as DateTimeNamesHolderTrait<YearNamesV1Marker>>::Container<FieldLength>,
month_names: <FSet::MonthNames as DateTimeNamesHolderTrait<MonthNamesV1Marker>>::Container<(
fields::Month,
FieldLength,
)>,
weekday_names:
<FSet::WeekdayNames as DateTimeNamesHolderTrait<WeekdayNamesV1Marker>>::Container<(
fields::Weekday,
FieldLength,
)>,
dayperiod_names:
<FSet::DayPeriodNames as DateTimeNamesHolderTrait<DayPeriodNamesV1Marker>>::Container<
FieldLength,
>,
zone_essentials:
<FSet::ZoneEssentials as DateTimeNamesHolderTrait<tz::EssentialsV1Marker>>::Container<()>,
locations_root:
<FSet::ZoneLocations as DateTimeNamesHolderTrait<tz::LocationsV1Marker>>::Container<()>,
locations:
<FSet::ZoneLocations as DateTimeNamesHolderTrait<tz::LocationsV1Marker>>::Container<()>,
mz_generic_long: <FSet::ZoneGenericLong as DateTimeNamesHolderTrait<
tz::MzGenericLongV1Marker,
>>::Container<()>,
mz_generic_short: <FSet::ZoneGenericShort as DateTimeNamesHolderTrait<
tz::MzGenericShortV1Marker,
>>::Container<()>,
mz_specific_long: <FSet::ZoneSpecificLong as DateTimeNamesHolderTrait<
tz::MzSpecificLongV1Marker,
>>::Container<()>,
mz_specific_short: <FSet::ZoneSpecificShort as DateTimeNamesHolderTrait<
tz::MzSpecificShortV1Marker,
>>::Container<()>,
mz_periods:
<FSet::MetazoneLookup as DateTimeNamesHolderTrait<tz::MzPeriodV1Marker>>::Container<()>,
fixed_decimal_formatter: Option<FixedDecimalFormatter>,
_marker: PhantomData<FSet>,
}
impl<FSet: DateTimeNamesMarker> fmt::Debug for RawDateTimeNames<FSet> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("RawDateTimeNames")
.field("year_names", &self.year_names)
.field("month_names", &self.month_names)
.field("weekday_names", &self.weekday_names)
.field("dayperiod_names", &self.dayperiod_names)
.field("zone_essentials", &self.zone_essentials)
.field("locations", &self.locations)
.field("mz_generic_long", &self.mz_generic_long)
.field("mz_generic_short", &self.mz_generic_short)
.field("mz_specific_long", &self.mz_specific_long)
.field("mz_specific_short", &self.mz_specific_short)
.field("fixed_decimal_formatter", &self.fixed_decimal_formatter)
.finish()
}
}
#[derive(Debug, Copy, Clone)]
pub(crate) struct RawDateTimeNamesBorrowed<'l> {
year_names: OptionalNames<FieldLength, &'l YearNamesV1<'l>>,
month_names: OptionalNames<(fields::Month, FieldLength), &'l MonthNamesV1<'l>>,
weekday_names: OptionalNames<(fields::Weekday, FieldLength), &'l LinearNamesV1<'l>>,
dayperiod_names: OptionalNames<FieldLength, &'l LinearNamesV1<'l>>,
zone_essentials: OptionalNames<(), &'l tz::EssentialsV1<'l>>,
locations_root: OptionalNames<(), &'l tz::LocationsV1<'l>>,
locations: OptionalNames<(), &'l tz::LocationsV1<'l>>,
mz_generic_long: OptionalNames<(), &'l tz::MzGenericV1<'l>>,
mz_generic_short: OptionalNames<(), &'l tz::MzGenericV1<'l>>,
mz_specific_long: OptionalNames<(), &'l tz::MzSpecificV1<'l>>,
mz_specific_short: OptionalNames<(), &'l tz::MzSpecificV1<'l>>,
mz_periods: OptionalNames<(), &'l tz::MzPeriodV1<'l>>,
pub(crate) fixed_decimal_formatter: Option<&'l FixedDecimalFormatter>,
}
impl<C: CldrCalendar, FSet: DateTimeNamesMarker> TypedDateTimeNames<C, FSet> {
#[cfg(feature = "compiled_data")]
pub fn try_new(prefs: DateTimeFormatterPreferences) -> Result<Self, DataError> {
let mut names = Self {
prefs,
inner: RawDateTimeNames::new_without_number_formatting(),
_calendar: PhantomData,
};
names.include_fixed_decimal_formatter()?;
Ok(names)
}
#[doc = icu_provider::gen_any_buffer_unstable_docs!(UNSTABLE, Self::try_new)]
pub fn try_new_unstable<P>(
provider: &P,
prefs: DateTimeFormatterPreferences,
) -> Result<Self, DataError>
where
P: DataProvider<DecimalSymbolsV2Marker> + DataProvider<DecimalDigitsV1Marker> + ?Sized,
{
let mut names = Self {
prefs,
inner: RawDateTimeNames::new_without_number_formatting(),
_calendar: PhantomData,
};
names.load_fixed_decimal_formatter(provider)?;
Ok(names)
}
pub fn new_without_number_formatting(prefs: DateTimeFormatterPreferences) -> Self {
Self {
prefs,
inner: RawDateTimeNames::new_without_number_formatting(),
_calendar: PhantomData,
}
}
pub fn load_year_names<P>(
&mut self,
provider: &P,
field_length: FieldLength,
) -> Result<&mut Self, PatternLoadError>
where
P: DataProvider<C::YearNamesV1Marker> + ?Sized,
{
self.inner.load_year_names(
&C::YearNamesV1Marker::bind(provider),
self.prefs,
field_length,
)?;
Ok(self)
}
#[cfg(feature = "compiled_data")]
pub fn include_year_names(
&mut self,
field_length: FieldLength,
) -> Result<&mut Self, PatternLoadError>
where
crate::provider::Baked: icu_provider::DataProvider<<C as CldrCalendar>::YearNamesV1Marker>,
{
self.load_year_names(&crate::provider::Baked, field_length)
}
pub fn load_month_names<P>(
&mut self,
provider: &P,
field_symbol: fields::Month,
field_length: FieldLength,
) -> Result<&mut Self, PatternLoadError>
where
P: DataProvider<C::MonthNamesV1Marker> + ?Sized,
{
self.inner.load_month_names(
&C::MonthNamesV1Marker::bind(provider),
self.prefs,
field_symbol,
field_length,
)?;
Ok(self)
}
#[cfg(feature = "compiled_data")]
pub fn include_month_names(
&mut self,
field_symbol: fields::Month,
field_length: FieldLength,
) -> Result<&mut Self, PatternLoadError>
where
crate::provider::Baked: icu_provider::DataProvider<<C as CldrCalendar>::MonthNamesV1Marker>,
{
self.load_month_names(&crate::provider::Baked, field_symbol, field_length)
}
pub fn load_day_period_names<P>(
&mut self,
provider: &P,
field_length: FieldLength,
) -> Result<&mut Self, PatternLoadError>
where
P: DataProvider<DayPeriodNamesV1Marker> + ?Sized,
{
let provider = DayPeriodNamesV1Marker::bind(provider);
self.inner
.load_day_period_names(&provider, self.prefs, field_length)?;
Ok(self)
}
#[cfg(feature = "compiled_data")]
pub fn include_day_period_names(
&mut self,
field_length: FieldLength,
) -> Result<&mut Self, PatternLoadError>
where
crate::provider::Baked: icu_provider::DataProvider<DayPeriodNamesV1Marker>,
{
self.load_day_period_names(&crate::provider::Baked, field_length)
}
pub fn load_weekday_names<P>(
&mut self,
provider: &P,
field_symbol: fields::Weekday,
field_length: FieldLength,
) -> Result<&mut Self, PatternLoadError>
where
P: DataProvider<WeekdayNamesV1Marker> + ?Sized,
{
self.inner.load_weekday_names(
&WeekdayNamesV1Marker::bind(provider),
self.prefs,
field_symbol,
field_length,
)?;
Ok(self)
}
#[cfg(feature = "compiled_data")]
pub fn include_weekday_names(
&mut self,
field_symbol: fields::Weekday,
field_length: FieldLength,
) -> Result<&mut Self, PatternLoadError>
where
crate::provider::Baked: icu_provider::DataProvider<WeekdayNamesV1Marker>,
{
self.load_weekday_names(&crate::provider::Baked, field_symbol, field_length)
}
pub fn load_time_zone_essentials<P>(
&mut self,
provider: &P,
) -> Result<&mut Self, PatternLoadError>
where
P: DataProvider<tz::EssentialsV1Marker> + ?Sized,
{
self.inner
.load_time_zone_essentials(&tz::EssentialsV1Marker::bind(provider), self.prefs)?;
Ok(self)
}
#[cfg(feature = "compiled_data")]
pub fn include_time_zone_essentials(&mut self) -> Result<&mut Self, PatternLoadError>
where
crate::provider::Baked: icu_provider::DataProvider<tz::EssentialsV1Marker>,
{
self.load_time_zone_essentials(&crate::provider::Baked)
}
pub fn load_time_zone_location_names<P>(
&mut self,
provider: &P,
) -> Result<&mut Self, PatternLoadError>
where
P: DataProvider<tz::LocationsV1Marker> + ?Sized,
{
self.inner
.load_time_zone_location_names(&tz::LocationsV1Marker::bind(provider), self.prefs)?;
Ok(self)
}
#[cfg(feature = "compiled_data")]
pub fn include_time_zone_location_names(&mut self) -> Result<&mut Self, PatternLoadError>
where
crate::provider::Baked: icu_provider::DataProvider<tz::MzGenericShortV1Marker>,
{
self.load_time_zone_location_names(&crate::provider::Baked)
}
pub fn load_time_zone_generic_long_names<P>(
&mut self,
provider: &P,
) -> Result<&mut Self, PatternLoadError>
where
P: DataProvider<tz::MzGenericLongV1Marker> + DataProvider<tz::MzPeriodV1Marker> + ?Sized,
{
self.inner.load_time_zone_generic_long_names(
&tz::MzGenericLongV1Marker::bind(provider),
&tz::MzPeriodV1Marker::bind(provider),
self.prefs,
)?;
Ok(self)
}
#[cfg(feature = "compiled_data")]
pub fn include_time_zone_generic_long_names(&mut self) -> Result<&mut Self, PatternLoadError>
where
crate::provider::Baked: icu_provider::DataProvider<tz::MzGenericLongV1Marker>,
{
self.load_time_zone_generic_long_names(&crate::provider::Baked)
}
pub fn load_time_zone_generic_short_names<P>(
&mut self,
provider: &P,
) -> Result<&mut Self, PatternLoadError>
where
P: DataProvider<tz::MzGenericShortV1Marker> + DataProvider<tz::MzPeriodV1Marker> + ?Sized,
{
self.inner.load_time_zone_generic_short_names(
&tz::MzGenericShortV1Marker::bind(provider),
&tz::MzPeriodV1Marker::bind(provider),
self.prefs,
)?;
Ok(self)
}
#[cfg(feature = "compiled_data")]
pub fn include_time_zone_generic_short_names(&mut self) -> Result<&mut Self, PatternLoadError>
where
crate::provider::Baked: icu_provider::DataProvider<tz::MzGenericShortV1Marker>,
{
self.load_time_zone_generic_short_names(&crate::provider::Baked)
}
pub fn load_time_zone_specific_long_names<P>(
&mut self,
provider: &P,
) -> Result<&mut Self, PatternLoadError>
where
P: DataProvider<tz::MzSpecificLongV1Marker> + DataProvider<tz::MzPeriodV1Marker> + ?Sized,
{
self.inner.load_time_zone_specific_long_names(
&tz::MzSpecificLongV1Marker::bind(provider),
&tz::MzPeriodV1Marker::bind(provider),
self.prefs,
)?;
Ok(self)
}
#[cfg(feature = "compiled_data")]
pub fn include_time_zone_specific_long_names(&mut self) -> Result<&mut Self, PatternLoadError>
where
crate::provider::Baked: icu_provider::DataProvider<tz::MzSpecificLongV1Marker>,
{
self.load_time_zone_specific_long_names(&crate::provider::Baked)
}
pub fn load_time_zone_specific_short_names<P>(
&mut self,
provider: &P,
) -> Result<&mut Self, PatternLoadError>
where
P: DataProvider<tz::MzSpecificShortV1Marker> + DataProvider<tz::MzPeriodV1Marker> + ?Sized,
{
self.inner.load_time_zone_specific_short_names(
&tz::MzSpecificShortV1Marker::bind(provider),
&tz::MzPeriodV1Marker::bind(provider),
self.prefs,
)?;
Ok(self)
}
#[cfg(feature = "compiled_data")]
pub fn include_time_zone_specific_short_names(&mut self) -> Result<&mut Self, PatternLoadError>
where
crate::provider::Baked: icu_provider::DataProvider<tz::MzSpecificShortV1Marker>,
{
self.load_time_zone_specific_short_names(&crate::provider::Baked)
}
#[inline]
pub fn load_fixed_decimal_formatter<P>(&mut self, provider: &P) -> Result<&mut Self, DataError>
where
P: DataProvider<DecimalSymbolsV2Marker> + DataProvider<DecimalDigitsV1Marker> + ?Sized,
{
self.inner
.load_fixed_decimal_formatter(&ExternalLoaderUnstable(provider), self.prefs)?;
Ok(self)
}
#[cfg(feature = "compiled_data")]
#[inline]
pub fn include_fixed_decimal_formatter(&mut self) -> Result<&mut Self, DataError> {
self.inner
.load_fixed_decimal_formatter(&ExternalLoaderCompiledData, self.prefs)?;
Ok(self)
}
#[inline]
pub fn with_pattern_unchecked<'l>(
&'l self,
pattern: &'l DateTimePattern,
) -> DateTimePatternFormatter<'l, C, FSet> {
DateTimePatternFormatter::new(pattern.as_borrowed(), self.inner.as_borrowed())
}
pub fn load_for_pattern<'l, P>(
&'l mut self,
provider: &P,
pattern: &'l DateTimePattern,
) -> Result<DateTimePatternFormatter<'l, C, FSet>, PatternLoadError>
where
P: DataProvider<C::YearNamesV1Marker>
+ DataProvider<C::MonthNamesV1Marker>
+ DataProvider<WeekdayNamesV1Marker>
+ DataProvider<DayPeriodNamesV1Marker>
+ DataProvider<tz::EssentialsV1Marker>
+ DataProvider<tz::LocationsV1Marker>
+ DataProvider<tz::MzGenericLongV1Marker>
+ DataProvider<tz::MzGenericShortV1Marker>
+ DataProvider<tz::MzSpecificLongV1Marker>
+ DataProvider<tz::MzSpecificShortV1Marker>
+ DataProvider<tz::MzPeriodV1Marker>
+ DataProvider<DecimalSymbolsV2Marker>
+ DataProvider<DecimalDigitsV1Marker>
+ ?Sized,
{
let locale = self.prefs;
self.inner.load_for_pattern(
&C::YearNamesV1Marker::bind(provider),
&C::MonthNamesV1Marker::bind(provider),
&WeekdayNamesV1Marker::bind(provider),
&DayPeriodNamesV1Marker::bind(provider),
&tz::EssentialsV1Marker::bind(provider),
&tz::LocationsV1Marker::bind(provider),
&tz::MzGenericLongV1Marker::bind(provider),
&tz::MzGenericShortV1Marker::bind(provider),
&tz::MzSpecificLongV1Marker::bind(provider),
&tz::MzSpecificShortV1Marker::bind(provider),
&tz::MzPeriodV1Marker::bind(provider),
&ExternalLoaderUnstable(provider),
locale,
pattern.iter_items(),
)?;
Ok(DateTimePatternFormatter::new(
pattern.as_borrowed(),
self.inner.as_borrowed(),
))
}
#[cfg(feature = "compiled_data")]
pub fn include_for_pattern<'l>(
&'l mut self,
pattern: &'l DateTimePattern,
) -> Result<DateTimePatternFormatter<'l, C, FSet>, PatternLoadError>
where
crate::provider::Baked: DataProvider<C::YearNamesV1Marker>
+ DataProvider<C::MonthNamesV1Marker>
+ DataProvider<WeekdayNamesV1Marker>
+ DataProvider<DayPeriodNamesV1Marker>
+ DataProvider<tz::EssentialsV1Marker>
+ DataProvider<tz::MzGenericShortV1Marker>,
{
let locale = self.prefs;
self.inner.load_for_pattern(
&C::YearNamesV1Marker::bind(&crate::provider::Baked),
&C::MonthNamesV1Marker::bind(&crate::provider::Baked),
&WeekdayNamesV1Marker::bind(&crate::provider::Baked),
&DayPeriodNamesV1Marker::bind(&crate::provider::Baked),
&tz::EssentialsV1Marker::bind(&crate::provider::Baked),
&tz::LocationsV1Marker::bind(&crate::provider::Baked),
&tz::MzGenericLongV1Marker::bind(&crate::provider::Baked),
&tz::MzGenericShortV1Marker::bind(&crate::provider::Baked),
&tz::MzSpecificLongV1Marker::bind(&crate::provider::Baked),
&tz::MzSpecificShortV1Marker::bind(&crate::provider::Baked),
&tz::MzPeriodV1Marker::bind(&crate::provider::Baked),
&ExternalLoaderCompiledData,
locale,
pattern.iter_items(),
)?;
Ok(DateTimePatternFormatter::new(
pattern.as_borrowed(),
self.inner.as_borrowed(),
))
}
}
impl<FSet: DateTimeNamesMarker> RawDateTimeNames<FSet> {
pub(crate) fn new_without_number_formatting() -> Self {
Self {
year_names: <FSet::YearNames as DateTimeNamesHolderTrait<YearNamesV1Marker>>::Container::<_>::new_empty(),
month_names: <FSet::MonthNames as DateTimeNamesHolderTrait<MonthNamesV1Marker>>::Container::<_>::new_empty(),
weekday_names: <FSet::WeekdayNames as DateTimeNamesHolderTrait<WeekdayNamesV1Marker>>::Container::<_>::new_empty(),
dayperiod_names: <FSet::DayPeriodNames as DateTimeNamesHolderTrait<DayPeriodNamesV1Marker>>::Container::<_>::new_empty(),
zone_essentials: <FSet::ZoneEssentials as DateTimeNamesHolderTrait<tz::EssentialsV1Marker>>::Container::<_>::new_empty(),
locations_root: <FSet::ZoneLocations as DateTimeNamesHolderTrait<tz::LocationsV1Marker>>::Container::<_>::new_empty(),
locations: <FSet::ZoneLocations as DateTimeNamesHolderTrait<tz::LocationsV1Marker>>::Container::<_>::new_empty(),
mz_generic_long: <FSet::ZoneGenericLong as DateTimeNamesHolderTrait<tz::MzGenericLongV1Marker>>::Container::<_>::new_empty(),
mz_generic_short: <FSet::ZoneGenericShort as DateTimeNamesHolderTrait<tz::MzGenericShortV1Marker>>::Container::<_>::new_empty(),
mz_specific_long: <FSet::ZoneSpecificLong as DateTimeNamesHolderTrait<tz::MzSpecificLongV1Marker>>::Container::<_>::new_empty(),
mz_specific_short: <FSet::ZoneSpecificShort as DateTimeNamesHolderTrait<tz::MzSpecificShortV1Marker>>::Container::<_>::new_empty(),
mz_periods: <FSet::MetazoneLookup as DateTimeNamesHolderTrait<tz::MzPeriodV1Marker>>::Container::<_>::new_empty(),
fixed_decimal_formatter: None,
_marker: PhantomData,
}
}
pub(crate) fn as_borrowed(&self) -> RawDateTimeNamesBorrowed {
RawDateTimeNamesBorrowed {
year_names: self.year_names.get().inner,
month_names: self.month_names.get().inner,
weekday_names: self.weekday_names.get().inner,
dayperiod_names: self.dayperiod_names.get().inner,
zone_essentials: self.zone_essentials.get().inner,
locations_root: self.locations_root.get().inner,
locations: self.locations.get().inner,
mz_generic_long: self.mz_generic_long.get().inner,
mz_generic_short: self.mz_generic_short.get().inner,
mz_specific_long: self.mz_specific_long.get().inner,
mz_specific_short: self.mz_specific_short.get().inner,
mz_periods: self.mz_periods.get().inner,
fixed_decimal_formatter: self.fixed_decimal_formatter.as_ref(),
}
}
pub(crate) fn load_year_names<P>(
&mut self,
provider: &P,
prefs: DateTimeFormatterPreferences,
field_length: FieldLength,
) -> Result<(), PatternLoadError>
where
P: BoundDataProvider<YearNamesV1Marker> + ?Sized,
{
let locale = provider.bound_marker().make_locale(prefs.locale_prefs);
let field = fields::Field {
symbol: FieldSymbol::Era,
length: field_length,
};
let field_length = field_length.numeric_to_abbr();
let variables = field_length;
let req = DataRequest {
id: DataIdentifierBorrowed::for_marker_attributes_and_locale(
marker_attrs::name_attr_for(
marker_attrs::Context::Format,
match field_length {
FieldLength::Three => marker_attrs::Length::Abbr,
FieldLength::Five => marker_attrs::Length::Narrow,
FieldLength::Four => marker_attrs::Length::Wide,
_ => return Err(PatternLoadError::UnsupportedLength(field)),
},
),
&locale,
),
..Default::default()
};
self.year_names
.load_put(provider, req, variables)
.map_err(|e| MaybePayloadError::into_load_error(e, field))?
.map_err(|e| PatternLoadError::Data(e, field))?;
Ok(())
}
pub(crate) fn load_month_names<P>(
&mut self,
provider: &P,
prefs: DateTimeFormatterPreferences,
field_symbol: fields::Month,
field_length: FieldLength,
) -> Result<(), PatternLoadError>
where
P: BoundDataProvider<MonthNamesV1Marker> + ?Sized,
{
let locale = provider.bound_marker().make_locale(prefs.locale_prefs);
let field = fields::Field {
symbol: FieldSymbol::Month(field_symbol),
length: field_length,
};
let variables = (field_symbol, field_length);
let req = DataRequest {
id: DataIdentifierBorrowed::for_marker_attributes_and_locale(
marker_attrs::name_attr_for(
match field_symbol {
fields::Month::Format => marker_attrs::Context::Format,
fields::Month::StandAlone => marker_attrs::Context::Standalone,
},
match field_length {
FieldLength::Three => marker_attrs::Length::Abbr,
FieldLength::Five => marker_attrs::Length::Narrow,
FieldLength::Four => marker_attrs::Length::Wide,
_ => return Err(PatternLoadError::UnsupportedLength(field)),
},
),
&locale,
),
..Default::default()
};
self.month_names
.load_put(provider, req, variables)
.map_err(|e| MaybePayloadError::into_load_error(e, field))?
.map_err(|e| PatternLoadError::Data(e, field))?;
Ok(())
}
pub(crate) fn load_day_period_names<P>(
&mut self,
provider: &P,
prefs: DateTimeFormatterPreferences,
field_length: FieldLength,
) -> Result<(), PatternLoadError>
where
P: BoundDataProvider<DayPeriodNamesV1Marker> + ?Sized,
{
let locale = provider.bound_marker().make_locale(prefs.locale_prefs);
let field = fields::Field {
symbol: FieldSymbol::DayPeriod(fields::DayPeriod::NoonMidnight),
length: field_length,
};
let field_length = field_length.numeric_to_abbr();
let variables = field_length;
let req = DataRequest {
id: DataIdentifierBorrowed::for_marker_attributes_and_locale(
marker_attrs::name_attr_for(
marker_attrs::Context::Format,
match field_length {
FieldLength::Three => marker_attrs::Length::Abbr,
FieldLength::Five => marker_attrs::Length::Narrow,
FieldLength::Four => marker_attrs::Length::Wide,
_ => return Err(PatternLoadError::UnsupportedLength(field)),
},
),
&locale,
),
..Default::default()
};
self.dayperiod_names
.load_put(provider, req, variables)
.map_err(|e| MaybePayloadError::into_load_error(e, field))?
.map_err(|e| PatternLoadError::Data(e, field))?;
Ok(())
}
pub(crate) fn load_weekday_names<P>(
&mut self,
provider: &P,
prefs: DateTimeFormatterPreferences,
field_symbol: fields::Weekday,
field_length: FieldLength,
) -> Result<(), PatternLoadError>
where
P: BoundDataProvider<WeekdayNamesV1Marker> + ?Sized,
{
let locale = provider.bound_marker().make_locale(prefs.locale_prefs);
let field = fields::Field {
symbol: FieldSymbol::Weekday(field_symbol),
length: field_length,
};
let field_length = if matches!(field_symbol, fields::Weekday::Format) {
field_length.numeric_to_abbr()
} else {
field_length
};
let variables = (field_symbol, field_length);
let req = DataRequest {
id: DataIdentifierBorrowed::for_marker_attributes_and_locale(
marker_attrs::name_attr_for(
match field_symbol {
fields::Weekday::Format | fields::Weekday::Local => {
marker_attrs::Context::Format
}
fields::Weekday::StandAlone => marker_attrs::Context::Standalone,
},
match field_length {
FieldLength::Three => marker_attrs::Length::Abbr,
FieldLength::Five => marker_attrs::Length::Narrow,
FieldLength::Four => marker_attrs::Length::Wide,
FieldLength::Six => marker_attrs::Length::Short,
_ => return Err(PatternLoadError::UnsupportedLength(field)),
},
),
&locale,
),
..Default::default()
};
self.weekday_names
.load_put(provider, req, variables)
.map_err(|e| MaybePayloadError::into_load_error(e, field))?
.map_err(|e| PatternLoadError::Data(e, field))?;
Ok(())
}
pub(crate) fn load_time_zone_essentials<P>(
&mut self,
provider: &P,
prefs: DateTimeFormatterPreferences,
) -> Result<(), PatternLoadError>
where
P: BoundDataProvider<tz::EssentialsV1Marker> + ?Sized,
{
let locale = provider.bound_marker().make_locale(prefs.locale_prefs);
let field = fields::Field {
symbol: FieldSymbol::TimeZone(fields::TimeZone::LocalizedOffset),
length: FieldLength::Four,
};
let variables = ();
let req = DataRequest {
id: DataIdentifierBorrowed::for_locale(&locale),
..Default::default()
};
self.zone_essentials
.load_put(provider, req, variables)
.map_err(|e| MaybePayloadError::into_load_error(e, field))?
.map_err(|e| PatternLoadError::Data(e, field))?;
Ok(())
}
pub(crate) fn load_time_zone_location_names<P>(
&mut self,
provider: &P,
prefs: DateTimeFormatterPreferences,
) -> Result<(), PatternLoadError>
where
P: BoundDataProvider<tz::LocationsV1Marker> + ?Sized,
{
let locale = provider.bound_marker().make_locale(prefs.locale_prefs);
let field = fields::Field {
symbol: FieldSymbol::TimeZone(fields::TimeZone::Location),
length: FieldLength::Four,
};
let variables = ();
let req = DataRequest {
id: DataIdentifierBorrowed::for_locale(&locale),
..Default::default()
};
self.locations_root
.load_put(provider, Default::default(), variables)
.map_err(|e| MaybePayloadError::into_load_error(e, field))?
.map_err(|e| PatternLoadError::Data(e, field))?;
self.locations
.load_put(provider, req, variables)
.map_err(|e| MaybePayloadError::into_load_error(e, field))?
.map_err(|e| PatternLoadError::Data(e, field))?;
Ok(())
}
fn load_mz_periods<P>(
&mut self,
provider: &P,
field: fields::Field,
) -> Result<(), PatternLoadError>
where
P: BoundDataProvider<tz::MzPeriodV1Marker> + ?Sized,
{
let variables = ();
self.mz_periods
.load_put(provider, Default::default(), variables)
.map_err(|e| MaybePayloadError::into_load_error(e, field))?
.map_err(|e| PatternLoadError::Data(e, field))?;
Ok(())
}
pub(crate) fn load_time_zone_generic_long_names(
&mut self,
provider: &(impl BoundDataProvider<tz::MzGenericLongV1Marker> + ?Sized),
mz_period_provider: &(impl BoundDataProvider<tz::MzPeriodV1Marker> + ?Sized),
prefs: DateTimeFormatterPreferences,
) -> Result<(), PatternLoadError> {
let locale = provider.bound_marker().make_locale(prefs.locale_prefs);
let field = fields::Field {
symbol: FieldSymbol::TimeZone(fields::TimeZone::GenericNonLocation),
length: FieldLength::Four,
};
let variables = ();
let req = DataRequest {
id: DataIdentifierBorrowed::for_locale(&locale),
..Default::default()
};
self.mz_generic_long
.load_put(provider, req, variables)
.map_err(|e| MaybePayloadError::into_load_error(e, field))?
.map_err(|e| PatternLoadError::Data(e, field))?;
self.load_mz_periods(mz_period_provider, field)?;
Ok(())
}
pub(crate) fn load_time_zone_generic_short_names(
&mut self,
provider: &(impl BoundDataProvider<tz::MzGenericShortV1Marker> + ?Sized),
mz_period_provider: &(impl BoundDataProvider<tz::MzPeriodV1Marker> + ?Sized),
prefs: DateTimeFormatterPreferences,
) -> Result<(), PatternLoadError> {
let locale = provider.bound_marker().make_locale(prefs.locale_prefs);
let field = fields::Field {
symbol: FieldSymbol::TimeZone(fields::TimeZone::GenericNonLocation),
length: FieldLength::One,
};
let variables = ();
let req = DataRequest {
id: DataIdentifierBorrowed::for_locale(&locale),
..Default::default()
};
self.mz_generic_short
.load_put(provider, req, variables)
.map_err(|e| MaybePayloadError::into_load_error(e, field))?
.map_err(|e| PatternLoadError::Data(e, field))?;
self.load_mz_periods(mz_period_provider, field)?;
Ok(())
}
pub(crate) fn load_time_zone_specific_long_names(
&mut self,
provider: &(impl BoundDataProvider<tz::MzSpecificLongV1Marker> + ?Sized),
mz_period_provider: &(impl BoundDataProvider<tz::MzPeriodV1Marker> + ?Sized),
prefs: DateTimeFormatterPreferences,
) -> Result<(), PatternLoadError> {
let locale = provider.bound_marker().make_locale(prefs.locale_prefs);
let field = fields::Field {
symbol: FieldSymbol::TimeZone(fields::TimeZone::SpecificNonLocation),
length: FieldLength::Four,
};
let variables = ();
let req = DataRequest {
id: DataIdentifierBorrowed::for_locale(&locale),
..Default::default()
};
self.mz_specific_long
.load_put(provider, req, variables)
.map_err(|e| MaybePayloadError::into_load_error(e, field))?
.map_err(|e| PatternLoadError::Data(e, field))?;
self.load_mz_periods(mz_period_provider, field)?;
Ok(())
}
pub(crate) fn load_time_zone_specific_short_names(
&mut self,
provider: &(impl BoundDataProvider<tz::MzSpecificShortV1Marker> + ?Sized),
mz_period_provider: &(impl BoundDataProvider<tz::MzPeriodV1Marker> + ?Sized),
prefs: DateTimeFormatterPreferences,
) -> Result<(), PatternLoadError> {
let locale = provider.bound_marker().make_locale(prefs.locale_prefs);
let field = fields::Field {
symbol: FieldSymbol::TimeZone(fields::TimeZone::SpecificNonLocation),
length: FieldLength::One,
};
let variables = ();
let req = DataRequest {
id: DataIdentifierBorrowed::for_locale(&locale),
..Default::default()
};
self.mz_specific_short
.load_put(provider, req, variables)
.map_err(|e| MaybePayloadError::into_load_error(e, field))?
.map_err(|e| PatternLoadError::Data(e, field))?;
self.load_mz_periods(mz_period_provider, field)?;
Ok(())
}
pub(crate) fn load_fixed_decimal_formatter(
&mut self,
loader: &impl FixedDecimalFormatterLoader,
prefs: DateTimeFormatterPreferences,
) -> Result<(), DataError> {
if self.fixed_decimal_formatter.is_some() {
return Ok(());
}
let mut options = FixedDecimalFormatterOptions::default();
options.grouping_strategy = GroupingStrategy::Never;
self.fixed_decimal_formatter = Some(FixedDecimalFormatterLoader::load(
loader,
(&prefs).into(),
options,
)?);
Ok(())
}
#[allow(clippy::too_many_arguments)]
pub(crate) fn load_for_pattern(
&mut self,
year_provider: &(impl BoundDataProvider<YearNamesV1Marker> + ?Sized),
month_provider: &(impl BoundDataProvider<MonthNamesV1Marker> + ?Sized),
weekday_provider: &(impl BoundDataProvider<WeekdayNamesV1Marker> + ?Sized),
dayperiod_provider: &(impl BoundDataProvider<DayPeriodNamesV1Marker> + ?Sized),
zone_essentials_provider: &(impl BoundDataProvider<tz::EssentialsV1Marker> + ?Sized),
locations_provider: &(impl BoundDataProvider<tz::LocationsV1Marker> + ?Sized),
mz_generic_long_provider: &(impl BoundDataProvider<tz::MzGenericLongV1Marker> + ?Sized),
mz_generic_short_provider: &(impl BoundDataProvider<tz::MzGenericShortV1Marker> + ?Sized),
mz_specific_long_provider: &(impl BoundDataProvider<tz::MzSpecificLongV1Marker> + ?Sized),
mz_specific_short_provider: &(impl BoundDataProvider<tz::MzSpecificShortV1Marker> + ?Sized),
mz_period_provider: &(impl BoundDataProvider<tz::MzPeriodV1Marker> + ?Sized),
fixed_decimal_formatter_loader: &impl FixedDecimalFormatterLoader,
prefs: DateTimeFormatterPreferences,
pattern_items: impl Iterator<Item = PatternItem>,
) -> Result<(), PatternLoadError> {
let mut numeric_field = None;
for item in pattern_items {
let PatternItem::Field(field) = item else {
continue;
};
use fields::*;
use FieldLength::*;
use FieldSymbol as FS;
match (field.symbol, field.length) {
(FS::Era, One | Two | Three | Four | Five) => {
self.load_year_names(year_provider, prefs, field.length)?;
}
(FS::Year(Year::Cyclic), One | Two | Three | Four | Five) => {
numeric_field = Some(field);
self.load_year_names(year_provider, prefs, field.length)?;
}
(FS::Month(Month::Format), Three | Four | Five) => {
self.load_month_names(month_provider, prefs, Month::Format, field.length)?;
}
(FS::Month(Month::StandAlone), Three | Four | Five) => {
self.load_month_names(month_provider, prefs, Month::StandAlone, field.length)?;
}
(FS::Weekday(Weekday::Format), One | Two) => {
self.load_weekday_names(
weekday_provider,
prefs,
Weekday::Format,
field.length,
)?;
}
(FS::Weekday(symbol), Three | Four | Five | Six) => {
self.load_weekday_names(weekday_provider, prefs, symbol, field.length)?;
}
(FS::DayPeriod(_), One | Two | Three | Four | Five) => {
self.load_day_period_names(dayperiod_provider, prefs, field.length)?;
}
(FS::TimeZone(TimeZone::SpecificNonLocation), One | Two | Three) => {
numeric_field = Some(field);
self.load_time_zone_essentials(zone_essentials_provider, prefs)?;
self.load_time_zone_specific_short_names(
mz_specific_short_provider,
mz_period_provider,
prefs,
)?;
}
(FS::TimeZone(TimeZone::SpecificNonLocation), Four) => {
numeric_field = Some(field);
self.load_time_zone_essentials(zone_essentials_provider, prefs)?;
self.load_time_zone_specific_long_names(
mz_specific_long_provider,
mz_period_provider,
prefs,
)?;
self.load_time_zone_location_names(locations_provider, prefs)?;
}
(FS::TimeZone(TimeZone::GenericNonLocation), One) => {
numeric_field = Some(field);
self.load_time_zone_essentials(zone_essentials_provider, prefs)?;
self.load_time_zone_generic_short_names(
mz_generic_short_provider,
mz_period_provider,
prefs,
)?;
self.load_time_zone_location_names(locations_provider, prefs)?;
}
(FS::TimeZone(TimeZone::GenericNonLocation), Four) => {
numeric_field = Some(field);
self.load_time_zone_essentials(zone_essentials_provider, prefs)?;
self.load_time_zone_generic_long_names(
mz_generic_long_provider,
mz_period_provider,
prefs,
)?;
self.load_time_zone_location_names(locations_provider, prefs)?;
}
(FS::TimeZone(TimeZone::Location), One) => {
}
(FS::TimeZone(TimeZone::Location), Four) => {
numeric_field = Some(field);
self.load_time_zone_essentials(zone_essentials_provider, prefs)?;
self.load_time_zone_location_names(locations_provider, prefs)?;
}
(FS::TimeZone(TimeZone::LocalizedOffset), One | Four) => {
self.load_time_zone_essentials(zone_essentials_provider, prefs)?;
numeric_field = Some(field);
}
(
FS::TimeZone(TimeZone::IsoWithZ | TimeZone::Iso),
One | Two | Three | Four | Five,
) => {
}
(FS::Year(Year::Calendar), _) => numeric_field = Some(field),
(FS::Year(Year::RelatedIso), _) => {
}
(FS::Month(_), One | Two) => numeric_field = Some(field),
(FS::Weekday(Weekday::Local | Weekday::StandAlone), One | Two) => {
return Err(PatternLoadError::UnsupportedLength(field));
}
(FS::Day(Day::DayOfMonth), One | Two) => numeric_field = Some(field),
(FS::Day(Day::DayOfYear), One | Two | Three) => numeric_field = Some(field),
(FS::Day(Day::DayOfWeekInMonth), One) => numeric_field = Some(field),
(FS::Hour(_), One | Two) => numeric_field = Some(field),
(FS::Minute, One | Two) => numeric_field = Some(field),
(FS::Second(Second::Second), One | Two) => numeric_field = Some(field),
(FS::Second(Second::MillisInDay), _) => numeric_field = Some(field),
(FS::DecimalSecond(_), One | Two) => numeric_field = Some(field),
_ => {
return Err(PatternLoadError::UnsupportedLength(field));
}
}
}
if let Some(field) = numeric_field {
self.load_fixed_decimal_formatter(fixed_decimal_formatter_loader, prefs)
.map_err(|e| PatternLoadError::Data(e, field))?;
}
Ok(())
}
}
impl<'data> RawDateTimeNamesBorrowed<'data> {
pub(crate) fn get_name_for_month(
&self,
field_symbol: fields::Month,
field_length: FieldLength,
code: MonthCode,
) -> Result<MonthPlaceholderValue, GetNameForMonthError> {
let month_names = self
.month_names
.get_with_variables((field_symbol, field_length))
.ok_or(GetNameForMonthError::NotLoaded)?;
let Some((month_number, is_leap)) = code.parsed() else {
return Err(GetNameForMonthError::Invalid);
};
let Some(month_index) = month_number.checked_sub(1) else {
return Err(GetNameForMonthError::Invalid);
};
let month_index = usize::from(month_index);
let name = match month_names {
MonthNamesV1::Linear(linear) => {
if is_leap {
None
} else {
linear.get(month_index)
}
}
MonthNamesV1::LeapLinear(leap_linear) => {
let num_months = leap_linear.len() / 2;
if is_leap {
leap_linear.get(month_index + num_months)
} else if month_index < num_months {
leap_linear.get(month_index)
} else {
None
}
}
MonthNamesV1::LeapNumeric(leap_numeric) => {
if is_leap {
return Ok(MonthPlaceholderValue::NumericPattern(leap_numeric));
} else {
return Ok(MonthPlaceholderValue::Numeric);
}
}
};
name.map(MonthPlaceholderValue::PlainString)
.ok_or(GetNameForMonthError::Invalid)
}
pub(crate) fn get_name_for_weekday(
&self,
field_symbol: fields::Weekday,
field_length: FieldLength,
day: input::IsoWeekday,
) -> Result<&str, GetNameForWeekdayError> {
let field_symbol = field_symbol.to_format_symbol();
let field_length = if matches!(field_symbol, fields::Weekday::Format) {
field_length.numeric_to_abbr()
} else {
field_length
};
let weekday_names = self
.weekday_names
.get_with_variables((field_symbol, field_length))
.ok_or(GetNameForWeekdayError::NotLoaded)?;
weekday_names
.names
.get((day as usize) % 7)
.ok_or(GetNameForWeekdayError::NotLoaded)
}
pub(crate) fn get_name_for_era(
&self,
field_length: FieldLength,
era: FormattingEra,
) -> Result<&str, GetSymbolForEraError> {
let field_length = field_length.numeric_to_abbr();
let year_names = self
.year_names
.get_with_variables(field_length)
.ok_or(GetSymbolForEraError::NotLoaded)?;
match (year_names, era) {
(YearNamesV1::VariableEras(era_names), FormattingEra::Code(era_code)) => era_names
.get(era_code.0.as_str().into())
.ok_or(GetSymbolForEraError::Invalid),
(YearNamesV1::FixedEras(era_names), FormattingEra::Index(index, _fallback)) => {
era_names
.get(index.into())
.ok_or(GetSymbolForEraError::Invalid)
}
_ => Err(GetSymbolForEraError::Invalid),
}
}
pub(crate) fn get_name_for_cyclic(
&self,
field_length: FieldLength,
cyclic: NonZeroU8,
) -> Result<&str, GetSymbolForCyclicYearError> {
let field_length = field_length.numeric_to_abbr();
let year_names = self
.year_names
.get_with_variables(field_length)
.ok_or(GetSymbolForCyclicYearError::NotLoaded)?;
let YearNamesV1::Cyclic(cyclics) = year_names else {
return Err(GetSymbolForCyclicYearError::Invalid { max: 0 });
};
cyclics
.get((cyclic.get() as usize) - 1)
.ok_or(GetSymbolForCyclicYearError::Invalid {
max: cyclics.len() + 1,
})
}
pub(crate) fn get_name_for_day_period(
&self,
field_symbol: fields::DayPeriod,
field_length: FieldLength,
hour: input::IsoHour,
is_top_of_hour: bool,
) -> Result<&str, GetNameForDayPeriodError> {
use fields::DayPeriod::NoonMidnight;
let field_length = field_length.numeric_to_abbr();
let dayperiod_names = self
.dayperiod_names
.get_with_variables(field_length)
.ok_or(GetNameForDayPeriodError::NotLoaded)?;
let option_value: Option<&str> = match (field_symbol, u8::from(hour), is_top_of_hour) {
(NoonMidnight, 00, true) => dayperiod_names.midnight().or_else(|| dayperiod_names.am()),
(NoonMidnight, 12, true) => dayperiod_names.noon().or_else(|| dayperiod_names.pm()),
(_, hour, _) if hour < 12 => dayperiod_names.am(),
_ => dayperiod_names.pm(),
};
option_value.ok_or(GetNameForDayPeriodError::NotLoaded)
}
}
#[derive(Debug, Copy, Clone, Default)]
pub(crate) struct TimeZoneDataPayloadsBorrowed<'a> {
pub(crate) essentials: Option<&'a tz::EssentialsV1<'a>>,
pub(crate) locations_root: Option<&'a tz::LocationsV1<'a>>,
pub(crate) locations: Option<&'a tz::LocationsV1<'a>>,
pub(crate) mz_generic_long: Option<&'a tz::MzGenericV1<'a>>,
pub(crate) mz_generic_short: Option<&'a tz::MzGenericV1<'a>>,
pub(crate) mz_specific_long: Option<&'a tz::MzSpecificV1<'a>>,
pub(crate) mz_specific_short: Option<&'a tz::MzSpecificV1<'a>>,
pub(crate) mz_periods: Option<&'a tz::MzPeriodV1<'a>>,
}
impl<'data> RawDateTimeNamesBorrowed<'data> {
pub(crate) fn get_payloads(&self) -> TimeZoneDataPayloadsBorrowed<'data> {
TimeZoneDataPayloadsBorrowed {
essentials: self.zone_essentials.get_option(),
locations_root: self.locations_root.get_option(),
locations: self.locations.get_option(),
mz_generic_long: self.mz_generic_long.get_option(),
mz_generic_short: self.mz_generic_short.get_option(),
mz_specific_long: self.mz_specific_long.get_option(),
mz_specific_short: self.mz_specific_short.get_option(),
mz_periods: self.mz_periods.get_option(),
}
}
}