diff --git a/components/datetime/src/format/datetime.rs b/components/datetime/src/format/datetime.rs index d71b1de30e3..e3072cc1c38 100644 --- a/components/datetime/src/format/datetime.rs +++ b/components/datetime/src/format/datetime.rs @@ -14,9 +14,10 @@ use crate::provider::calendar::patterns::PatternPluralsFromPatternsV1Marker; #[cfg(feature = "experimental")] use crate::provider::date_time::GetSymbolForDayPeriodError; use crate::provider::date_time::{ - DateSymbols, GetSymbolForEraError, GetSymbolForMonthError, GetSymbolForTimeZoneError, - GetSymbolForWeekdayError, MonthPlaceholderValue, TimeSymbols, ZoneSymbols, + DateSymbols, GetSymbolForEraError, GetSymbolForMonthError, GetSymbolForWeekdayError, + MonthPlaceholderValue, TimeSymbols, ZoneSymbols, }; +use crate::time_zone::{FormatTimeZone, FormatTimeZoneError, GenericNonLocationShortFormat}; use core::fmt::{self, Write}; use core::iter::Peekable; @@ -29,7 +30,7 @@ use icu_calendar::AnyCalendarKind; use icu_decimal::FixedDecimalFormatter; use icu_plurals::PluralRules; use icu_provider::DataPayload; -use icu_timezone::{CustomTimeZone, GmtOffset}; +use icu_timezone::CustomTimeZone; use writeable::{Part, Writeable}; /// [`FormattedDateTime`] is a intermediate structure which can be retrieved as @@ -207,7 +208,7 @@ where W: writeable::PartsWrite + ?Sized, DS: DateSymbols<'data>, TS: TimeSymbols, - ZS: ZoneSymbols, + ZS: ZoneSymbols<'data>, { try_write_pattern_items( pattern.metadata, @@ -238,7 +239,7 @@ where W: writeable::PartsWrite + ?Sized, DS: DateSymbols<'data>, TS: TimeSymbols, - ZS: ZoneSymbols, + ZS: ZoneSymbols<'data>, { let mut r = Ok(()); let mut iter = pattern_items.peekable(); @@ -778,7 +779,7 @@ where } // #[allow(clippy::too_many_arguments)] -pub(crate) fn try_write_zone( +pub(crate) fn try_write_zone<'data, W, ZS>( field_symbol: fields::TimeZone, field_length: FieldLength, datetime: &ExtractedDateTimeInput, @@ -788,7 +789,7 @@ pub(crate) fn try_write_zone( ) -> Result, fmt::Error> where W: writeable::PartsWrite + ?Sized, - ZS: ZoneSymbols, + ZS: ZoneSymbols<'data>, { fn write_time_zone_missing( w: &mut (impl writeable::PartsWrite + ?Sized), @@ -796,26 +797,6 @@ where w.with_part(Part::ERROR, |w| "{GMT+?}".write_to(w)) } - fn try_write_time_zone_gmt( - w: &mut (impl writeable::PartsWrite + ?Sized), - _gmt_offset: Option, - zone_symbols: Option<&impl ZoneSymbols>, - _graceful: bool, - ) -> Result, fmt::Error> { - #[allow(clippy::bind_instead_of_map)] // TODO: Use proper formatting logic here - Ok( - match zone_symbols - .ok_or(DateTimeWriteError::MissingZoneSymbols) - .and_then(|_zs| { - // TODO: Use proper formatting logic here - Ok("{todo}") - }) { - Err(e) => Err(e), - Ok(s) => Ok(s.write_to(w)?), - }, - ) - } - // for errors only: let field = Field { symbol: FieldSymbol::TimeZone(field_symbol), @@ -828,38 +809,33 @@ where write_time_zone_missing(w)?; Err(DateTimeWriteError::MissingInputField("time_zone")) } - Some(CustomTimeZone { - #[cfg(feature = "experimental")] - gmt_offset, - metazone_id: Some(metazone_id), - time_zone_id, - .. - }) => match zone_symbols - .ok_or(GetSymbolForTimeZoneError::MissingNames(field)) - .and_then(|zs| zs.get_generic_short_for_zone(metazone_id, time_zone_id)) - { - Err(e) => match e { - GetSymbolForTimeZoneError::TypeTooNarrow => { - write_time_zone_missing(w)?; - Err(DateTimeWriteError::MissingNames(field)) - } - #[cfg(feature = "experimental")] - GetSymbolForTimeZoneError::Missing => { - try_write_time_zone_gmt(w, gmt_offset, zone_symbols, true)? - .map_err(|_| DateTimeWriteError::MissingNames(field)) - } - GetSymbolForTimeZoneError::MissingNames(f) => { - write_time_zone_missing(w)?; - Err(DateTimeWriteError::MissingNames(f)) + Some(custom_time_zone) => match zone_symbols { + None => { + write_time_zone_missing(w)?; + Err(DateTimeWriteError::MissingZoneSymbols) + } + Some(zs) => { + let payloads = zs.get_payloads(); + let tz_formatter = GenericNonLocationShortFormat {}; + match tz_formatter.format(w, &custom_time_zone.into(), payloads)? { + Ok(()) => Ok(()), + Err(e) => { + write_time_zone_missing(w)?; + Err(match e { + FormatTimeZoneError::MissingInputField(s) => { + DateTimeWriteError::MissingInputField(s) + } + FormatTimeZoneError::NameNotFound => { + DateTimeWriteError::MissingNames(field) + } + FormatTimeZoneError::MissingZoneSymbols => { + DateTimeWriteError::MissingZoneSymbols + } + }) + } } - }, - Ok(s) => Ok(w.write_str(s)?), + } }, - Some(CustomTimeZone { gmt_offset, .. }) => { - // Required time zone fields not present in input - try_write_time_zone_gmt(w, gmt_offset, zone_symbols, false)? - .map_err(|_| DateTimeWriteError::MissingInputField("metazone_id")) - } }) } diff --git a/components/datetime/src/format/neo.rs b/components/datetime/src/format/neo.rs index a31feb77396..730aca4547c 100644 --- a/components/datetime/src/format/neo.rs +++ b/components/datetime/src/format/neo.rs @@ -19,14 +19,17 @@ use crate::neo_skeleton::NeoDateTimeComponents; use crate::pattern::PatternItem; use crate::provider::date_time::{ DateSymbols, GetSymbolForDayPeriodError, GetSymbolForEraError, GetSymbolForMonthError, - GetSymbolForTimeZoneError, GetSymbolForWeekdayError, MonthPlaceholderValue, TimeSymbols, - ZoneSymbols, + GetSymbolForWeekdayError, MonthPlaceholderValue, TimeSymbols, ZoneSymbols, }; use crate::provider::neo::*; use crate::provider::time_zones::{ - MetazoneGenericNamesShortV1, MetazoneGenericNamesShortV1Marker, TimeZoneFormatsV1, - TimeZoneFormatsV1Marker, + ExemplarCitiesV1, ExemplarCitiesV1Marker, MetazoneGenericNamesLongV1, + MetazoneGenericNamesLongV1Marker, MetazoneGenericNamesShortV1, + MetazoneGenericNamesShortV1Marker, MetazoneSpecificNamesLongV1, + MetazoneSpecificNamesLongV1Marker, MetazoneSpecificNamesShortV1, + MetazoneSpecificNamesShortV1Marker, TimeZoneFormatsV1, TimeZoneFormatsV1Marker, }; +use crate::time_zone::TimeZoneDataPayloadsBorrowed; use core::fmt; use core::marker::PhantomData; use icu_calendar::provider::WeekDataV2Marker; @@ -37,89 +40,232 @@ use icu_decimal::options::FixedDecimalFormatterOptions; use icu_decimal::options::GroupingStrategy; use icu_decimal::provider::DecimalSymbolsV1Marker; use icu_decimal::FixedDecimalFormatter; +use icu_provider::marker::NeverMarker; use icu_provider::prelude::*; -use icu_timezone::{MetazoneId, TimeZoneBcp47Id}; use writeable::TryWriteable; use yoke::Yokeable; +pub trait DateTimeNamesHolderTrait { + type Container: MaybePayload2 + + fmt::Debug; +} + +impl DateTimeNamesHolderTrait for NeverMarker<()> { + type Container = (); +} + +macro_rules! impl_holder_trait { + ($marker:path) => { + impl DateTimeNamesHolderTrait<$marker> for $marker { + type Container = + DateTimeNamesData2<$marker, Variables>; + } + }; +} + +impl_holder_trait!(YearNamesV1Marker); +impl_holder_trait!(MonthNamesV1Marker); +impl_holder_trait!(WeekdayNamesV1Marker); +impl_holder_trait!(DayPeriodNamesV1Marker); +impl_holder_trait!(TimeZoneFormatsV1Marker); +impl_holder_trait!(ExemplarCitiesV1Marker); +impl_holder_trait!(MetazoneGenericNamesLongV1Marker); +impl_holder_trait!(MetazoneGenericNamesShortV1Marker); +impl_holder_trait!(MetazoneSpecificNamesLongV1Marker); +impl_holder_trait!(MetazoneSpecificNamesShortV1Marker); + +#[non_exhaustive] +pub enum MaybePayloadError2 { + TypeTooNarrow, + InsufficientStorage, +} + +impl MaybePayloadError2 { + fn into_single_load_error(self, field: Field) -> SingleLoadError { + match self { + Self::TypeTooNarrow => SingleLoadError::TypeTooNarrow(field), + Self::InsufficientStorage => SingleLoadError::DuplicateField(field), + } + } +} + +pub trait MaybePayload2 { + fn new_empty() -> Self; + fn load_put

( + &mut self, + provider: &P, + req: DataRequest, + variables: Variables, + ) -> Result, MaybePayloadError2> + where + P: BoundDataProvider + ?Sized, + Self: Sized; + fn get(&self) -> DateTimeNamesData2Borrowed; +} + +pub struct DateTimeNamesData2 { + inner: OptionalNames>, +} + +impl fmt::Debug for DateTimeNamesData2 +where + Variables: fmt::Debug, + DataPayload: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.inner.fmt(f) + } +} + +impl DateTimeNamesData2 { + #[inline] + pub(crate) fn none() -> Self { + Self { + inner: OptionalNames::None, + } + } +} + +pub struct DateTimeNamesData2Borrowed<'data, M: DynamicDataMarker, Variables> { + inner: OptionalNames>::Output>, +} + +impl MaybePayload2 + for DateTimeNamesData2 +where + Variables: PartialEq + Copy, +{ + #[inline] + fn new_empty() -> Self { + Self { + inner: OptionalNames::None, + } + } + fn load_put

( + &mut self, + provider: &P, + req: DataRequest, + variables: Variables, + ) -> Result, MaybePayloadError2> + where + P: BoundDataProvider + ?Sized, + Self: Sized, + { + let arg_variables = variables; + match &self.inner { + OptionalNames::SingleLength { variables, .. } if arg_variables == *variables => { + return Ok(Ok(())); + } + OptionalNames::SingleLength { .. } => { + return Err(MaybePayloadError2::InsufficientStorage); + } + OptionalNames::None => (), + }; + match provider.load_bound(req) { + Ok(response) => { + self.inner = OptionalNames::SingleLength { + payload: response.payload.cast(), + variables: arg_variables, + }; + Ok(Ok(())) + } + Err(e) => Ok(Err(e)), + } + } + #[inline] + fn get(&self) -> DateTimeNamesData2Borrowed { + DateTimeNamesData2Borrowed { + inner: self.inner.as_borrowed(), + } + } +} + +impl MaybePayload2 for () { + #[inline] + fn new_empty() -> Self {} + #[inline] + fn load_put

( + &mut self, + _: &P, + _: DataRequest, + _: Variables, + ) -> Result, MaybePayloadError2> + where + P: BoundDataProvider + ?Sized, + Self: Sized, + { + Err(MaybePayloadError2::TypeTooNarrow) + } + #[allow(clippy::needless_lifetimes)] // Yokeable is involved + #[inline] + fn get(&self) -> DateTimeNamesData2Borrowed { + DateTimeNamesData2Borrowed { + inner: OptionalNames::None, + } + } +} + /// This can be extended in the future to support multiple lengths. /// For now, this type wraps a symbols object tagged with a single length. See #4337 #[derive(Debug, Copy, Clone)] -enum OptionalNames { +enum OptionalNames { None, - SingleLength(S, FieldLength, T), + SingleLength { + variables: Variables, + payload: Payload, + }, } -enum NamePresence { - /// The data is not loaded - NotLoaded, - /// The data matches and is already loaded - Loaded, - /// There is data loaded which does not match - Mismatched, -} - -impl OptionalNames +impl OptionalNames where - S: Copy + PartialEq, + Variables: Copy + PartialEq, + Payload: Copy, { - pub(crate) fn check_with_length( - &self, - field_symbol: S, - field_length: FieldLength, - ) -> NamePresence { + pub(crate) fn get_with_variables(&self, arg_variables: Variables) -> Option { match self { - Self::SingleLength(actual_field_symbol, actual_length, _) - if field_symbol == *actual_field_symbol && field_length == *actual_length => - { - NamePresence::Loaded + Self::None => None, + Self::SingleLength { variables, payload } if arg_variables == *variables => { + Some(*payload) } - OptionalNames::SingleLength(_, _, _) => NamePresence::Mismatched, - OptionalNames::None => NamePresence::NotLoaded, + _ => None, } } } -impl OptionalNames +impl OptionalNames<(), Payload> where - S: Copy + PartialEq, - T: Copy, + Payload: Copy, { - pub(crate) fn get_with_length(&self, field_symbol: S, field_length: FieldLength) -> Option { + pub(crate) fn get_option(&self) -> Option { match self { - Self::None => None, - Self::SingleLength(actual_field_symbol, actual_length, t) - if field_symbol == *actual_field_symbol && field_length == *actual_length => - { - Some(*t) - } + Self::SingleLength { + variables: (), + payload, + } => Some(*payload), _ => None, } } } -impl OptionalNames +impl OptionalNames> where - S: Copy, + Variables: Copy, { + #[allow(clippy::needless_lifetimes)] // Yokeable is involved #[inline] - pub(crate) fn as_borrowed<'a, Y>(&'a self) -> OptionalNames>::Output> - where - T: MaybePayload, - Y: for<'y> Yokeable<'y>, - { + pub(crate) fn as_borrowed<'a>( + &'a self, + ) -> OptionalNames>::Output> { match self { Self::None => OptionalNames::None, - Self::SingleLength(field_symbol, field_length, payload) => match payload.maybe_get() { - Some(data) => OptionalNames::SingleLength(*field_symbol, *field_length, data), - None => OptionalNames::None, + Self::SingleLength { variables, payload } => OptionalNames::SingleLength { + variables: *variables, + payload: payload.get(), }, } } } -const IGNORED_FIELD_LENGTH: FieldLength = FieldLength::One; - size_test!( TypedDateTimeNames, typed_date_time_names_size, @@ -237,116 +383,64 @@ pub struct TypedDateTimeNames> + fmt::Debug; - type MonthNames: MaybePayload> + fmt::Debug; - type WeekdayNames: MaybePayload> + fmt::Debug; - type DayPeriodNames: MaybePayload> + fmt::Debug; - type ZoneEssentials: MaybePayload> + fmt::Debug; - type ZoneGenericShortNames: MaybePayload> + fmt::Debug; -} - -pub trait MaybePayload Yokeable<'a>> { - fn maybe_from_payload(payload: DataPayload) -> Option - where - M: DynamicDataMarker, - Self: Sized; - fn load_from(provider: &P, req: DataRequest) -> Option> - where - M: DynamicDataMarker, - P: BoundDataProvider + ?Sized, - Self: Sized; - #[allow(clippy::needless_lifetimes)] // Yokeable is involved - fn maybe_get<'a>(&'a self) -> Option<&'a >::Output>; -} - -impl Yokeable<'a>> MaybePayload for DataPayload -where - M0: DynamicDataMarker, -{ - #[inline] - fn maybe_from_payload(payload: DataPayload) -> Option - where - M: DynamicDataMarker, - { - Some(payload.cast()) - } - #[inline] - fn load_from(provider: &P, req: DataRequest) -> Option> - where - M: DynamicDataMarker, - P: BoundDataProvider + ?Sized, - Self: Sized, - { - Some(provider.load_bound(req).map(|r| r.payload.cast())) - } - #[allow(clippy::needless_lifetimes)] // Yokeable is involved - #[inline] - fn maybe_get<'a>(&'a self) -> Option<&'a >::Output> { - Some(self.get()) - } -} - -impl Yokeable<'a>> MaybePayload for () { - #[inline] - fn maybe_from_payload(_payload: DataPayload) -> Option - where - M: DynamicDataMarker, - { - None - } - #[inline] - fn load_from(_provider: &P, _req: DataRequest) -> Option> - where - M: DynamicDataMarker, - P: BoundDataProvider + ?Sized, - Self: Sized, - { - // TODO: Is it better to return DataError or SingleLoadError? - // SingleLoadError needs to be from the caller because it needs `field`. - None - // Err(DataError::custom("cannot load into this type").with_req(provider.marker(), req)) - } - #[allow(clippy::needless_lifetimes)] // Yokeable is involved - #[inline] - fn maybe_get<'a>(&'a self) -> Option<&'a >::Output> { - None - } + type YearNames: DateTimeNamesHolderTrait; + type MonthNames: DateTimeNamesHolderTrait; + type WeekdayNames: DateTimeNamesHolderTrait; + type DayPeriodNames: DateTimeNamesHolderTrait; + type ZoneEssentials: DateTimeNamesHolderTrait; + type ZoneExemplarCities: DateTimeNamesHolderTrait; + type ZoneGenericLong: DateTimeNamesHolderTrait; + type ZoneGenericShort: DateTimeNamesHolderTrait; + type ZoneSpecificLong: DateTimeNamesHolderTrait; + type ZoneSpecificShort: DateTimeNamesHolderTrait; } #[derive(Debug)] pub struct DateMarker {} impl DateTimeNamesMarker for DateMarker { - type YearNames = DataPayload; - type MonthNames = DataPayload; - type WeekdayNames = DataPayload; - type DayPeriodNames = (); - type ZoneEssentials = (); - type ZoneGenericShortNames = (); + type YearNames = YearNamesV1Marker; + type MonthNames = MonthNamesV1Marker; + type WeekdayNames = WeekdayNamesV1Marker; + type DayPeriodNames = NeverMarker<()>; + type ZoneEssentials = NeverMarker<()>; + type ZoneExemplarCities = NeverMarker<()>; + type ZoneGenericLong = NeverMarker<()>; + type ZoneGenericShort = NeverMarker<()>; + type ZoneSpecificLong = NeverMarker<()>; + type ZoneSpecificShort = NeverMarker<()>; } #[derive(Debug)] pub struct TimeMarker {} impl DateTimeNamesMarker for TimeMarker { - type YearNames = (); - type MonthNames = (); - type WeekdayNames = (); - type DayPeriodNames = DataPayload; - type ZoneEssentials = (); - type ZoneGenericShortNames = (); + type YearNames = NeverMarker<()>; + type MonthNames = NeverMarker<()>; + type WeekdayNames = NeverMarker<()>; + type DayPeriodNames = DayPeriodNamesV1Marker; + type ZoneEssentials = NeverMarker<()>; + type ZoneExemplarCities = NeverMarker<()>; + type ZoneGenericLong = NeverMarker<()>; + type ZoneGenericShort = NeverMarker<()>; + type ZoneSpecificLong = NeverMarker<()>; + type ZoneSpecificShort = NeverMarker<()>; } #[derive(Debug)] pub struct DateTimeMarker {} impl DateTimeNamesMarker for DateTimeMarker { - type YearNames = DataPayload; - type MonthNames = DataPayload; - type WeekdayNames = DataPayload; - type DayPeriodNames = DataPayload; - type ZoneEssentials = (); - type ZoneGenericShortNames = (); + type YearNames = YearNamesV1Marker; + type MonthNames = MonthNamesV1Marker; + type WeekdayNames = WeekdayNamesV1Marker; + type DayPeriodNames = DayPeriodNamesV1Marker; + type ZoneEssentials = NeverMarker<()>; + type ZoneExemplarCities = NeverMarker<()>; + type ZoneGenericLong = NeverMarker<()>; + type ZoneGenericShort = NeverMarker<()>; + type ZoneSpecificLong = NeverMarker<()>; + type ZoneSpecificShort = NeverMarker<()>; } impl From> for RawDateTimeNames { @@ -355,9 +449,13 @@ impl From> for RawDateTimeNames { year_symbols: other.year_symbols, month_symbols: other.month_symbols, weekday_symbols: other.weekday_symbols, - dayperiod_symbols: OptionalNames::None, - zone_essentials: OptionalNames::None, - zone_generic_short_names: OptionalNames::None, + dayperiod_symbols: DateTimeNamesData2::none(), + zone_essentials: (), + exemplar_cities: (), + mz_generic_long: (), + mz_generic_short: (), + mz_specific_long: (), + mz_specific_short: (), fixed_decimal_formatter: other.fixed_decimal_formatter, week_calculator: other.week_calculator, _marker: PhantomData, @@ -368,12 +466,16 @@ impl From> for RawDateTimeNames { impl From> for RawDateTimeNames { fn from(other: RawDateTimeNames) -> Self { Self { - year_symbols: OptionalNames::None, - month_symbols: OptionalNames::None, - weekday_symbols: OptionalNames::None, + year_symbols: DateTimeNamesData2::none(), + month_symbols: DateTimeNamesData2::none(), + weekday_symbols: DateTimeNamesData2::none(), dayperiod_symbols: other.dayperiod_symbols, - zone_essentials: OptionalNames::None, - zone_generic_short_names: OptionalNames::None, + zone_essentials: (), + exemplar_cities: (), + mz_generic_long: (), + mz_generic_short: (), + mz_specific_long: (), + mz_specific_short: (), fixed_decimal_formatter: other.fixed_decimal_formatter, week_calculator: other.week_calculator, _marker: PhantomData, @@ -381,29 +483,74 @@ impl From> for RawDateTimeNames { } } -#[derive(Debug)] pub(crate) struct RawDateTimeNames { - year_symbols: OptionalNames<(), R::YearNames>, - month_symbols: OptionalNames, - weekday_symbols: OptionalNames, - dayperiod_symbols: OptionalNames<(), R::DayPeriodNames>, - zone_essentials: OptionalNames<(), R::ZoneEssentials>, - zone_generic_short_names: OptionalNames<(), R::ZoneGenericShortNames>, + year_symbols: + >::Container, + month_symbols: >::Container<( + fields::Month, + FieldLength, + )>, + weekday_symbols: >::Container< + (fields::Weekday, FieldLength), + >, + dayperiod_symbols: + >::Container< + FieldLength, + >, + zone_essentials: + >::Container<()>, + exemplar_cities: + >::Container<()>, + mz_generic_long: >::Container<()>, + mz_generic_short: >::Container<()>, + mz_specific_long: >::Container<()>, + mz_specific_short: >::Container<()>, // TODO(#4340): Make the FixedDecimalFormatter optional fixed_decimal_formatter: Option, week_calculator: Option, _marker: PhantomData, } +// Need a custom impl because not all of the associated types impl Debug +impl fmt::Debug for RawDateTimeNames { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("RawDateTimeNames") + .field("year_symbols", &self.year_symbols) + .field("month_symbols", &self.month_symbols) + .field("weekday_symbols", &self.weekday_symbols) + .field("dayperiod_symbols", &self.dayperiod_symbols) + .field("zone_essentials", &self.zone_essentials) + .field("exemplar_cities", &self.exemplar_cities) + .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) + .field("week_calculator", &self.week_calculator) + .finish() + } +} + #[derive(Debug, Copy, Clone)] pub(crate) struct RawDateTimeNamesBorrowed<'l> { - year_names: OptionalNames<(), &'l YearNamesV1<'l>>, - month_names: OptionalNames>, - weekday_names: OptionalNames>, - dayperiod_names: OptionalNames<(), &'l LinearNamesV1<'l>>, - // TODO: Do something with zone_essentials - _zone_essentials: OptionalNames<(), &'l TimeZoneFormatsV1<'l>>, - zone_generic_short_names: OptionalNames<(), &'l MetazoneGenericNamesShortV1<'l>>, + year_names: OptionalNames>, + month_names: OptionalNames<(fields::Month, FieldLength), &'l MonthNamesV1<'l>>, + weekday_names: OptionalNames<(fields::Weekday, FieldLength), &'l LinearNamesV1<'l>>, + dayperiod_names: OptionalNames>, + zone_essentials: OptionalNames<(), &'l TimeZoneFormatsV1<'l>>, + exemplar_cities: OptionalNames<(), &'l ExemplarCitiesV1<'l>>, + mz_generic_long: OptionalNames<(), &'l MetazoneGenericNamesLongV1<'l>>, + mz_generic_short: OptionalNames<(), &'l MetazoneGenericNamesShortV1<'l>>, + mz_specific_long: OptionalNames<(), &'l MetazoneSpecificNamesLongV1<'l>>, + mz_specific_short: OptionalNames<(), &'l MetazoneSpecificNamesShortV1<'l>>, pub(crate) fixed_decimal_formatter: Option<&'l FixedDecimalFormatter>, pub(crate) week_calculator: Option<&'l WeekCalculator>, } @@ -730,7 +877,7 @@ impl TypedDateTimeNames { /// use writeable::assert_try_writeable_eq; /// /// let mut names = - /// TypedDateTimeNames::::try_new(&locale!("th-TH").into()) + /// TypedDateTimeNames::::try_new(&locale!("sr-ME").into()) /// .unwrap(); /// /// names @@ -742,8 +889,8 @@ impl TypedDateTimeNames { /// let pattern: DateTimePattern = pattern_str.parse().unwrap(); /// /// assert_try_writeable_eq!( - /// names.with_pattern(&pattern).format(&CustomTimeZone::bst()), - /// "Your time zone is: {todo}", + /// names.with_pattern(&pattern).format(&CustomTimeZone::gmt()), + /// "Your time zone is: GMT", /// ); /// ``` #[cfg(feature = "compiled_data")] @@ -978,12 +1125,16 @@ impl From for LoadError { impl RawDateTimeNames { pub(crate) fn new_without_fixed_decimal_formatter() -> Self { Self { - year_symbols: OptionalNames::None, - month_symbols: OptionalNames::None, - weekday_symbols: OptionalNames::None, - dayperiod_symbols: OptionalNames::None, - zone_essentials: OptionalNames::None, - zone_generic_short_names: OptionalNames::None, + year_symbols: >::Container::<_>::new_empty(), + month_symbols: >::Container::<_>::new_empty(), + weekday_symbols: >::Container::<_>::new_empty(), + dayperiod_symbols: >::Container::<_>::new_empty(), + zone_essentials: >::Container::<_>::new_empty(), + exemplar_cities: >::Container::<_>::new_empty(), + mz_generic_long: >::Container::<_>::new_empty(), + mz_generic_short: >::Container::<_>::new_empty(), + mz_specific_long: >::Container::<_>::new_empty(), + mz_specific_short: >::Container::<_>::new_empty(), fixed_decimal_formatter: None, week_calculator: None, _marker: PhantomData, @@ -992,12 +1143,16 @@ impl RawDateTimeNames { pub(crate) fn as_borrowed(&self) -> RawDateTimeNamesBorrowed { RawDateTimeNamesBorrowed { - year_names: self.year_symbols.as_borrowed(), - month_names: self.month_symbols.as_borrowed(), - weekday_names: self.weekday_symbols.as_borrowed(), - dayperiod_names: self.dayperiod_symbols.as_borrowed(), - _zone_essentials: self.zone_essentials.as_borrowed(), - zone_generic_short_names: self.zone_generic_short_names.as_borrowed(), + year_names: self.year_symbols.get().inner, + month_names: self.month_symbols.get().inner, + weekday_names: self.weekday_symbols.get().inner, + dayperiod_names: self.dayperiod_symbols.get().inner, + zone_essentials: self.zone_essentials.get().inner, + exemplar_cities: self.exemplar_cities.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, fixed_decimal_formatter: self.fixed_decimal_formatter.as_ref(), week_calculator: self.week_calculator.as_ref(), } @@ -1018,35 +1173,26 @@ impl RawDateTimeNames { }; // UTS 35 says that "G..GGG" are all Abbreviated let field_length = field_length.numeric_to_abbr(); - match self.year_symbols.check_with_length((), field_length) { - NamePresence::Loaded => return Ok(()), - NamePresence::NotLoaded => (), - NamePresence::Mismatched => return Err(SingleLoadError::DuplicateField(field)), - }; - let payload = provider - .load_bound(DataRequest { - id: DataIdentifierBorrowed::for_marker_attributes_and_locale( - marker_attrs::symbol_attr_for( - marker_attrs::Context::Format, - match field_length { - FieldLength::Abbreviated => marker_attrs::Length::Abbr, - FieldLength::Narrow => marker_attrs::Length::Narrow, - FieldLength::Wide => marker_attrs::Length::Wide, - _ => return Err(SingleLoadError::UnsupportedField(field)), - }, - ), - locale, + let variables = field_length; + let req = DataRequest { + id: DataIdentifierBorrowed::for_marker_attributes_and_locale( + marker_attrs::symbol_attr_for( + marker_attrs::Context::Format, + match field_length { + FieldLength::Abbreviated => marker_attrs::Length::Abbr, + FieldLength::Narrow => marker_attrs::Length::Narrow, + FieldLength::Wide => marker_attrs::Length::Wide, + _ => return Err(SingleLoadError::UnsupportedField(field)), + }, ), - ..Default::default() - }) - .map_err(SingleLoadError::Data)? - .payload; - self.year_symbols = OptionalNames::SingleLength( - (), - field_length, - R::YearNames::maybe_from_payload(payload) - .ok_or(SingleLoadError::TypeTooNarrow(field))?, - ); + locale, + ), + ..Default::default() + }; + self.year_symbols + .load_put(provider, req, variables) + .map_err(|e| MaybePayloadError2::into_single_load_error(e, field))? + .map_err(SingleLoadError::Data)?; Ok(()) } @@ -1064,42 +1210,29 @@ impl RawDateTimeNames { symbol: FieldSymbol::Month(field_symbol), length: field_length, }; - // Note: UTS 35 says that "M..MM" and "L..LL" are numeric - match self - .month_symbols - .check_with_length(field_symbol, field_length) - { - NamePresence::Loaded => return Ok(()), - NamePresence::NotLoaded => (), - NamePresence::Mismatched => return Err(SingleLoadError::DuplicateField(field)), - }; - let payload = provider - .load_bound(DataRequest { - id: DataIdentifierBorrowed::for_marker_attributes_and_locale( - marker_attrs::symbol_attr_for( - match field_symbol { - fields::Month::Format => marker_attrs::Context::Format, - fields::Month::StandAlone => marker_attrs::Context::Standalone, - }, - match field_length { - FieldLength::Abbreviated => marker_attrs::Length::Abbr, - FieldLength::Narrow => marker_attrs::Length::Narrow, - FieldLength::Wide => marker_attrs::Length::Wide, - _ => return Err(SingleLoadError::UnsupportedField(field)), - }, - ), - locale, + let variables = (field_symbol, field_length); + let req = DataRequest { + id: DataIdentifierBorrowed::for_marker_attributes_and_locale( + marker_attrs::symbol_attr_for( + match field_symbol { + fields::Month::Format => marker_attrs::Context::Format, + fields::Month::StandAlone => marker_attrs::Context::Standalone, + }, + match field_length { + FieldLength::Abbreviated => marker_attrs::Length::Abbr, + FieldLength::Narrow => marker_attrs::Length::Narrow, + FieldLength::Wide => marker_attrs::Length::Wide, + _ => return Err(SingleLoadError::UnsupportedField(field)), + }, ), - ..Default::default() - }) - .map_err(SingleLoadError::Data)? - .payload; - self.month_symbols = OptionalNames::SingleLength( - field_symbol, - field_length, - R::MonthNames::maybe_from_payload(payload) - .ok_or(SingleLoadError::TypeTooNarrow(field))?, - ); + locale, + ), + ..Default::default() + }; + self.month_symbols + .load_put(provider, req, variables) + .map_err(|e| MaybePayloadError2::into_single_load_error(e, field))? + .map_err(SingleLoadError::Data)?; Ok(()) } @@ -1119,32 +1252,26 @@ impl RawDateTimeNames { }; // UTS 35 says that "a..aaa" are all Abbreviated let field_length = field_length.numeric_to_abbr(); - match self.dayperiod_symbols.check_with_length((), field_length) { - NamePresence::Loaded => return Ok(()), - NamePresence::NotLoaded => (), - NamePresence::Mismatched => return Err(SingleLoadError::DuplicateField(field)), - }; - let payload = R::DayPeriodNames::load_from( - provider, - DataRequest { - id: DataIdentifierBorrowed::for_marker_attributes_and_locale( - marker_attrs::symbol_attr_for( - marker_attrs::Context::Format, - match field_length { - FieldLength::Abbreviated => marker_attrs::Length::Abbr, - FieldLength::Narrow => marker_attrs::Length::Narrow, - FieldLength::Wide => marker_attrs::Length::Wide, - _ => return Err(SingleLoadError::UnsupportedField(field)), - }, - ), - locale, + let variables = field_length; + let req = DataRequest { + id: DataIdentifierBorrowed::for_marker_attributes_and_locale( + marker_attrs::symbol_attr_for( + marker_attrs::Context::Format, + match field_length { + FieldLength::Abbreviated => marker_attrs::Length::Abbr, + FieldLength::Narrow => marker_attrs::Length::Narrow, + FieldLength::Wide => marker_attrs::Length::Wide, + _ => return Err(SingleLoadError::UnsupportedField(field)), + }, ), - ..Default::default() - }, - ) - .ok_or(SingleLoadError::TypeTooNarrow(field))? - .map_err(SingleLoadError::Data)?; - self.dayperiod_symbols = OptionalNames::SingleLength((), field_length, payload); + locale, + ), + ..Default::default() + }; + self.dayperiod_symbols + .load_put(provider, req, variables) + .map_err(|e| MaybePayloadError2::into_single_load_error(e, field))? + .map_err(SingleLoadError::Data)?; Ok(()) } @@ -1169,45 +1296,33 @@ impl RawDateTimeNames { } else { field_length }; - match self - .weekday_symbols - .check_with_length(field_symbol, field_length) - { - NamePresence::Loaded => return Ok(()), - NamePresence::NotLoaded => (), - NamePresence::Mismatched => return Err(SingleLoadError::DuplicateField(field)), - }; - let payload = provider - .load_bound(DataRequest { - id: DataIdentifierBorrowed::for_marker_attributes_and_locale( - marker_attrs::symbol_attr_for( - match field_symbol { - // UTS 35 says that "e" and "E" have the same non-numeric names - fields::Weekday::Format | fields::Weekday::Local => { - marker_attrs::Context::Format - } - fields::Weekday::StandAlone => marker_attrs::Context::Standalone, - }, - match field_length { - FieldLength::Abbreviated => marker_attrs::Length::Abbr, - FieldLength::Narrow => marker_attrs::Length::Narrow, - FieldLength::Wide => marker_attrs::Length::Wide, - FieldLength::Six => marker_attrs::Length::Short, - _ => return Err(SingleLoadError::UnsupportedField(field)), - }, - ), - locale, + let variables = (field_symbol, field_length); + let req = DataRequest { + id: DataIdentifierBorrowed::for_marker_attributes_and_locale( + marker_attrs::symbol_attr_for( + match field_symbol { + // UTS 35 says that "e" and "E" have the same non-numeric names + fields::Weekday::Format | fields::Weekday::Local => { + marker_attrs::Context::Format + } + fields::Weekday::StandAlone => marker_attrs::Context::Standalone, + }, + match field_length { + FieldLength::Abbreviated => marker_attrs::Length::Abbr, + FieldLength::Narrow => marker_attrs::Length::Narrow, + FieldLength::Wide => marker_attrs::Length::Wide, + FieldLength::Six => marker_attrs::Length::Short, + _ => return Err(SingleLoadError::UnsupportedField(field)), + }, ), - ..Default::default() - }) - .map_err(SingleLoadError::Data)? - .payload; - self.weekday_symbols = OptionalNames::SingleLength( - field_symbol, - field_length, - R::WeekdayNames::maybe_from_payload(payload) - .ok_or(SingleLoadError::TypeTooNarrow(field))?, - ); + locale, + ), + ..Default::default() + }; + self.weekday_symbols + .load_put(provider, req, variables) + .map_err(|e| MaybePayloadError2::into_single_load_error(e, field))? + .map_err(SingleLoadError::Data)?; Ok(()) } @@ -1219,29 +1334,20 @@ impl RawDateTimeNames { where P: BoundDataProvider + ?Sized, { + // TODO: Get this field from a constant somewhere let field = fields::Field { symbol: FieldSymbol::TimeZone(fields::TimeZone::LowerV), - length: IGNORED_FIELD_LENGTH, + length: FieldLength::One, }; - match self - .zone_generic_short_names - .check_with_length((), IGNORED_FIELD_LENGTH) - { - NamePresence::Loaded => return Ok(()), - NamePresence::NotLoaded => (), - NamePresence::Mismatched => return Err(SingleLoadError::DuplicateField(field)), + let variables = (); + let req = DataRequest { + id: DataIdentifierBorrowed::for_locale(locale), + ..Default::default() }; - let payload = R::ZoneGenericShortNames::load_from( - provider, - DataRequest { - id: DataIdentifierBorrowed::for_locale(locale), - ..Default::default() - }, - ) - .ok_or(SingleLoadError::TypeTooNarrow(field))? - .map_err(SingleLoadError::Data)?; - self.zone_generic_short_names = - OptionalNames::SingleLength((), IGNORED_FIELD_LENGTH, payload); + self.mz_generic_short + .load_put(provider, req, variables) + .map_err(|e| MaybePayloadError2::into_single_load_error(e, field))? + .map_err(SingleLoadError::Data)?; Ok(()) } @@ -1578,7 +1684,7 @@ impl<'data> DateSymbols<'data> for RawDateTimeNamesBorrowed<'data> { }; let month_symbols = self .month_names - .get_with_length(field_symbol, field_length) + .get_with_variables((field_symbol, field_length)) .ok_or(GetSymbolForMonthError::MissingNames(field))?; let Some((month_number, is_leap)) = code.parsed() else { return Err(GetSymbolForMonthError::Missing); @@ -1641,7 +1747,7 @@ impl<'data> DateSymbols<'data> for RawDateTimeNamesBorrowed<'data> { }; let weekday_symbols = self .weekday_names - .get_with_length(field_symbol, field_length) + .get_with_variables((field_symbol, field_length)) .ok_or(GetSymbolForWeekdayError::MissingNames(field))?; weekday_symbols .symbols @@ -1662,7 +1768,7 @@ impl<'data> DateSymbols<'data> for RawDateTimeNamesBorrowed<'data> { let field_length = field_length.numeric_to_abbr(); let year_symbols = self .year_names - .get_with_length((), field_length) + .get_with_variables(field_length) .ok_or(GetSymbolForEraError::MissingNames(field))?; let YearNamesV1::Eras(era_symbols) = year_symbols else { return Err(GetSymbolForEraError::MissingNames(field)); @@ -1690,7 +1796,7 @@ impl<'data> TimeSymbols for RawDateTimeNamesBorrowed<'data> { let field_length = field_length.numeric_to_abbr(); let dayperiod_symbols = self .dayperiod_names - .get_with_length((), field_length) + .get_with_variables(field_length) .ok_or(GetSymbolForDayPeriodError::MissingNames(field))?; let option_value: Option<&str> = match (field_symbol, u8::from(hour), is_top_of_hour) { (NoonMidnight, 00, true) => dayperiod_symbols @@ -1704,24 +1810,16 @@ impl<'data> TimeSymbols for RawDateTimeNamesBorrowed<'data> { } } -impl<'data> ZoneSymbols for RawDateTimeNamesBorrowed<'data> { - fn get_generic_short_for_zone( - &self, - metazone_id: MetazoneId, - time_zone_id: Option, - ) -> Result<&str, GetSymbolForTimeZoneError> { - let field = fields::Field { - symbol: FieldSymbol::TimeZone(fields::TimeZone::LowerV), - length: IGNORED_FIELD_LENGTH, - }; - let data = self - .zone_generic_short_names - .get_with_length((), IGNORED_FIELD_LENGTH) - .ok_or(GetSymbolForTimeZoneError::MissingNames(field))?; - time_zone_id - .and_then(|time_zone_id| data.overrides.get(&time_zone_id)) - .or_else(|| data.defaults.get(&metazone_id)) - .ok_or(GetSymbolForTimeZoneError::Missing) +impl<'data> ZoneSymbols<'data> for RawDateTimeNamesBorrowed<'data> { + fn get_payloads(&self) -> crate::time_zone::TimeZoneDataPayloadsBorrowed<'data> { + TimeZoneDataPayloadsBorrowed { + zone_formats: self.zone_essentials.get_option(), + exemplar_cities: self.exemplar_cities.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(), + } } } diff --git a/components/datetime/src/input.rs b/components/datetime/src/input.rs index 0a848f2d94e..cdb397a22d0 100644 --- a/components/datetime/src/input.rs +++ b/components/datetime/src/input.rs @@ -263,6 +263,17 @@ impl ExtractedTimeZoneInput { } } +impl From for ExtractedTimeZoneInput { + fn from(value: CustomTimeZone) -> Self { + Self { + gmt_offset: value.gmt_offset, + time_zone_id: value.time_zone_id, + metazone_id: value.metazone_id, + zone_variant: value.zone_variant, + } + } +} + impl DateInput for ExtractedDateTimeInput { /// This actually doesn't matter, by the time we use this /// it's purely internal raw code where calendars are irrelevant diff --git a/components/datetime/src/neo.rs b/components/datetime/src/neo.rs index ef189e71503..5585b44db98 100644 --- a/components/datetime/src/neo.rs +++ b/components/datetime/src/neo.rs @@ -154,7 +154,7 @@ macro_rules! gen_any_buffer_constructors_with_external_loader { }; } -size_test!(TypedNeoFormatter, typed_neo_year_month_day_formatter_size, 544); +size_test!(TypedNeoFormatter, typed_neo_year_month_day_formatter_size, 536); /// [`TypedNeoFormatter`] is a formatter capable of formatting dates and/or times from /// a calendar selected at compile time. @@ -557,7 +557,7 @@ impl> TypedNeoFormatter { size_test!( NeoFormatter, neo_year_month_day_formatter_size, - 600 + 592 ); /// [`NeoFormatter`] is a formatter capable of formatting dates and/or times from diff --git a/components/datetime/src/neo_marker.rs b/components/datetime/src/neo_marker.rs index c9e0881ea9a..d54d537a736 100644 --- a/components/datetime/src/neo_marker.rs +++ b/components/datetime/src/neo_marker.rs @@ -13,8 +13,9 @@ use crate::{ provider::{ neo::*, time_zones::{ - MetazoneGenericNamesShortV1, MetazoneGenericNamesShortV1Marker, TimeZoneFormatsV1, - TimeZoneFormatsV1Marker, + ExemplarCitiesV1Marker, MetazoneGenericNamesLongV1Marker, MetazoneGenericNamesShortV1, + MetazoneGenericNamesShortV1Marker, MetazoneSpecificNamesLongV1Marker, + MetazoneSpecificNamesShortV1Marker, TimeZoneFormatsV1, TimeZoneFormatsV1Marker, }, }, CldrCalendar, @@ -635,9 +636,13 @@ where type YearNames = D::YearNames; type MonthNames = D::MonthNames; type WeekdayNames = D::WeekdayNames; - type DayPeriodNames = (); - type ZoneEssentials = (); - type ZoneGenericShortNames = (); + type DayPeriodNames = NeverMarker<()>; + type ZoneEssentials = NeverMarker<()>; + type ZoneExemplarCities = NeverMarker<()>; + type ZoneGenericLong = NeverMarker<()>; + type ZoneGenericShort = NeverMarker<()>; + type ZoneSpecificLong = NeverMarker<()>; + type ZoneSpecificShort = NeverMarker<()>; } impl TypedDateTimeMarkers for DateTimeCombo @@ -678,12 +683,16 @@ impl DateTimeNamesMarker for DateTimeCombo where T: DateTimeNamesMarker, { - type YearNames = (); - type MonthNames = (); - type WeekdayNames = (); + type YearNames = NeverMarker<()>; + type MonthNames = NeverMarker<()>; + type WeekdayNames = NeverMarker<()>; type DayPeriodNames = T::DayPeriodNames; - type ZoneEssentials = (); - type ZoneGenericShortNames = (); + type ZoneEssentials = NeverMarker<()>; + type ZoneExemplarCities = NeverMarker<()>; + type ZoneGenericLong = NeverMarker<()>; + type ZoneGenericShort = NeverMarker<()>; + type ZoneSpecificLong = NeverMarker<()>; + type ZoneSpecificShort = NeverMarker<()>; } impl TypedDateTimeMarkers for DateTimeCombo @@ -729,8 +738,12 @@ where type MonthNames = D::MonthNames; type WeekdayNames = D::WeekdayNames; type DayPeriodNames = T::DayPeriodNames; - type ZoneEssentials = (); - type ZoneGenericShortNames = (); + type ZoneEssentials = NeverMarker<()>; + type ZoneExemplarCities = NeverMarker<()>; + type ZoneGenericLong = NeverMarker<()>; + type ZoneGenericShort = NeverMarker<()>; + type ZoneSpecificLong = NeverMarker<()>; + type ZoneSpecificShort = NeverMarker<()>; } impl TypedDateTimeMarkers for DateTimeCombo @@ -862,32 +875,74 @@ macro_rules! datetime_marker_helper { (@data/zone/essentials, yes) => { TimeZoneFormatsV1Marker }; - (@data/zone/genericshort, yes) => { + (@data/zone/exemplar, yes) => { + ExemplarCitiesV1Marker + }; + (@data/zone/generic_long, yes) => { + MetazoneGenericNamesLongV1Marker + }; + (@data/zone/generic_short, yes) => { MetazoneGenericNamesShortV1Marker }; + (@data/zone/specific_long, yes) => { + MetazoneSpecificNamesLongV1Marker + }; + (@data/zone/specific_short, yes) => { + MetazoneSpecificNamesShortV1Marker + }; + (@data/zone/essentials, no) => { + NeverMarker> + }; + (@data/zone/exemplar, no) => { + NeverMarker> + }; + (@data/zone/generic_long, no) => { + NeverMarker> + }; + (@data/zone/generic_short, no) => { + NeverMarker> + }; + (@data/zone/specific_long, no) => { + NeverMarker> + }; + (@data/zone/specific_short, no) => { + NeverMarker> + }; (@names/year, yes) => { - DataPayload + YearNamesV1Marker }; (@names/month, yes) => { - DataPayload + MonthNamesV1Marker }; (@names/weekday, yes) => { - DataPayload + WeekdayNamesV1Marker }; (@names/dayperiod, yes) => { - DataPayload + DayPeriodNamesV1Marker }; (@names/zone/essentials, yes) => { - DataPayload + TimeZoneFormatsV1Marker + }; + (@names/zone/exemplar, yes) => { + ExemplarCitiesV1Marker + }; + (@names/zone/generic_long, yes) => { + MetazoneGenericNamesLongV1Marker }; - (@names/zone/genericshort, yes) => { - DataPayload + (@names/zone/generic_short, yes) => { + MetazoneGenericNamesShortV1Marker + }; + (@names/zone/specific_long, yes) => { + MetazoneSpecificNamesLongV1Marker + }; + (@names/zone/specific_short, yes) => { + MetazoneSpecificNamesShortV1Marker }; (@names/$any:ident, no) => { - () + NeverMarker<()> }; (@names/zone/$any:ident, no) => { - () + NeverMarker<()> }; } @@ -967,7 +1022,11 @@ macro_rules! impl_date_marker { type WeekdayNames = datetime_marker_helper!(@names/weekday, $weekdays_yesno); type DayPeriodNames = datetime_marker_helper!(@names/dayperiod, no); type ZoneEssentials = datetime_marker_helper!(@names/zone/essentials, no); - type ZoneGenericShortNames = datetime_marker_helper!(@names/zone/genericshort, no); + type ZoneExemplarCities = datetime_marker_helper!(@names/zone/exemplar, no); + type ZoneGenericLong = datetime_marker_helper!(@names/zone/generic_long, no); + type ZoneGenericShort = datetime_marker_helper!(@names/zone/generic_short, no); + type ZoneSpecificLong = datetime_marker_helper!(@names/zone/specific_long, no); + type ZoneSpecificShort = datetime_marker_helper!(@names/zone/specific_short, no); } impl HasDateComponents for $type { const COMPONENTS: NeoDateComponents = $components; @@ -1130,7 +1189,11 @@ macro_rules! impl_time_marker { type WeekdayNames = datetime_marker_helper!(@names/weekday, no); type DayPeriodNames = datetime_marker_helper!(@names/dayperiod, $dayperiods_yesno); type ZoneEssentials = datetime_marker_helper!(@names/zone/essentials, no); - type ZoneGenericShortNames = datetime_marker_helper!(@names/zone/genericshort, no); + type ZoneExemplarCities = datetime_marker_helper!(@names/zone/exemplar, no); + type ZoneGenericLong = datetime_marker_helper!(@names/zone/generic_long, no); + type ZoneGenericShort = datetime_marker_helper!(@names/zone/generic_short, no); + type ZoneSpecificLong = datetime_marker_helper!(@names/zone/specific_long, no); + type ZoneSpecificShort = datetime_marker_helper!(@names/zone/specific_short, no); } impl HasTimeComponents for $type { const COMPONENTS: NeoTimeComponents = $components; @@ -1171,7 +1234,11 @@ macro_rules! impl_zone_marker { description = $description:literal, expectation = $expectation:literal, zone_essentials = $zone_essentials_yesno:ident, - zone_genericshort = $zone_genericshort_yesno:ident, + zone_exemplar = $zone_exemplar_yesno:ident, + zone_generic_long = $zone_generic_long_yesno:ident, + zone_generic_short = $zone_generic_short_yesno:ident, + zone_specific_long = $zone_specific_long_yesno:ident, + zone_specific_short = $zone_specific_short_yesno:ident, ) => { #[doc = concat!("Marker for ", $description, ": ", $expectation)] /// @@ -1234,7 +1301,11 @@ macro_rules! impl_zone_marker { type WeekdayNames = datetime_marker_helper!(@names/weekday, no); type DayPeriodNames = datetime_marker_helper!(@names/dayperiod, no); type ZoneEssentials = datetime_marker_helper!(@names/zone/essentials, $zone_essentials_yesno); - type ZoneGenericShortNames = datetime_marker_helper!(@names/zone/genericshort, $zone_genericshort_yesno); + type ZoneExemplarCities = datetime_marker_helper!(@names/zone/exemplar, $zone_exemplar_yesno); + type ZoneGenericLong = datetime_marker_helper!(@names/zone/generic_long, $zone_generic_long_yesno); + type ZoneGenericShort = datetime_marker_helper!(@names/zone/generic_short, $zone_generic_short_yesno); + type ZoneSpecificLong = datetime_marker_helper!(@names/zone/specific_long, $zone_specific_long_yesno); + type ZoneSpecificShort = datetime_marker_helper!(@names/zone/specific_short, $zone_specific_short_yesno); } impl HasZoneComponent for $type { const COMPONENT: NeoTimeZoneSkeleton = $components; @@ -1242,7 +1313,7 @@ macro_rules! impl_zone_marker { impl ZoneMarkers for $type { type TimeZoneInput = datetime_marker_helper!(@input/timezone, yes); type ZoneEssentialsV1Marker = datetime_marker_helper!(@data/zone/essentials, $zone_essentials_yesno); - type ZoneGenericShortNamesV1Marker = datetime_marker_helper!(@data/zone/genericshort, $zone_genericshort_yesno); + type ZoneGenericShortNamesV1Marker = datetime_marker_helper!(@data/zone/generic_short, $zone_generic_short_yesno); } impl TypedDateTimeMarkers for $type { type D = NeoNeverMarker; @@ -1497,7 +1568,11 @@ impl_zone_marker!( description = "a generic short time zone format", expectation = "GMT", zone_essentials = yes, - zone_genericshort = yes, + zone_exemplar = yes, + zone_generic_long = yes, + zone_generic_short = yes, + zone_specific_long = yes, + zone_specific_short = yes, ); // TODO: Make this use NeoAutoZoneMarker, derived from time length patterns @@ -1525,7 +1600,11 @@ impl DateTimeNamesMarker for NeoDateComponents { type WeekdayNames = datetime_marker_helper!(@names/weekday, yes); type DayPeriodNames = datetime_marker_helper!(@names/dayperiod, no); type ZoneEssentials = datetime_marker_helper!(@names/zone/essentials, no); - type ZoneGenericShortNames = datetime_marker_helper!(@names/zone/genericshort, no); + type ZoneExemplarCities = datetime_marker_helper!(@names/zone/exemplar, no); + type ZoneGenericLong = datetime_marker_helper!(@names/zone/generic_long, no); + type ZoneGenericShort = datetime_marker_helper!(@names/zone/generic_short, no); + type ZoneSpecificLong = datetime_marker_helper!(@names/zone/specific_long, no); + type ZoneSpecificShort = datetime_marker_helper!(@names/zone/specific_short, no); } impl TypedDateMarkers for NeoDateComponents { @@ -1579,7 +1658,11 @@ impl DateTimeNamesMarker for NeoTimeComponents { type WeekdayNames = datetime_marker_helper!(@names/weekday, no); type DayPeriodNames = datetime_marker_helper!(@names/dayperiod, yes); type ZoneEssentials = datetime_marker_helper!(@names/zone/essentials, no); - type ZoneGenericShortNames = datetime_marker_helper!(@names/zone/genericshort, no); + type ZoneExemplarCities = datetime_marker_helper!(@names/zone/exemplar, no); + type ZoneGenericLong = datetime_marker_helper!(@names/zone/generic_long, no); + type ZoneGenericShort = datetime_marker_helper!(@names/zone/generic_short, no); + type ZoneSpecificLong = datetime_marker_helper!(@names/zone/specific_long, no); + type ZoneSpecificShort = datetime_marker_helper!(@names/zone/specific_short, no); } impl TimeMarkers for NeoTimeComponents { @@ -1615,13 +1698,17 @@ impl DateTimeNamesMarker for NeoTimeZoneSkeleton { type WeekdayNames = datetime_marker_helper!(@names/weekday, no); type DayPeriodNames = datetime_marker_helper!(@names/dayperiod, no); type ZoneEssentials = datetime_marker_helper!(@names/zone/essentials, yes); - type ZoneGenericShortNames = datetime_marker_helper!(@names/zone/genericshort, yes); + type ZoneExemplarCities = datetime_marker_helper!(@names/zone/exemplar, yes); + type ZoneGenericLong = datetime_marker_helper!(@names/zone/generic_long, yes); + type ZoneGenericShort = datetime_marker_helper!(@names/zone/generic_short, yes); + type ZoneSpecificLong = datetime_marker_helper!(@names/zone/specific_long, yes); + type ZoneSpecificShort = datetime_marker_helper!(@names/zone/specific_short, yes); } impl ZoneMarkers for NeoTimeZoneSkeleton { type TimeZoneInput = datetime_marker_helper!(@input/timezone, yes); type ZoneEssentialsV1Marker = datetime_marker_helper!(@data/zone/essentials, yes); - type ZoneGenericShortNamesV1Marker = datetime_marker_helper!(@data/zone/genericshort, yes); + type ZoneGenericShortNamesV1Marker = datetime_marker_helper!(@data/zone/generic_short, yes); } impl TypedDateTimeMarkers for NeoTimeZoneSkeleton { @@ -1648,7 +1735,11 @@ impl DateTimeNamesMarker for NeoDateTimeComponents { type WeekdayNames = datetime_marker_helper!(@names/weekday, yes); type DayPeriodNames = datetime_marker_helper!(@names/dayperiod, yes); type ZoneEssentials = datetime_marker_helper!(@names/zone/essentials, no); - type ZoneGenericShortNames = datetime_marker_helper!(@names/zone/genericshort, no); + type ZoneExemplarCities = datetime_marker_helper!(@names/zone/exemplar, no); + type ZoneGenericLong = datetime_marker_helper!(@names/zone/generic_long, no); + type ZoneGenericShort = datetime_marker_helper!(@names/zone/generic_short, no); + type ZoneSpecificLong = datetime_marker_helper!(@names/zone/specific_long, no); + type ZoneSpecificShort = datetime_marker_helper!(@names/zone/specific_short, no); } impl TypedDateTimeMarkers for NeoDateTimeComponents { @@ -1674,8 +1765,12 @@ impl DateTimeNamesMarker for NeoComponents { type MonthNames = datetime_marker_helper!(@names/month, yes); type WeekdayNames = datetime_marker_helper!(@names/weekday, yes); type DayPeriodNames = datetime_marker_helper!(@names/dayperiod, yes); - type ZoneEssentials = datetime_marker_helper!(@names/zone/essentials, yes); - type ZoneGenericShortNames = datetime_marker_helper!(@names/zone/genericshort, yes); + type ZoneEssentials = datetime_marker_helper!(@names/zone/essentials, no); + type ZoneExemplarCities = datetime_marker_helper!(@names/zone/exemplar, no); + type ZoneGenericLong = datetime_marker_helper!(@names/zone/generic_long, no); + type ZoneGenericShort = datetime_marker_helper!(@names/zone/generic_short, no); + type ZoneSpecificLong = datetime_marker_helper!(@names/zone/specific_long, no); + type ZoneSpecificShort = datetime_marker_helper!(@names/zone/specific_short, no); } impl TypedDateTimeMarkers for NeoComponents { diff --git a/components/datetime/src/provider/date_time.rs b/components/datetime/src/provider/date_time.rs index acea905a090..5c362ecda97 100644 --- a/components/datetime/src/provider/date_time.rs +++ b/components/datetime/src/provider/date_time.rs @@ -5,7 +5,6 @@ //! Traits for managing data needed by [`TypedDateTimeFormatter`](crate::TypedDateTimeFormatter). use crate::fields; -use crate::fields::Field; use crate::input; use crate::options::{length, preferences, DateTimeFormatterOptions}; use crate::pattern::PatternError; @@ -19,13 +18,13 @@ use crate::provider::calendar::{ }; #[cfg(feature = "experimental")] use crate::provider::neo::SimpleSubstitutionPattern; +use crate::time_zone::TimeZoneDataPayloadsBorrowed; #[cfg(feature = "experimental")] -use crate::{options::components, provider::calendar::DateSkeletonPatternsV1Marker}; +use crate::{fields::Field, options::components, provider::calendar::DateSkeletonPatternsV1Marker}; use icu_calendar::types::Era; use icu_calendar::types::MonthCode; use icu_locale_core::extensions::unicode::Value; use icu_provider::prelude::*; -use icu_timezone::{MetazoneId, TimeZoneBcp47Id}; pub(crate) enum GetSymbolForMonthError { Missing, @@ -49,13 +48,6 @@ pub(crate) enum GetSymbolForDayPeriodError { MissingNames(Field), } -pub(crate) enum GetSymbolForTimeZoneError { - TypeTooNarrow, - #[cfg(feature = "experimental")] - Missing, - MissingNames(Field), -} - #[cfg(feature = "experimental")] pub(crate) enum UnsupportedOptionsOrDataError { UnsupportedOptions, @@ -577,20 +569,12 @@ impl<'data> TimeSymbols for provider::calendar::TimeSymbolsV1<'data> { } } -pub(crate) trait ZoneSymbols { - fn get_generic_short_for_zone( - &self, - metazone_id: MetazoneId, - time_zone_id: Option, - ) -> Result<&str, GetSymbolForTimeZoneError>; +pub(crate) trait ZoneSymbols<'data> { + fn get_payloads(&self) -> TimeZoneDataPayloadsBorrowed<'data>; } -impl ZoneSymbols for () { - fn get_generic_short_for_zone( - &self, - _: MetazoneId, - _: Option, - ) -> Result<&str, GetSymbolForTimeZoneError> { - Err(GetSymbolForTimeZoneError::TypeTooNarrow) +impl<'data> ZoneSymbols<'data> for () { + fn get_payloads(&self) -> TimeZoneDataPayloadsBorrowed<'data> { + TimeZoneDataPayloadsBorrowed::empty() } } diff --git a/components/datetime/src/time_zone.rs b/components/datetime/src/time_zone.rs index 35e14858134..4a602f9f4eb 100644 --- a/components/datetime/src/time_zone.rs +++ b/components/datetime/src/time_zone.rs @@ -169,19 +169,20 @@ pub(super) struct TimeZoneDataPayloads { /// A container contains all data payloads for CustomTimeZone (borrowed version). #[derive(Debug)] -pub(super) struct TimeZoneDataPayloadsBorrowed<'a> { +pub(crate) struct TimeZoneDataPayloadsBorrowed<'a> { /// The data that contains meta information about how to display content. - zone_formats: Option<&'a provider::time_zones::TimeZoneFormatsV1<'a>>, + pub(crate) zone_formats: Option<&'a provider::time_zones::TimeZoneFormatsV1<'a>>, /// The exemplar cities for time zones. - exemplar_cities: Option<&'a provider::time_zones::ExemplarCitiesV1<'a>>, + pub(crate) exemplar_cities: Option<&'a provider::time_zones::ExemplarCitiesV1<'a>>, /// The generic long metazone names, e.g. Pacific Time - mz_generic_long: Option<&'a provider::time_zones::MetazoneGenericNamesLongV1<'a>>, + pub(crate) mz_generic_long: Option<&'a provider::time_zones::MetazoneGenericNamesLongV1<'a>>, /// The generic short metazone names, e.g. PT - mz_generic_short: Option<&'a provider::time_zones::MetazoneGenericNamesShortV1<'a>>, + pub(crate) mz_generic_short: Option<&'a provider::time_zones::MetazoneGenericNamesShortV1<'a>>, /// The specific long metazone names, e.g. Pacific Daylight Time - mz_specific_long: Option<&'a provider::time_zones::MetazoneSpecificNamesLongV1<'a>>, + pub(crate) mz_specific_long: Option<&'a provider::time_zones::MetazoneSpecificNamesLongV1<'a>>, /// The specific short metazone names, e.g. Pacific Daylight Time - mz_specific_short: Option<&'a provider::time_zones::MetazoneSpecificNamesShortV1<'a>>, + pub(crate) mz_specific_short: + Option<&'a provider::time_zones::MetazoneSpecificNamesShortV1<'a>>, } impl TimeZoneDataPayloads { @@ -197,6 +198,19 @@ impl TimeZoneDataPayloads { } } +impl<'a> TimeZoneDataPayloadsBorrowed<'a> { + pub(crate) fn empty() -> Self { + TimeZoneDataPayloadsBorrowed { + zone_formats: None, + exemplar_cities: None, + mz_generic_long: None, + mz_generic_short: None, + mz_specific_long: None, + mz_specific_short: None, + } + } +} + impl TimeZoneFormatter { /// Constructor that selectively loads data based on what is required to /// format the given pattern into the given locale. diff --git a/components/timezone/src/time_zone.rs b/components/timezone/src/time_zone.rs index be42efd88c7..99b087725dd 100644 --- a/components/timezone/src/time_zone.rs +++ b/components/timezone/src/time_zone.rs @@ -70,7 +70,7 @@ impl CustomTimeZone { } } - /// Creates a new [`CustomTimeZone`] with the GMT offset set to UTC. + /// Creates a new [`CustomTimeZone`] with the GMT offset set to 0. /// /// All other fields are left empty. pub const fn utc() -> Self { @@ -84,6 +84,9 @@ impl CustomTimeZone { /// Creates a new [`CustomTimeZone`] representing Greenwich Mean Time /// (London Time as observed in the winter). + /// + /// This is the same local time as UTC, but there are more + /// localizations available. pub const fn gmt() -> Self { Self { gmt_offset: Some(GmtOffset::utc()), @@ -93,17 +96,6 @@ impl CustomTimeZone { } } - /// Creates a new [`CustomTimeZone`] representing British Summer Time - /// (London Time as observed in the summer). - pub const fn bst() -> Self { - Self { - gmt_offset: Some(GmtOffset::utc_plus_1()), - time_zone_id: Some(TimeZoneBcp47Id(tinystr!(8, "gblon"))), - metazone_id: Some(MetazoneId(tinystr!(4, "mgmt"))), - zone_variant: Some(ZoneVariant::daylight()), - } - } - /// Parse a [`CustomTimeZone`] from a UTF-8 string representing a GMT Offset. See also [`GmtOffset`]. /// /// diff --git a/components/timezone/src/types.rs b/components/timezone/src/types.rs index 8a59958c10a..eb227664361 100644 --- a/components/timezone/src/types.rs +++ b/components/timezone/src/types.rs @@ -38,10 +38,6 @@ impl GmtOffset { Self(0) } - pub(crate) const fn utc_plus_1() -> Self { - Self(3600) - } - /// Parse a [`GmtOffset`] from bytes. /// /// The offset must range from GMT-12 to GMT+14. diff --git a/ffi/capi/bindings/c/ICU4XCustomTimeZone.h b/ffi/capi/bindings/c/ICU4XCustomTimeZone.h index fb22990a756..b1c7e4fe68d 100644 --- a/ffi/capi/bindings/c/ICU4XCustomTimeZone.h +++ b/ffi/capi/bindings/c/ICU4XCustomTimeZone.h @@ -29,8 +29,6 @@ ICU4XCustomTimeZone* ICU4XCustomTimeZone_create_utc(); ICU4XCustomTimeZone* ICU4XCustomTimeZone_create_gmt(); -ICU4XCustomTimeZone* ICU4XCustomTimeZone_create_bst(); - typedef struct ICU4XCustomTimeZone_try_set_gmt_offset_seconds_result {union { ICU4XTimeZoneInvalidOffsetError err;}; bool is_ok;} ICU4XCustomTimeZone_try_set_gmt_offset_seconds_result; ICU4XCustomTimeZone_try_set_gmt_offset_seconds_result ICU4XCustomTimeZone_try_set_gmt_offset_seconds(ICU4XCustomTimeZone* self, int32_t offset_seconds); diff --git a/ffi/capi/bindings/cpp/ICU4XCustomTimeZone.d.hpp b/ffi/capi/bindings/cpp/ICU4XCustomTimeZone.d.hpp index 61e184c231d..9d93a8b1d15 100644 --- a/ffi/capi/bindings/cpp/ICU4XCustomTimeZone.d.hpp +++ b/ffi/capi/bindings/cpp/ICU4XCustomTimeZone.d.hpp @@ -33,8 +33,6 @@ class ICU4XCustomTimeZone { inline static std::unique_ptr create_gmt(); - inline static std::unique_ptr create_bst(); - inline diplomat::result try_set_gmt_offset_seconds(int32_t offset_seconds); inline void clear_gmt_offset(); diff --git a/ffi/capi/bindings/cpp/ICU4XCustomTimeZone.hpp b/ffi/capi/bindings/cpp/ICU4XCustomTimeZone.hpp index a753ae8ec89..129fe739299 100644 --- a/ffi/capi/bindings/cpp/ICU4XCustomTimeZone.hpp +++ b/ffi/capi/bindings/cpp/ICU4XCustomTimeZone.hpp @@ -29,8 +29,6 @@ namespace capi { ICU4XCustomTimeZone* ICU4XCustomTimeZone_create_gmt(); - ICU4XCustomTimeZone* ICU4XCustomTimeZone_create_bst(); - typedef struct ICU4XCustomTimeZone_try_set_gmt_offset_seconds_result {union { ICU4XTimeZoneInvalidOffsetError err;}; bool is_ok;} ICU4XCustomTimeZone_try_set_gmt_offset_seconds_result; ICU4XCustomTimeZone_try_set_gmt_offset_seconds_result ICU4XCustomTimeZone_try_set_gmt_offset_seconds(ICU4XCustomTimeZone* self, int32_t offset_seconds); @@ -117,11 +115,6 @@ inline std::unique_ptr ICU4XCustomTimeZone::create_gmt() { return std::unique_ptr(ICU4XCustomTimeZone::FromFFI(result)); } -inline std::unique_ptr ICU4XCustomTimeZone::create_bst() { - auto result = capi::ICU4XCustomTimeZone_create_bst(); - return std::unique_ptr(ICU4XCustomTimeZone::FromFFI(result)); -} - inline diplomat::result ICU4XCustomTimeZone::try_set_gmt_offset_seconds(int32_t offset_seconds) { auto result = capi::ICU4XCustomTimeZone_try_set_gmt_offset_seconds(this->AsFFI(), offset_seconds); diff --git a/ffi/capi/bindings/dart/CustomTimeZone.g.dart b/ffi/capi/bindings/dart/CustomTimeZone.g.dart index 35a06863958..574cc97a526 100644 --- a/ffi/capi/bindings/dart/CustomTimeZone.g.dart +++ b/ffi/capi/bindings/dart/CustomTimeZone.g.dart @@ -46,7 +46,7 @@ final class CustomTimeZone implements ffi.Finalizable { return CustomTimeZone._fromFfi(result, []); } - /// Creates a time zone for UTC. + /// Creates a time zone for UTC (Coordinated Universal Time). /// /// See the [Rust documentation for `utc`](https://docs.rs/icu/latest/icu/timezone/struct.CustomTimeZone.html#method.utc) for more information. factory CustomTimeZone.utc() { @@ -54,7 +54,7 @@ final class CustomTimeZone implements ffi.Finalizable { return CustomTimeZone._fromFfi(result, []); } - /// Creates a time zone for GMT (London winter time). + /// Creates a time zone for GMT (Greenwich Mean Time). /// /// See the [Rust documentation for `gmt`](https://docs.rs/icu/latest/icu/timezone/struct.CustomTimeZone.html#method.gmt) for more information. factory CustomTimeZone.gmt() { @@ -62,14 +62,6 @@ final class CustomTimeZone implements ffi.Finalizable { return CustomTimeZone._fromFfi(result, []); } - /// Creates a time zone for BST (London summer time). - /// - /// See the [Rust documentation for `bst`](https://docs.rs/icu/latest/icu/timezone/struct.CustomTimeZone.html#method.bst) for more information. - factory CustomTimeZone.bst() { - final result = _ICU4XCustomTimeZone_create_bst(); - return CustomTimeZone._fromFfi(result, []); - } - /// Sets the `gmt_offset` field from offset seconds. /// /// Errors if the offset seconds are out of range. @@ -395,11 +387,6 @@ external ffi.Pointer _ICU4XCustomTimeZone_create_utc(); // ignore: non_constant_identifier_names external ffi.Pointer _ICU4XCustomTimeZone_create_gmt(); -@meta.ResourceIdentifier('ICU4XCustomTimeZone_create_bst') -@ffi.Native Function()>(isLeaf: true, symbol: 'ICU4XCustomTimeZone_create_bst') -// ignore: non_constant_identifier_names -external ffi.Pointer _ICU4XCustomTimeZone_create_bst(); - @meta.ResourceIdentifier('ICU4XCustomTimeZone_try_set_gmt_offset_seconds') @ffi.Native<_ResultVoidInt32 Function(ffi.Pointer, ffi.Int32)>(isLeaf: true, symbol: 'ICU4XCustomTimeZone_try_set_gmt_offset_seconds') // ignore: non_constant_identifier_names diff --git a/ffi/capi/bindings/js/ICU4XCustomTimeZone.d.ts b/ffi/capi/bindings/js/ICU4XCustomTimeZone.d.ts index e43734eddb5..8385f0d8ca2 100644 --- a/ffi/capi/bindings/js/ICU4XCustomTimeZone.d.ts +++ b/ffi/capi/bindings/js/ICU4XCustomTimeZone.d.ts @@ -31,7 +31,7 @@ export class ICU4XCustomTimeZone { /** - * Creates a time zone for UTC. + * Creates a time zone for UTC (Coordinated Universal Time). * See the {@link https://docs.rs/icu/latest/icu/timezone/struct.CustomTimeZone.html#method.utc Rust documentation for `utc`} for more information. */ @@ -39,20 +39,12 @@ export class ICU4XCustomTimeZone { /** - * Creates a time zone for GMT (London winter time). + * Creates a time zone for GMT (Greenwich Mean Time). * See the {@link https://docs.rs/icu/latest/icu/timezone/struct.CustomTimeZone.html#method.gmt Rust documentation for `gmt`} for more information. */ static create_gmt(): ICU4XCustomTimeZone; - /** - - * Creates a time zone for BST (London summer time). - - * See the {@link https://docs.rs/icu/latest/icu/timezone/struct.CustomTimeZone.html#method.bst Rust documentation for `bst`} for more information. - */ - static create_bst(): ICU4XCustomTimeZone; - /** * Sets the `gmt_offset` field from offset seconds. diff --git a/ffi/capi/bindings/js/ICU4XCustomTimeZone.mjs b/ffi/capi/bindings/js/ICU4XCustomTimeZone.mjs index 939b81975a0..3671c60efde 100644 --- a/ffi/capi/bindings/js/ICU4XCustomTimeZone.mjs +++ b/ffi/capi/bindings/js/ICU4XCustomTimeZone.mjs @@ -49,10 +49,6 @@ export class ICU4XCustomTimeZone { return new ICU4XCustomTimeZone(wasm.ICU4XCustomTimeZone_create_gmt(), true, []); } - static create_bst() { - return new ICU4XCustomTimeZone(wasm.ICU4XCustomTimeZone_create_bst(), true, []); - } - try_set_gmt_offset_seconds(arg_offset_seconds) { return (() => { const diplomat_receive_buffer = wasm.diplomat_alloc(5, 4); diff --git a/ffi/capi/src/timezone.rs b/ffi/capi/src/timezone.rs index 774017951ba..a372b90f5dd 100644 --- a/ffi/capi/src/timezone.rs +++ b/ffi/capi/src/timezone.rs @@ -42,7 +42,7 @@ pub mod ffi { Box::new(CustomTimeZone::new_empty().into()) } - /// Creates a time zone for UTC. + /// Creates a time zone for UTC (Coordinated Universal Time). #[diplomat::rust_link(icu::timezone::CustomTimeZone::utc, FnInStruct)] #[diplomat::rust_link(icu::timezone::GmtOffset::utc, FnInStruct, hidden)] #[diplomat::attr(all(supports = constructors, supports = fallible_constructors, supports = named_constructors), named_constructor = "utc")] @@ -50,20 +50,13 @@ pub mod ffi { Box::new(CustomTimeZone::utc().into()) } - /// Creates a time zone for GMT (London winter time). + /// Creates a time zone for GMT (Greenwich Mean Time). #[diplomat::rust_link(icu::timezone::CustomTimeZone::gmt, FnInStruct)] #[diplomat::attr(all(supports = constructors, supports = fallible_constructors, supports = named_constructors), named_constructor = "gmt")] pub fn create_gmt() -> Box { Box::new(CustomTimeZone::gmt().into()) } - /// Creates a time zone for BST (London summer time). - #[diplomat::rust_link(icu::timezone::CustomTimeZone::bst, FnInStruct)] - #[diplomat::attr(all(supports = constructors, supports = fallible_constructors, supports = named_constructors), named_constructor = "bst")] - pub fn create_bst() -> Box { - Box::new(CustomTimeZone::bst().into()) - } - /// Sets the `gmt_offset` field from offset seconds. /// /// Errors if the offset seconds are out of range. diff --git a/provider/core/src/response.rs b/provider/core/src/response.rs index 1eff44716f8..a0924889e9a 100644 --- a/provider/core/src/response.rs +++ b/provider/core/src/response.rs @@ -840,6 +840,16 @@ where ))) } + /// Returns whether this object represents a [`DataPayload`]. + #[inline] + pub fn is_payload(&self) -> bool { + match &self.0 { + DataPayloadOrInner::Yoke(_) => true, + DataPayloadOrInner::Inner(DataPayloadOrInnerInner::StaticRef(_)) => true, + DataPayloadOrInner::Inner(DataPayloadOrInnerInner::Other(_)) => false, + } + } + /// Gets the value from this [`DataPayload`] as `Ok` or the other type as `Err`. #[allow(clippy::needless_lifetimes)] #[inline] @@ -867,6 +877,24 @@ where } } +impl DataPayloadOr +where + M: DynamicDataMarker, +{ + /// Convenience function to return the other type with value `()` + #[inline] + pub fn none() -> Self { + Self::from_other(()) + } + + /// Convenience function to return `Some` or `None` for other type `()` + #[allow(clippy::needless_lifetimes)] + #[inline] + pub fn get_option<'a>(&'a self) -> Option<&'a >::Output> { + self.get().ok() + } +} + /// A response object containing an object as payload and metadata about it. #[allow(clippy::exhaustive_structs)] // this type is stable pub struct DataResponse diff --git a/utils/yoke/src/macro_impls.rs b/utils/yoke/src/macro_impls.rs index b8a6d8729ea..4e17db9120b 100644 --- a/utils/yoke/src/macro_impls.rs +++ b/utils/yoke/src/macro_impls.rs @@ -36,7 +36,7 @@ macro_rules! copy_yoke_impl { }; } macro_rules! impl_copy_type { - ($ty:ident) => { + ($ty:ty) => { // Safety: all the types that this macro is used to generate impls of Yokeable for do not // borrow any memory. unsafe impl<'a> Yokeable<'a> for $ty { @@ -46,6 +46,7 @@ macro_rules! impl_copy_type { }; } +impl_copy_type!(()); impl_copy_type!(u8); impl_copy_type!(u16); impl_copy_type!(u32);