From 121b0524a9789ccd9d6086f79ca2ecfcdc985fe9 Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Thu, 11 Aug 2022 17:10:09 -0700 Subject: [PATCH 01/17] icu_datetime building with skeletons as experimental --- components/datetime/Cargo.toml | 1 + components/datetime/src/any/date.rs | 1 - components/datetime/src/any/datetime.rs | 91 ++++++++++++++++-- components/datetime/src/any/zoned_datetime.rs | 93 ++++++++++++++++++- components/datetime/src/datetime.rs | 60 +++++++++++- components/datetime/src/error.rs | 3 + components/datetime/src/lib.rs | 1 + components/datetime/src/options/components.rs | 3 + components/datetime/src/options/mod.rs | 5 + .../datetime/src/provider/calendar/mod.rs | 2 + components/datetime/src/provider/date_time.rs | 37 +++++++- components/datetime/src/raw/datetime.rs | 25 ++--- components/datetime/src/raw/zoned_datetime.rs | 11 +-- components/datetime/src/zoned_datetime.rs | 64 ++++++++++++- 14 files changed, 349 insertions(+), 48 deletions(-) diff --git a/components/datetime/Cargo.toml b/components/datetime/Cargo.toml index 9a4d2502c71..cf77faafaca 100644 --- a/components/datetime/Cargo.toml +++ b/components/datetime/Cargo.toml @@ -72,6 +72,7 @@ bench = false # This option is required for Benchmark CI std = ["icu_provider/std", "icu_locid/std", "icu_calendar/std"] default = [] bench = ["serde"] +experimental = [] serde = ["dep:serde", "litemap/serde", "zerovec/serde", "tinystr/serde", "smallvec/serde", "icu_calendar/serde", "icu_decimal/serde", "icu_provider/serde", "icu_plurals/serde", "icu_timezone/serde"] datagen = ["serde", "icu_calendar/datagen", "icu_timezone/datagen", "icu_provider/datagen", "std", "databake"] diff --git a/components/datetime/src/any/date.rs b/components/datetime/src/any/date.rs index 87571f3a2cb..33a3df403ff 100644 --- a/components/datetime/src/any/date.rs +++ b/components/datetime/src/any/date.rs @@ -170,7 +170,6 @@ impl DateFormatter { where P: DataProvider + DataProvider - + DataProvider + DataProvider + DataProvider + DataProvider diff --git a/components/datetime/src/any/datetime.rs b/components/datetime/src/any/datetime.rs index 211aa778dea..090f79b33c7 100644 --- a/components/datetime/src/any/datetime.rs +++ b/components/datetime/src/any/datetime.rs @@ -2,18 +2,14 @@ // called LICENSE at the top level of the ICU4X source tree // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). -use crate::{ - calendar, - options::{components, DateTimeFormatterOptions}, - raw, DateFormatter, TimeFormatter, -}; +use crate::{calendar, options::DateTimeFormatterOptions, raw, DateFormatter, TimeFormatter}; use alloc::string::String; use icu_locid::{extensions_unicode_key as key, extensions_unicode_value as value}; use icu_provider::prelude::*; -use crate::provider::{calendar::*, week_data::WeekDataV1Marker}; +use crate::provider::{calendar::*, week_data::WeekDataV1Marker, date_time::PatternSelector}; use crate::{input::DateTimeInput, DateTimeFormatterError, FormattedDateTime}; use icu_calendar::any_calendar::{AnyCalendar, AnyCalendarKind}; use icu_calendar::provider::{JapaneseErasV1Marker, JapaneseExtendedErasV1Marker}; @@ -212,6 +208,7 @@ impl DateTimeFormatter { /// let value = dtf.format_to_string(&any_datetime).expect("calendars should match"); /// assert_eq!(value, "Sep 1, 2020, 12:34 PM"); /// ``` + #[cfg(feature = "experimental")] #[inline(never)] pub fn try_new_unstable

( data_provider: &P, @@ -221,7 +218,7 @@ impl DateTimeFormatter { where P: DataProvider + DataProvider - + DataProvider + + DataProvider + DataProvider + DataProvider + DataProvider @@ -262,10 +259,87 @@ impl DateTimeFormatter { let calendar = AnyCalendar::try_new_unstable(data_provider, kind)?; + let patterns = PatternSelector::for_options( + data_provider, + calendar::load_lengths_for_any_calendar_kind(data_provider, locale, kind)?, + &locale, + &options, + )?; + + Ok(Self( + raw::DateTimeFormatter::try_new( + data_provider, + patterns, + || calendar::load_symbols_for_any_calendar_kind(data_provider, locale, kind), + locale_with_cal, + options, + )?, + calendar, + )) + } + + // No docs because the "experimental" version is what docs use + #[cfg(not(feature = "experimental"))] + #[inline(never)] + pub fn try_new_unstable

( + data_provider: &P, + locale: &DataLocale, + options: DateTimeFormatterOptions, + ) -> Result + where + P: DataProvider + + DataProvider + + DataProvider + + DataProvider + + DataProvider + + DataProvider + + DataProvider + + DataProvider + + DataProvider + + DataProvider + + DataProvider + + DataProvider + + DataProvider + + DataProvider + + DataProvider + + DataProvider + + DataProvider + + DataProvider + + DataProvider + + DataProvider + + DataProvider + + ?Sized, + { + // TODO(#2188): Avoid cloning the DataLocale by passing the calendar + // separately into the raw formatter. + let mut locale_with_cal = locale.clone(); + + // TODO (#2038), DO NOT SHIP 1.0 without fixing this + let kind = if let Ok(kind) = AnyCalendarKind::from_data_locale(&locale_with_cal) { + kind + } else { + locale_with_cal.set_unicode_ext(key!("ca"), value!("gregory")); + AnyCalendarKind::Gregorian + }; + + // We share data under ethiopic + if kind == AnyCalendarKind::Ethioaa { + locale_with_cal.set_unicode_ext(key!("ca"), value!("ethiopic")); + } + + let calendar = AnyCalendar::try_new_unstable(data_provider, kind)?; + + let patterns = PatternSelector::for_options( + data_provider, + calendar::load_lengths_for_any_calendar_kind(data_provider, locale, kind)?, + &locale, + &options, + )?; + Ok(Self( raw::DateTimeFormatter::try_new( data_provider, - calendar::load_lengths_for_any_calendar_kind(data_provider, locale, kind)?, + patterns, || calendar::load_symbols_for_any_calendar_kind(data_provider, locale, kind), locale_with_cal, options, @@ -415,6 +489,7 @@ where { /// /// assert_eq!(dtf.resolve_components(), expected_components_bag); /// ``` + #[cfg(feature = "experimental")] pub fn resolve_components(&self) -> components::Bag { self.0.resolve_components() } diff --git a/components/datetime/src/any/zoned_datetime.rs b/components/datetime/src/any/zoned_datetime.rs index be488377ba7..1b1341bfdc8 100644 --- a/components/datetime/src/any/zoned_datetime.rs +++ b/components/datetime/src/any/zoned_datetime.rs @@ -10,7 +10,7 @@ use icu_locid::{extensions_unicode_key as key, extensions_unicode_value as value use icu_provider::prelude::*; use crate::input::{DateTimeInput, ExtractedDateTimeInput, TimeZoneInput}; -use crate::provider::{self, calendar::*, week_data::WeekDataV1Marker}; +use crate::provider::{self, calendar::*, week_data::WeekDataV1Marker, date_time::PatternSelector}; use crate::time_zone::TimeZoneFormatterOptions; use crate::{DateTimeFormatterError, FormattedZonedDateTime}; use icu_calendar::any_calendar::{AnyCalendar, AnyCalendarKind}; @@ -110,6 +110,7 @@ impl ZonedDateTimeFormatter { /// ``` /// /// [data provider]: icu_provider + #[cfg(feature = "experimental")] #[inline] #[allow(clippy::too_many_arguments)] pub fn try_new_unstable

( @@ -121,7 +122,7 @@ impl ZonedDateTimeFormatter { where P: DataProvider + DataProvider - + DataProvider + + DataProvider + DataProvider + DataProvider + DataProvider @@ -168,10 +169,96 @@ impl ZonedDateTimeFormatter { let calendar = AnyCalendar::try_new_unstable(provider, kind)?; + let patterns = PatternSelector::for_options( + provider, + calendar::load_lengths_for_any_calendar_kind(provider, locale, kind)?, + &locale, + &date_time_format_options, + )?; + + Ok(Self( + raw::ZonedDateTimeFormatter::try_new( + provider, + patterns, + || calendar::load_symbols_for_any_calendar_kind(provider, locale, kind), + locale_with_cal, + date_time_format_options, + time_zone_format_options, + )?, + calendar, + )) + } + + // No docs because the "experimental" version is what docs use + #[cfg(not(feature = "experimental"))] + #[inline] + #[allow(clippy::too_many_arguments)] + pub fn try_new_unstable

( + provider: &P, + locale: &DataLocale, + date_time_format_options: DateTimeFormatterOptions, + time_zone_format_options: TimeZoneFormatterOptions, + ) -> Result + where + P: DataProvider + + DataProvider + + DataProvider + + DataProvider + + DataProvider + + DataProvider + + DataProvider + + DataProvider + + DataProvider + + DataProvider + + DataProvider + + DataProvider + + DataProvider + + DataProvider + + DataProvider + + DataProvider + + DataProvider + + DataProvider + + DataProvider + + DataProvider + + DataProvider + + DataProvider + + DataProvider + + DataProvider + + DataProvider + + DataProvider + + DataProvider + + ?Sized, + { + // TODO(#2188): Avoid cloning the DataLocale by passing the calendar + // separately into the raw formatter. + let mut locale_with_cal = locale.clone(); + + // TODO (#2038), DO NOT SHIP 1.0 without fixing this + let kind = if let Ok(kind) = AnyCalendarKind::from_data_locale(&locale_with_cal) { + kind + } else { + locale_with_cal.set_unicode_ext(key!("ca"), value!("gregory")); + AnyCalendarKind::Gregorian + }; + + // We share data under ethiopic + if kind == AnyCalendarKind::Ethioaa { + locale_with_cal.set_unicode_ext(key!("ca"), value!("ethiopic")); + } + + let calendar = AnyCalendar::try_new_unstable(provider, kind)?; + + let patterns = PatternSelector::for_options( + provider, + calendar::load_lengths_for_any_calendar_kind(provider, locale, kind)?, + &locale, + &date_time_format_options, + )?; + Ok(Self( raw::ZonedDateTimeFormatter::try_new( provider, - calendar::load_lengths_for_any_calendar_kind(provider, locale, kind)?, + patterns, || calendar::load_symbols_for_any_calendar_kind(provider, locale, kind), locale_with_cal, date_time_format_options, diff --git a/components/datetime/src/datetime.rs b/components/datetime/src/datetime.rs index 0354349643a..a3dbbdd6126 100644 --- a/components/datetime/src/datetime.rs +++ b/components/datetime/src/datetime.rs @@ -6,8 +6,9 @@ //! Central to this is the [`TypedDateTimeFormatter`]. use crate::{ - options::{components, length, preferences, DateTimeFormatterOptions}, - provider::calendar::{DateSkeletonPatternsV1Marker, TimeLengthsV1Marker, TimeSymbolsV1Marker}, + options::{length, preferences, DateTimeFormatterOptions}, + provider::calendar::{TimeLengthsV1Marker, TimeSymbolsV1Marker}, + provider::date_time::PatternSelector, provider::week_data::WeekDataV1Marker, raw, }; @@ -485,6 +486,7 @@ where { /// ``` /// /// [data provider]: icu_provider + #[cfg(feature = "experimental")] #[inline] pub fn try_new_unstable( data_provider: &D, @@ -496,7 +498,7 @@ where { + DataProvider<::DateLengthsV1Marker> + DataProvider + DataProvider - + DataProvider + + DataProvider + DataProvider + DataProvider + DataProvider @@ -507,10 +509,57 @@ where { let mut locale_with_cal = locale.clone(); calendar::potentially_fixup_calendar::(&mut locale_with_cal)?; + let patterns = PatternSelector::for_options( + data_provider, + calendar::load_lengths_for_cldr_calendar::(data_provider, locale)?, + &locale, + &options, + )?; Ok(Self( raw::DateTimeFormatter::try_new( data_provider, - calendar::load_lengths_for_cldr_calendar::(data_provider, locale)?, + patterns, + || calendar::load_symbols_for_cldr_calendar::(data_provider, locale), + locale_with_cal, + options, + )?, + PhantomData, + )) + } + + // No docs because the "experimental" version is what docs use + #[cfg(not(feature = "experimental"))] + #[inline] + pub fn try_new_unstable( + data_provider: &D, + locale: &DataLocale, + options: DateTimeFormatterOptions, + ) -> Result + where + D: DataProvider<::DateSymbolsV1Marker> + + DataProvider<::DateLengthsV1Marker> + + DataProvider + + DataProvider + + DataProvider + + DataProvider + + DataProvider + + ?Sized, + { + // TODO(#2188): Avoid cloning the DataLocale by passing the calendar + // separately into the raw formatter. + let mut locale_with_cal = locale.clone(); + + calendar::potentially_fixup_calendar::(&mut locale_with_cal)?; + let patterns = PatternSelector::for_options( + data_provider, + calendar::load_lengths_for_cldr_calendar::(data_provider, locale)?, + &locale, + &options, + )?; + Ok(Self( + raw::DateTimeFormatter::try_new( + data_provider, + patterns, || calendar::load_symbols_for_cldr_calendar::(data_provider, locale), locale_with_cal, options, @@ -644,7 +693,8 @@ where { /// /// assert_eq!(dtf.resolve_components(), expected_components_bag); /// ``` - pub fn resolve_components(&self) -> components::Bag { + #[cfg(feature = "experimental")] + pub fn resolve_components(&self) -> crate::options::components::Bag { self.0.resolve_components() } } diff --git a/components/datetime/src/error.rs b/components/datetime/src/error.rs index 62e29b7375c..4daa0ec8fa9 100644 --- a/components/datetime/src/error.rs +++ b/components/datetime/src/error.rs @@ -5,6 +5,7 @@ use crate::fields::FieldSymbol; use crate::input::DateTimeError; use crate::pattern::PatternError; +#[cfg(feature = "experimental")] use crate::skeleton::SkeletonError; use displaydoc::Display; use icu_calendar::any_calendar::AnyCalendarKind; @@ -33,6 +34,7 @@ pub enum DateTimeFormatterError { MissingInputField(Option<&'static str>), /// An error originating from skeleton matching. #[displaydoc("{0}")] + #[cfg(feature = "experimental")] Skeleton(SkeletonError), /// An error originating from an unsupported field in a datetime format. #[displaydoc("Unsupported field: {0:?}")] @@ -89,6 +91,7 @@ impl From for DateTimeFormatterError { } } +#[cfg(feature = "experimental")] impl From for DateTimeFormatterError { fn from(e: SkeletonError) -> Self { DateTimeFormatterError::Skeleton(e) diff --git a/components/datetime/src/lib.rs b/components/datetime/src/lib.rs index c5db25bd4fc..95a141c0072 100644 --- a/components/datetime/src/lib.rs +++ b/components/datetime/src/lib.rs @@ -120,6 +120,7 @@ pub mod provider; pub(crate) mod raw; #[doc(hidden)] #[allow(clippy::exhaustive_structs, clippy::exhaustive_enums)] // private-ish module +#[cfg(feature = "experimental")] pub mod skeleton; #[allow(missing_docs)] // TODO(#686) - Add missing docs. pub mod time_zone; diff --git a/components/datetime/src/options/components.rs b/components/datetime/src/options/components.rs index fb5879bca80..7bab67e1810 100644 --- a/components/datetime/src/options/components.rs +++ b/components/datetime/src/options/components.rs @@ -4,6 +4,9 @@ //! # Implementation status //! +//! This module is available by enabling the `"experimental"` feature. It may change in breaking +//! ways, including across minor releases. +//! //! This is currently only a partial implementation of the UTS-35 skeleton matching algorithm. //! //! | Algorithm step | Status | diff --git a/components/datetime/src/options/mod.rs b/components/datetime/src/options/mod.rs index 45e88df02a4..495848781da 100644 --- a/components/datetime/src/options/mod.rs +++ b/components/datetime/src/options/mod.rs @@ -23,6 +23,7 @@ //! At the moment only the [`length::Bag`] works, and we plan to extend that to support //! `ECMA402`-like components bag later. +#[cfg(feature = "experimental")] pub mod components; pub mod length; pub mod preferences; @@ -49,6 +50,9 @@ pub enum DateTimeFormatterOptions { /// Bag of lengths for date and time. Length(length::Bag), /// Bag of components describing which fields and how should be displayed. + /// + /// Enabled with the `"experimental"` feature. This option is subject to breaking changes. + #[cfg(feature = "experimental")] Components(components::Bag), } @@ -64,6 +68,7 @@ impl From for DateTimeFormatterOptions { } } +#[cfg(feature = "experimental")] impl From for DateTimeFormatterOptions { fn from(input: components::Bag) -> Self { Self::Components(input) diff --git a/components/datetime/src/provider/calendar/mod.rs b/components/datetime/src/provider/calendar/mod.rs index 12d6c158681..e5dbb66f974 100644 --- a/components/datetime/src/provider/calendar/mod.rs +++ b/components/datetime/src/provider/calendar/mod.rs @@ -6,12 +6,14 @@ #![allow(missing_docs)] // TODO(#686) - Add missing docs. +#[cfg(feature = "experimental")] mod skeletons; mod symbols; use crate::pattern; use icu_provider::prelude::*; use icu_provider::{yoke, zerofrom}; +#[cfg(feature = "experimental")] pub use skeletons::*; pub use symbols::*; diff --git a/components/datetime/src/provider/date_time.rs b/components/datetime/src/provider/date_time.rs index 75f38eb8643..2a0e785597a 100644 --- a/components/datetime/src/provider/date_time.rs +++ b/components/datetime/src/provider/date_time.rs @@ -5,16 +5,15 @@ use crate::error::DateTimeFormatterError; use crate::fields; use crate::input; -use crate::options::{components, length, preferences, DateTimeFormatterOptions}; +use crate::options::{length, preferences, DateTimeFormatterOptions}; use crate::pattern::{hour_cycle, runtime::PatternPlurals}; use crate::provider; use crate::provider::calendar::patterns::PatternPluralsV1; use crate::provider::calendar::{ patterns::GenericPatternV1Marker, patterns::PatternPluralsFromPatternsV1Marker, - DateSkeletonPatternsV1Marker, ErasedDateLengthsV1Marker, TimeLengthsV1Marker, + ErasedDateLengthsV1Marker, TimeLengthsV1Marker, }; use crate::provider::calendar::{DateLengthsV1, TimeLengthsV1}; -use crate::skeleton; use icu_calendar::types::{Era, MonthCode}; use icu_provider::prelude::*; @@ -135,8 +134,9 @@ pub struct PatternSelector<'a, D: ?Sized> { impl PatternSelector<'_, D> where - D: DataProvider + DataProvider + ?Sized, + D: DataProvider + ?Sized, { + #[cfg(not(feature = "experimental"))] pub(crate) fn for_options<'a>( data_provider: &'a D, date_patterns_data: DataPayload, @@ -151,6 +151,7 @@ where match options { DateTimeFormatterOptions::Length(bag) => selector .pattern_for_length_bag(bag, Some(preferences::Bag::from_data_locale(locale))), + #[cfg(feature = "experimental")] DateTimeFormatterOptions::Components(bag) => selector.patterns_for_components_bag(bag), } } @@ -210,12 +211,39 @@ where Ok(PatternPlurals::from(pattern.combined(date, time)?).into()) }) } +} + +#[cfg(feature = "experimental")] +impl PatternSelector<'_, D> +where + D: DataProvider + + DataProvider + + ?Sized, +{ + pub(crate) fn for_options<'a>( + data_provider: &'a D, + date_patterns_data: DataPayload, + locale: &'a DataLocale, + options: &DateTimeFormatterOptions, + ) -> Result> { + let selector = PatternSelector { + data_provider, + date_patterns_data, + locale, + }; + match options { + DateTimeFormatterOptions::Length(bag) => selector + .pattern_for_length_bag(bag, Some(preferences::Bag::from_data_locale(locale))), + DateTimeFormatterOptions::Components(bag) => selector.patterns_for_components_bag(bag), + } + } /// Determine the appropriate `PatternPlurals` for a given `options::components::Bag`. fn patterns_for_components_bag( self, components: &components::Bag, ) -> Result> { + use crate::skeleton; let skeletons_data = self.skeleton_data_payload()?; // Not all skeletons are currently supported. let requested_fields = components.to_vec_fields(); @@ -236,6 +264,7 @@ where ))) } + #[cfg(feature = "experimental")] fn skeleton_data_payload(&self) -> Result> { let data = self .data_provider diff --git a/components/datetime/src/raw/datetime.rs b/components/datetime/src/raw/datetime.rs index dcbf146c312..81ae80a6d1c 100644 --- a/components/datetime/src/raw/datetime.rs +++ b/components/datetime/src/raw/datetime.rs @@ -8,16 +8,17 @@ use crate::{ format::datetime, input::{DateInput, DateTimeInput, ExtractedDateTimeInput, IsoTimeInput}, - options::components, options::{length, preferences, DateTimeFormatterOptions}, pattern::runtime::PatternPlurals, - provider, - provider::calendar::{ - patterns::GenericPatternV1Marker, patterns::PatternPluralsFromPatternsV1Marker, - DateSkeletonPatternsV1Marker, ErasedDateLengthsV1Marker, ErasedDateSymbolsV1Marker, - TimeLengthsV1Marker, TimeSymbolsV1Marker, + provider::{ + self, + calendar::{ + patterns::GenericPatternV1Marker, patterns::PatternPluralsFromPatternsV1Marker, + ErasedDateLengthsV1Marker, ErasedDateSymbolsV1Marker, TimeLengthsV1Marker, + TimeSymbolsV1Marker, + }, + week_data::WeekDataV1Marker, }, - provider::week_data::WeekDataV1Marker, DateTimeFormatterError, FormattedDateTime, }; use alloc::string::String; @@ -383,7 +384,7 @@ impl DateTimeFormatter { #[inline(never)] pub fn try_new( data_provider: &D, - patterns_data: DataPayload, + patterns: DataPayload, symbols_data_fn: impl FnOnce() -> Result, DataError>, mut locale: DataLocale, options: DateTimeFormatterOptions, @@ -391,7 +392,6 @@ impl DateTimeFormatter { where D: DataProvider + DataProvider - + DataProvider + DataProvider + DataProvider + DataProvider @@ -401,12 +401,6 @@ impl DateTimeFormatter { if cal == Some(value!("ethioaa")) { locale.set_unicode_ext(key!("ca"), value!("ethiopic")); } - let patterns = provider::date_time::PatternSelector::for_options( - data_provider, - patterns_data, - &locale, - &options, - )?; let required = datetime::analyze_patterns(&patterns.get().0, false) .map_err(|field| DateTimeFormatterError::UnsupportedField(field.symbol))?; @@ -539,6 +533,7 @@ impl DateTimeFormatter { /// Returns a [`components::Bag`] that represents the resolved components for the /// options that were provided to the [`DateTimeFormatter`]. + #[cfg(feature = "experimental")] pub fn resolve_components(&self) -> components::Bag { components::Bag::from(&self.patterns.get().0) } diff --git a/components/datetime/src/raw/zoned_datetime.rs b/components/datetime/src/raw/zoned_datetime.rs index 7a380ead63d..0cd56f1901d 100644 --- a/components/datetime/src/raw/zoned_datetime.rs +++ b/components/datetime/src/raw/zoned_datetime.rs @@ -24,7 +24,7 @@ use crate::{ provider::{ self, calendar::{ - DateSkeletonPatternsV1Marker, ErasedDateLengthsV1Marker, ErasedDateSymbolsV1Marker, + patterns::PatternPluralsFromPatternsV1Marker, ErasedDateSymbolsV1Marker, TimeLengthsV1Marker, TimeSymbolsV1Marker, }, week_data::WeekDataV1Marker, @@ -50,7 +50,7 @@ impl ZonedDateTimeFormatter { #[inline(never)] pub fn try_new

( provider: &P, - patterns_data: DataPayload, + patterns: DataPayload, symbols_data_fn: impl FnOnce() -> Result, DataError>, mut locale: DataLocale, date_time_format_options: DateTimeFormatterOptions, @@ -59,7 +59,6 @@ impl ZonedDateTimeFormatter { where P: DataProvider + DataProvider - + DataProvider + DataProvider + DataProvider + DataProvider @@ -75,12 +74,6 @@ impl ZonedDateTimeFormatter { locale.set_unicode_ext(key!("ca"), value!("ethiopic")); } - let patterns = provider::date_time::PatternSelector::for_options( - provider, - patterns_data, - &locale, - &date_time_format_options, - )?; let required = datetime::analyze_patterns(&patterns.get().0, true) .map_err(|field| DateTimeFormatterError::UnsupportedField(field.symbol))?; diff --git a/components/datetime/src/zoned_datetime.rs b/components/datetime/src/zoned_datetime.rs index 42ee6617d75..2ce7cb9a769 100644 --- a/components/datetime/src/zoned_datetime.rs +++ b/components/datetime/src/zoned_datetime.rs @@ -16,7 +16,8 @@ use crate::{ options::DateTimeFormatterOptions, provider::{ self, - calendar::{DateSkeletonPatternsV1Marker, TimeLengthsV1Marker, TimeSymbolsV1Marker}, + calendar::{TimeLengthsV1Marker, TimeSymbolsV1Marker}, + date_time::PatternSelector, week_data::WeekDataV1Marker, }, raw, @@ -96,6 +97,7 @@ impl TypedZonedDateTimeFormatter { /// ``` /// /// [data provider]: icu_provider + #[cfg(feature = "experimental")] #[inline] pub fn try_new_unstable

( provider: &P, @@ -108,7 +110,7 @@ impl TypedZonedDateTimeFormatter { + DataProvider<::DateLengthsV1Marker> + DataProvider + DataProvider - + DataProvider + + DataProvider + DataProvider + DataProvider + DataProvider @@ -126,10 +128,66 @@ impl TypedZonedDateTimeFormatter { let mut locale_with_cal = locale.clone(); calendar::potentially_fixup_calendar::(&mut locale_with_cal)?; + let patterns = PatternSelector::for_options( + provider, + calendar::load_lengths_for_cldr_calendar::(provider, locale)?, + &locale, + &date_time_format_options, + )?; Ok(Self( raw::ZonedDateTimeFormatter::try_new( provider, - calendar::load_lengths_for_cldr_calendar::(provider, locale)?, + patterns, + || calendar::load_symbols_for_cldr_calendar::(provider, locale), + locale_with_cal, + date_time_format_options, + time_zone_format_options, + )?, + PhantomData, + )) + } + + // No docs because the "experimental" version is what docs use + #[cfg(not(feature = "experimental"))] + #[inline] + pub fn try_new_unstable

( + provider: &P, + locale: &DataLocale, + date_time_format_options: DateTimeFormatterOptions, + time_zone_format_options: TimeZoneFormatterOptions, + ) -> Result + where + P: DataProvider<::DateSymbolsV1Marker> + + DataProvider<::DateLengthsV1Marker> + + DataProvider + + DataProvider + + DataProvider + + DataProvider + + DataProvider + + DataProvider + + DataProvider + + DataProvider + + DataProvider + + DataProvider + + DataProvider + + DataProvider + + ?Sized, + { + // TODO(#2188): Avoid cloning the DataLocale by passing the calendar + // separately into the raw formatter. + let mut locale_with_cal = locale.clone(); + + calendar::potentially_fixup_calendar::(&mut locale_with_cal)?; + let patterns = PatternSelector::for_options( + provider, + calendar::load_lengths_for_cldr_calendar::(provider, locale)?, + &locale, + &date_time_format_options, + )?; + Ok(Self( + raw::ZonedDateTimeFormatter::try_new( + provider, + patterns, || calendar::load_symbols_for_cldr_calendar::(provider, locale), locale_with_cal, date_time_format_options, From 52d37484ddc6225736444f0ebccb0b5c7403dbfa Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Fri, 12 Aug 2022 10:41:11 -0700 Subject: [PATCH 02/17] icu_datetime builds cleanly with default features and all features --- components/datetime/src/any/datetime.rs | 6 +++--- components/datetime/src/any/zoned_datetime.rs | 4 +--- components/datetime/src/datetime.rs | 4 +--- components/datetime/src/fields/mod.rs | 1 + components/datetime/src/fields/symbols.rs | 2 ++ components/datetime/src/pattern/runtime/helpers.rs | 1 + components/datetime/src/provider/date_time.rs | 7 ++++++- components/datetime/src/raw/datetime.rs | 5 +++-- components/datetime/src/raw/zoned_datetime.rs | 2 -- components/datetime/src/zoned_datetime.rs | 4 +--- 10 files changed, 19 insertions(+), 17 deletions(-) diff --git a/components/datetime/src/any/datetime.rs b/components/datetime/src/any/datetime.rs index 090f79b33c7..3a796742700 100644 --- a/components/datetime/src/any/datetime.rs +++ b/components/datetime/src/any/datetime.rs @@ -17,6 +17,8 @@ use icu_calendar::{types::Time, DateTime}; use icu_decimal::provider::DecimalSymbolsV1Marker; use icu_plurals::provider::OrdinalV1Marker; use icu_provider::DataLocale; +#[cfg(feature = "experimental")] +use crate::options::components; /// [`DateTimeFormatter`] is a formatter capable of formatting /// date/times from any calendar, selected at runtime. For the difference between this and [`TypedDateTimeFormatter`](crate::TypedDateTimeFormatter), @@ -272,13 +274,12 @@ impl DateTimeFormatter { patterns, || calendar::load_symbols_for_any_calendar_kind(data_provider, locale, kind), locale_with_cal, - options, )?, calendar, )) } - // No docs because the "experimental" version is what docs use + #[allow(missing_docs)] // The docs use the "experimental" version #[cfg(not(feature = "experimental"))] #[inline(never)] pub fn try_new_unstable

( @@ -342,7 +343,6 @@ impl DateTimeFormatter { patterns, || calendar::load_symbols_for_any_calendar_kind(data_provider, locale, kind), locale_with_cal, - options, )?, calendar, )) diff --git a/components/datetime/src/any/zoned_datetime.rs b/components/datetime/src/any/zoned_datetime.rs index 1b1341bfdc8..759988d541a 100644 --- a/components/datetime/src/any/zoned_datetime.rs +++ b/components/datetime/src/any/zoned_datetime.rs @@ -182,14 +182,13 @@ impl ZonedDateTimeFormatter { patterns, || calendar::load_symbols_for_any_calendar_kind(provider, locale, kind), locale_with_cal, - date_time_format_options, time_zone_format_options, )?, calendar, )) } - // No docs because the "experimental" version is what docs use + #[allow(missing_docs)] // The docs use the "experimental" version #[cfg(not(feature = "experimental"))] #[inline] #[allow(clippy::too_many_arguments)] @@ -261,7 +260,6 @@ impl ZonedDateTimeFormatter { patterns, || calendar::load_symbols_for_any_calendar_kind(provider, locale, kind), locale_with_cal, - date_time_format_options, time_zone_format_options, )?, calendar, diff --git a/components/datetime/src/datetime.rs b/components/datetime/src/datetime.rs index a3dbbdd6126..6f6784fb5b7 100644 --- a/components/datetime/src/datetime.rs +++ b/components/datetime/src/datetime.rs @@ -521,13 +521,12 @@ where { patterns, || calendar::load_symbols_for_cldr_calendar::(data_provider, locale), locale_with_cal, - options, )?, PhantomData, )) } - // No docs because the "experimental" version is what docs use + #[allow(missing_docs)] // The docs use the "experimental" version #[cfg(not(feature = "experimental"))] #[inline] pub fn try_new_unstable( @@ -562,7 +561,6 @@ where { patterns, || calendar::load_symbols_for_cldr_calendar::(data_provider, locale), locale_with_cal, - options, )?, PhantomData, )) diff --git a/components/datetime/src/fields/mod.rs b/components/datetime/src/fields/mod.rs index 5afd5c5da36..90c704a3c3b 100644 --- a/components/datetime/src/fields/mod.rs +++ b/components/datetime/src/fields/mod.rs @@ -55,6 +55,7 @@ pub struct Field { } impl Field { + #[cfg(feature = "experimental")] // only referenced in experimental code pub(crate) fn get_length_type(&self) -> TextOrNumeric { match self.symbol { FieldSymbol::Era => TextOrNumeric::Text, diff --git a/components/datetime/src/fields/symbols.rs b/components/datetime/src/fields/symbols.rs index 00b702e26d4..10aeb2cd220 100644 --- a/components/datetime/src/fields/symbols.rs +++ b/components/datetime/src/fields/symbols.rs @@ -138,6 +138,7 @@ impl FieldSymbol { } /// Returns the index associated with this FieldSymbol. + #[cfg(feature = "experimental")] // only referenced in experimental code fn discriminant_idx(&self) -> u8 { match self { FieldSymbol::Era => 0, @@ -156,6 +157,7 @@ impl FieldSymbol { /// Compares this enum with other solely based on the enum variant, /// ignoring the enum's data. + #[cfg(feature = "experimental")] // only referenced in experimental code pub(crate) fn discriminant_cmp(&self, other: &Self) -> Ordering { self.discriminant_idx().cmp(&other.discriminant_idx()) } diff --git a/components/datetime/src/pattern/runtime/helpers.rs b/components/datetime/src/pattern/runtime/helpers.rs index 50378aba290..80df7adf080 100644 --- a/components/datetime/src/pattern/runtime/helpers.rs +++ b/components/datetime/src/pattern/runtime/helpers.rs @@ -38,6 +38,7 @@ pub fn maybe_replace_first(pattern: &mut Pattern, f: impl Fn(&PatternItem) -> Op /// /// For a variant that replaces just the first matching instance, /// see `maybe_replace_first`. +#[cfg(feature = "experimental")] // only referenced in experimental code pub fn maybe_replace(pattern: &mut Pattern, f: impl Fn(&PatternItem) -> Option) { let result = pattern .items diff --git a/components/datetime/src/provider/date_time.rs b/components/datetime/src/provider/date_time.rs index 2a0e785597a..a0843dc1514 100644 --- a/components/datetime/src/provider/date_time.rs +++ b/components/datetime/src/provider/date_time.rs @@ -16,6 +16,11 @@ use crate::provider::calendar::{ use crate::provider::calendar::{DateLengthsV1, TimeLengthsV1}; use icu_calendar::types::{Era, MonthCode}; use icu_provider::prelude::*; +#[cfg(feature = "experimental")] +use crate::{ + options::components, + provider::calendar::DateSkeletonPatternsV1Marker +}; type Result = core::result::Result; @@ -217,7 +222,7 @@ where impl PatternSelector<'_, D> where D: DataProvider - + DataProvider + + DataProvider + ?Sized, { pub(crate) fn for_options<'a>( diff --git a/components/datetime/src/raw/datetime.rs b/components/datetime/src/raw/datetime.rs index 81ae80a6d1c..0223ae4b5e5 100644 --- a/components/datetime/src/raw/datetime.rs +++ b/components/datetime/src/raw/datetime.rs @@ -8,7 +8,7 @@ use crate::{ format::datetime, input::{DateInput, DateTimeInput, ExtractedDateTimeInput, IsoTimeInput}, - options::{length, preferences, DateTimeFormatterOptions}, + options::{length, preferences}, pattern::runtime::PatternPlurals, provider::{ self, @@ -21,6 +21,8 @@ use crate::{ }, DateTimeFormatterError, FormattedDateTime, }; +#[cfg(feature = "experimental")] +use crate::options::components; use alloc::string::String; use icu_decimal::{ @@ -387,7 +389,6 @@ impl DateTimeFormatter { patterns: DataPayload, symbols_data_fn: impl FnOnce() -> Result, DataError>, mut locale: DataLocale, - options: DateTimeFormatterOptions, ) -> Result where D: DataProvider diff --git a/components/datetime/src/raw/zoned_datetime.rs b/components/datetime/src/raw/zoned_datetime.rs index 0cd56f1901d..dd19905b216 100644 --- a/components/datetime/src/raw/zoned_datetime.rs +++ b/components/datetime/src/raw/zoned_datetime.rs @@ -19,7 +19,6 @@ use crate::{ }, input::{DateTimeInput, TimeZoneInput}, input::{ExtractedDateTimeInput, ExtractedTimeZoneInput}, - options::DateTimeFormatterOptions, pattern::runtime::PatternPlurals, provider::{ self, @@ -53,7 +52,6 @@ impl ZonedDateTimeFormatter { patterns: DataPayload, symbols_data_fn: impl FnOnce() -> Result, DataError>, mut locale: DataLocale, - date_time_format_options: DateTimeFormatterOptions, time_zone_format_options: TimeZoneFormatterOptions, ) -> Result where diff --git a/components/datetime/src/zoned_datetime.rs b/components/datetime/src/zoned_datetime.rs index 2ce7cb9a769..2ab526c248f 100644 --- a/components/datetime/src/zoned_datetime.rs +++ b/components/datetime/src/zoned_datetime.rs @@ -140,14 +140,13 @@ impl TypedZonedDateTimeFormatter { patterns, || calendar::load_symbols_for_cldr_calendar::(provider, locale), locale_with_cal, - date_time_format_options, time_zone_format_options, )?, PhantomData, )) } - // No docs because the "experimental" version is what docs use + #[allow(missing_docs)] // The docs use the "experimental" version #[cfg(not(feature = "experimental"))] #[inline] pub fn try_new_unstable

( @@ -190,7 +189,6 @@ impl TypedZonedDateTimeFormatter { patterns, || calendar::load_symbols_for_cldr_calendar::(provider, locale), locale_with_cal, - date_time_format_options, time_zone_format_options, )?, PhantomData, From 079cfe19a1995e529df92bab9a2f4ede036d30dc Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Fri, 12 Aug 2022 10:41:40 -0700 Subject: [PATCH 03/17] fmt --- components/datetime/src/any/datetime.rs | 6 +++--- components/datetime/src/any/zoned_datetime.rs | 2 +- components/datetime/src/provider/date_time.rs | 11 +++-------- components/datetime/src/raw/datetime.rs | 4 ++-- 4 files changed, 9 insertions(+), 14 deletions(-) diff --git a/components/datetime/src/any/datetime.rs b/components/datetime/src/any/datetime.rs index 3a796742700..327f5175893 100644 --- a/components/datetime/src/any/datetime.rs +++ b/components/datetime/src/any/datetime.rs @@ -9,7 +9,9 @@ use icu_locid::{extensions_unicode_key as key, extensions_unicode_value as value use icu_provider::prelude::*; -use crate::provider::{calendar::*, week_data::WeekDataV1Marker, date_time::PatternSelector}; +#[cfg(feature = "experimental")] +use crate::options::components; +use crate::provider::{calendar::*, date_time::PatternSelector, week_data::WeekDataV1Marker}; use crate::{input::DateTimeInput, DateTimeFormatterError, FormattedDateTime}; use icu_calendar::any_calendar::{AnyCalendar, AnyCalendarKind}; use icu_calendar::provider::{JapaneseErasV1Marker, JapaneseExtendedErasV1Marker}; @@ -17,8 +19,6 @@ use icu_calendar::{types::Time, DateTime}; use icu_decimal::provider::DecimalSymbolsV1Marker; use icu_plurals::provider::OrdinalV1Marker; use icu_provider::DataLocale; -#[cfg(feature = "experimental")] -use crate::options::components; /// [`DateTimeFormatter`] is a formatter capable of formatting /// date/times from any calendar, selected at runtime. For the difference between this and [`TypedDateTimeFormatter`](crate::TypedDateTimeFormatter), diff --git a/components/datetime/src/any/zoned_datetime.rs b/components/datetime/src/any/zoned_datetime.rs index 759988d541a..8d059ed9c0e 100644 --- a/components/datetime/src/any/zoned_datetime.rs +++ b/components/datetime/src/any/zoned_datetime.rs @@ -10,7 +10,7 @@ use icu_locid::{extensions_unicode_key as key, extensions_unicode_value as value use icu_provider::prelude::*; use crate::input::{DateTimeInput, ExtractedDateTimeInput, TimeZoneInput}; -use crate::provider::{self, calendar::*, week_data::WeekDataV1Marker, date_time::PatternSelector}; +use crate::provider::{self, calendar::*, date_time::PatternSelector, week_data::WeekDataV1Marker}; use crate::time_zone::TimeZoneFormatterOptions; use crate::{DateTimeFormatterError, FormattedZonedDateTime}; use icu_calendar::any_calendar::{AnyCalendar, AnyCalendarKind}; diff --git a/components/datetime/src/provider/date_time.rs b/components/datetime/src/provider/date_time.rs index a0843dc1514..d6cf3fc5ebd 100644 --- a/components/datetime/src/provider/date_time.rs +++ b/components/datetime/src/provider/date_time.rs @@ -14,13 +14,10 @@ use crate::provider::calendar::{ ErasedDateLengthsV1Marker, TimeLengthsV1Marker, }; use crate::provider::calendar::{DateLengthsV1, TimeLengthsV1}; +#[cfg(feature = "experimental")] +use crate::{options::components, provider::calendar::DateSkeletonPatternsV1Marker}; use icu_calendar::types::{Era, MonthCode}; use icu_provider::prelude::*; -#[cfg(feature = "experimental")] -use crate::{ - options::components, - provider::calendar::DateSkeletonPatternsV1Marker -}; type Result = core::result::Result; @@ -221,9 +218,7 @@ where #[cfg(feature = "experimental")] impl PatternSelector<'_, D> where - D: DataProvider - + DataProvider - + ?Sized, + D: DataProvider + DataProvider + ?Sized, { pub(crate) fn for_options<'a>( data_provider: &'a D, diff --git a/components/datetime/src/raw/datetime.rs b/components/datetime/src/raw/datetime.rs index 0223ae4b5e5..0d25acc54be 100644 --- a/components/datetime/src/raw/datetime.rs +++ b/components/datetime/src/raw/datetime.rs @@ -5,6 +5,8 @@ //! The collection of code that is needed for handling formatting operations for DateTimes. //! Central to this is the [`DateTimeFormatter`]. +#[cfg(feature = "experimental")] +use crate::options::components; use crate::{ format::datetime, input::{DateInput, DateTimeInput, ExtractedDateTimeInput, IsoTimeInput}, @@ -21,8 +23,6 @@ use crate::{ }, DateTimeFormatterError, FormattedDateTime, }; -#[cfg(feature = "experimental")] -use crate::options::components; use alloc::string::String; use icu_decimal::{ From d0ac04f42e690fe0d40426331e4bceb474822924 Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Fri, 12 Aug 2022 11:05:51 -0700 Subject: [PATCH 04/17] Tests mostly working --- components/datetime/Cargo.toml | 10 +++- components/datetime/src/any/zoned_datetime.rs | 2 +- components/datetime/src/pattern/hour_cycle.rs | 4 +- components/datetime/tests/datetime.rs | 60 ++++++++----------- components/datetime/tests/fixtures/mod.rs | 9 ++- components/datetime/tests/fixtures/structs.rs | 9 ++- 6 files changed, 49 insertions(+), 45 deletions(-) diff --git a/components/datetime/Cargo.toml b/components/datetime/Cargo.toml index cf77faafaca..8010800d59e 100644 --- a/components/datetime/Cargo.toml +++ b/components/datetime/Cargo.toml @@ -56,7 +56,7 @@ icu = { path = "../icu", default-features = false, features = ["experimental"] } icu_benchmark_macros = { version = "0.7", path = "../../tools/benchmark/macros" } icu_provider = { version = "1.0.0-beta1", path = "../../provider/core" } icu_provider_adapters = { path = "../../provider/adapters" } -icu_testdata = { path = "../../provider/testdata", features = ["baked"] } +icu_testdata = { path = "../../provider/testdata" } icu_calendar = { version = "1.0.0-beta1", path = "../calendar", features = ["serde"] } icu_datetime = { path = "../../components/datetime", features = ["datagen"] } @@ -90,6 +90,14 @@ required-features = ["bench"] name = "datetime" required-features = ["serde"] +[[test]] +name = "resolved_components" +required-features = ["experimental"] + +[[test]] +name = "skeleton_serialization" +required-features = ["experimental"] + [[example]] name = "work_log" required-features = ["serde"] diff --git a/components/datetime/src/any/zoned_datetime.rs b/components/datetime/src/any/zoned_datetime.rs index 8d059ed9c0e..e7adcd7dc00 100644 --- a/components/datetime/src/any/zoned_datetime.rs +++ b/components/datetime/src/any/zoned_datetime.rs @@ -282,7 +282,7 @@ impl ZonedDateTimeFormatter { /// since these functions currently *must* be given a fallback-enabled provider and /// we do not have one in `icu_testdata` /// - /// ```rust,should_panic + /// ```ignore /// use icu::calendar::Gregorian; /// use icu::datetime::options::length; /// use icu::datetime::mock::parse_zoned_gregorian_from_str; diff --git a/components/datetime/src/pattern/hour_cycle.rs b/components/datetime/src/pattern/hour_cycle.rs index 5bd370aa7b7..fcc53bfa519 100644 --- a/components/datetime/src/pattern/hour_cycle.rs +++ b/components/datetime/src/pattern/hour_cycle.rs @@ -4,7 +4,7 @@ use super::{reference, runtime, PatternItem}; use crate::{fields, options::preferences}; -#[cfg(feature = "datagen")] +#[cfg(all(feature = "datagen", feature = "experimental"))] use crate::{provider, skeleton}; use icu_provider::{yoke, zerofrom}; @@ -56,7 +56,7 @@ impl CoarseHourCycle { /// Invoke the pattern matching machinery to transform the hour cycle of a pattern. This provides /// a safe mapping from a h11/h12 to h23/h24 for transforms. #[doc(hidden)] - #[cfg(feature = "datagen")] + #[cfg(all(feature = "datagen", feature = "experimental"))] pub fn apply_on_pattern<'data>( &self, date_time: &provider::calendar::patterns::GenericLengthPatternsV1<'data>, diff --git a/components/datetime/tests/datetime.rs b/components/datetime/tests/datetime.rs index 651c699f2f1..1378f546d9a 100644 --- a/components/datetime/tests/datetime.rs +++ b/components/datetime/tests/datetime.rs @@ -14,7 +14,6 @@ use icu_calendar::{ ethiopic::{Ethiopic, EthiopicEraStyle}, indian::Indian, japanese::{Japanese, JapaneseExtended}, - provider::{JapaneseErasV1Marker, JapaneseExtendedErasV1Marker}, AsCalendar, DateTime, Gregorian, Iso, }; use icu_datetime::provider::time_zones::{ @@ -35,7 +34,6 @@ use icu_decimal::provider::DecimalSymbolsV1Marker; use icu_locid::{ extensions_unicode_key as key, extensions_unicode_value as value, LanguageIdentifier, Locale, }; -use icu_plurals::provider::OrdinalV1Marker; use icu_provider::prelude::*; use icu_provider_adapters::any_payload::AnyPayloadProvider; use icu_provider_adapters::fork::MultiForkByKeyProvider; @@ -61,7 +59,13 @@ fn test_fixture(fixture_name: &str) { let japanese = Japanese::try_new_unstable(&provider).expect("Cannot load japanese data"); let japanext = JapaneseExtended::try_new_unstable(&provider).expect("Cannot load japanese data"); - let options_base = fixtures::get_options(&fx.input.options); + let options_base = match fixtures::get_options(&fx.input.options) { + Some(o) => o, + #[cfg(feature = "experimental")] + None => unreachable!(), + #[cfg(not(feature = "experimental"))] + None => continue, + }; let input_value = parse_gregorian_from_str(&fx.input.value).unwrap(); let input_iso = input_value.to_calendar(Iso); let input_buddhist = input_value.to_calendar(Buddhist); @@ -179,35 +183,11 @@ fn assert_fixture_element( A: AsCalendar, A::Calendar: CldrCalendar, A::Calendar: IncludedInAnyCalendar, - D: DataProvider - + DataProvider - + DataProvider - + DataProvider - + DataProvider - + DataProvider - + DataProvider - + DataProvider - + DataProvider - + DataProvider - + DataProvider - + DataProvider - + DataProvider - + DataProvider - + DataProvider - + DataProvider - + DataProvider - + DataProvider - // Note: all CldrCalendar markers are covered above, but the compiler doesn't know that - + DataProvider<<::Calendar as CldrCalendar>::DateLengthsV1Marker> - + DataProvider<<::Calendar as CldrCalendar>::DateSymbolsV1Marker> - + DataProvider - + DataProvider - + DataProvider - + DataProvider, + D: BufferProvider { let any_input = input_value.to_any(); let iso_any_input = input_iso.to_any(); - let dtf = TypedDateTimeFormatter::::try_new_unstable( + let dtf = TypedDateTimeFormatter::::try_new_with_buffer_provider( provider, &locale.into(), options.clone(), @@ -218,7 +198,7 @@ fn assert_fixture_element( assert_eq!(result, output_value, "{}", description); let any_dtf = - DateTimeFormatter::try_new_unstable(provider, &locale.into(), options.clone()).unwrap(); + DateTimeFormatter::try_new_with_buffer_provider(provider, &locale.into(), options.clone()).unwrap(); let result = any_dtf.format_to_string(&any_input).unwrap(); assert_eq!(result, output_value, "(DateTimeFormatter) {}", description); @@ -245,13 +225,13 @@ fn assert_fixture_element( if let DateTimeFormatterOptions::Length(bag) = options { if bag.date.is_some() && bag.time.is_some() { - let df = TypedDateFormatter::::try_new_unstable( + let df = TypedDateFormatter::::try_new_with_buffer_provider( provider, &locale.into(), bag.date.unwrap(), ) .unwrap(); - let tf = TimeFormatter::try_new_unstable(provider, &locale.into(), bag.time.unwrap()) + let tf = TimeFormatter::try_new_with_buffer_provider(provider, &locale.into(), bag.time.unwrap()) .unwrap(); let dtf = TypedDateTimeFormatter::try_from_date_and_time(df, tf).unwrap(); @@ -271,7 +251,7 @@ fn assert_fixture_element( write!(s, "{}", fdt).unwrap(); assert_eq!(s, output_value, "{}", description); } else if bag.date.is_some() { - let df = TypedDateFormatter::::try_new_unstable( + let df = TypedDateFormatter::::try_new_with_buffer_provider( provider, &locale.into(), bag.date.unwrap(), @@ -293,7 +273,7 @@ fn assert_fixture_element( write!(s, "{}", fdt).unwrap(); assert_eq!(s, output_value, "{}", description); } else if bag.time.is_some() { - let tf = TimeFormatter::try_new_unstable(provider, &locale.into(), bag.time.unwrap()) + let tf = TimeFormatter::try_new_with_buffer_provider(provider, &locale.into(), bag.time.unwrap()) .unwrap(); let result = tf.format_to_string(input_value); @@ -322,7 +302,13 @@ fn test_fixture_with_time_zones(fixture_name: &str, config: TimeZoneConfig) { .expect("Unable to get fixture.") .0 { - let options = fixtures::get_options(&fx.input.options); + let options = match fixtures::get_options(&fx.input.options) { + Some(o) => o, + #[cfg(feature = "experimental")] + None => unreachable!(), + #[cfg(not(feature = "experimental"))] + None => continue, + }; let (input_date, mut time_zone) = parse_zoned_gregorian_from_str(&fx.input.value).unwrap(); time_zone.time_zone_id = config.time_zone_id.map(TimeZoneBcp47Id); @@ -397,6 +383,7 @@ fn test_dayperiod_patterns() { provider.load(req).unwrap().take_payload().unwrap(); let time_symbols_data: DataPayload = provider.load(req).unwrap().take_payload().unwrap(); + #[cfg(feature = "experimental")] let skeleton_data: DataPayload = provider.load(req).unwrap().take_payload().unwrap(); let week_data: DataPayload = @@ -430,6 +417,7 @@ fn test_dayperiod_patterns() { key: TimeSymbolsV1Marker::KEY, data: time_symbols_data.clone().wrap_into_any_payload(), }, + #[cfg(feature = "experimental")] AnyPayloadProvider { key: DateSkeletonPatternsV1Marker::KEY, data: skeleton_data.clone().wrap_into_any_payload(), @@ -599,6 +587,7 @@ fn test_time_zone_patterns() { date_provider.load(req).unwrap().take_payload().unwrap(); let mut time_patterns_data: DataPayload = date_provider.load(req).unwrap().take_payload().unwrap(); + #[cfg(feature = "experimental")] let skeleton_data: DataPayload = date_provider.load(req).unwrap().take_payload().unwrap(); let symbols_data: DataPayload = @@ -643,6 +632,7 @@ fn test_time_zone_patterns() { key: GregorianDateSymbolsV1Marker::KEY, data: symbols_data.clone().wrap_into_any_payload(), }, + #[cfg(feature = "experimental")] AnyPayloadProvider { key: DateSkeletonPatternsV1Marker::KEY, data: skeleton_data.clone().wrap_into_any_payload(), diff --git a/components/datetime/tests/fixtures/mod.rs b/components/datetime/tests/fixtures/mod.rs index 84b9b475e8c..64f294ac140 100644 --- a/components/datetime/tests/fixtures/mod.rs +++ b/components/datetime/tests/fixtures/mod.rs @@ -17,9 +17,12 @@ pub fn get_fixture(name: &str) -> std::io::Result { Ok(serde_json::from_reader(reader)?) } -pub fn get_options(input: &structs::TestOptions) -> DateTimeFormatterOptions { +pub fn get_options(input: &structs::TestOptions) -> Option { match input { - structs::TestOptions::Length(bag) => (*bag).into(), - structs::TestOptions::Components(bag) => (*bag).into(), + structs::TestOptions::Length(bag) => Some((*bag).into()), + #[cfg(feature = "experimental")] + structs::TestOptions::Components(bag) => Some((*bag).into()), + #[cfg(not(feature = "experimental"))] + structs::TestOptions::Components(_) => None, } } diff --git a/components/datetime/tests/fixtures/structs.rs b/components/datetime/tests/fixtures/structs.rs index d2d1112bf2f..446e4a97962 100644 --- a/components/datetime/tests/fixtures/structs.rs +++ b/components/datetime/tests/fixtures/structs.rs @@ -7,7 +7,6 @@ //! This file contains the serde representaitons of the JSON files located in //! components/datetime/tests/fixtures/tests -use icu_datetime::options::{components, length}; use serde::{Deserialize, Serialize}; use std::collections::HashMap; @@ -30,9 +29,13 @@ pub struct TestInput { #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub enum TestOptions { #[serde(rename = "length")] - Length(length::Bag), + Length(icu_datetime::options::length::Bag), #[serde(rename = "components")] - Components(components::Bag), + #[cfg(feature = "experimental")] + Components(icu_datetime::options::components::Bag), + #[serde(rename = "components")] + #[cfg(not(feature = "experimental"))] + Components(serde_json::Value), } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] From 83102480dba4ca09709ca0dc15593ae7aec1f0db Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Fri, 12 Aug 2022 13:04:13 -0700 Subject: [PATCH 05/17] Locale calendar fixes --- components/datetime/src/any/datetime.rs | 2 +- components/datetime/src/any/zoned_datetime.rs | 2 +- components/datetime/src/calendar.rs | 4 ++++ components/datetime/src/datetime.rs | 4 ++-- components/datetime/src/provider/date_time.rs | 2 ++ components/datetime/src/raw/datetime.rs | 8 ++------ components/datetime/src/zoned_datetime.rs | 4 ++-- components/datetime/tests/datetime.rs | 2 +- 8 files changed, 15 insertions(+), 13 deletions(-) diff --git a/components/datetime/src/any/datetime.rs b/components/datetime/src/any/datetime.rs index 327f5175893..017a86cd9f1 100644 --- a/components/datetime/src/any/datetime.rs +++ b/components/datetime/src/any/datetime.rs @@ -264,7 +264,7 @@ impl DateTimeFormatter { let patterns = PatternSelector::for_options( data_provider, calendar::load_lengths_for_any_calendar_kind(data_provider, locale, kind)?, - &locale, + &locale_with_cal, &options, )?; diff --git a/components/datetime/src/any/zoned_datetime.rs b/components/datetime/src/any/zoned_datetime.rs index e7adcd7dc00..89ac42f599b 100644 --- a/components/datetime/src/any/zoned_datetime.rs +++ b/components/datetime/src/any/zoned_datetime.rs @@ -172,7 +172,7 @@ impl ZonedDateTimeFormatter { let patterns = PatternSelector::for_options( provider, calendar::load_lengths_for_any_calendar_kind(provider, locale, kind)?, - &locale, + &locale_with_cal, &date_time_format_options, )?; diff --git a/components/datetime/src/calendar.rs b/components/datetime/src/calendar.rs index 74178959d0e..8c75eab0208 100644 --- a/components/datetime/src/calendar.rs +++ b/components/datetime/src/calendar.rs @@ -105,6 +105,10 @@ pub(crate) fn potentially_fixup_calendar( locale.set_unicode_ext(key!("ca"), C::DEFAULT_BCP_47_IDENTIFIER); } + if locale.get_unicode_ext(&key!("ca")) == Some(value!("ethioaa")) { + locale.set_unicode_ext(key!("ca"), value!("ethiopic")); + } + Ok(()) } diff --git a/components/datetime/src/datetime.rs b/components/datetime/src/datetime.rs index 6f6784fb5b7..35770387a74 100644 --- a/components/datetime/src/datetime.rs +++ b/components/datetime/src/datetime.rs @@ -512,7 +512,7 @@ where { let patterns = PatternSelector::for_options( data_provider, calendar::load_lengths_for_cldr_calendar::(data_provider, locale)?, - &locale, + &locale_with_cal, &options, )?; Ok(Self( @@ -552,7 +552,7 @@ where { let patterns = PatternSelector::for_options( data_provider, calendar::load_lengths_for_cldr_calendar::(data_provider, locale)?, - &locale, + &locale_with_cal, &options, )?; Ok(Self( diff --git a/components/datetime/src/provider/date_time.rs b/components/datetime/src/provider/date_time.rs index d6cf3fc5ebd..8a293f6bee4 100644 --- a/components/datetime/src/provider/date_time.rs +++ b/components/datetime/src/provider/date_time.rs @@ -145,6 +145,7 @@ where locale: &'a DataLocale, options: &DateTimeFormatterOptions, ) -> Result> { + debug_assert!(locale.get_unicode_ext(&icu_locid::extensions_unicode_key!("ca")).is_some()); let selector = PatternSelector { data_provider, date_patterns_data, @@ -226,6 +227,7 @@ where locale: &'a DataLocale, options: &DateTimeFormatterOptions, ) -> Result> { + debug_assert!(locale.get_unicode_ext(&icu_locid::extensions_unicode_key!("ca")).is_some()); let selector = PatternSelector { data_provider, date_patterns_data, diff --git a/components/datetime/src/raw/datetime.rs b/components/datetime/src/raw/datetime.rs index 0d25acc54be..c911b161102 100644 --- a/components/datetime/src/raw/datetime.rs +++ b/components/datetime/src/raw/datetime.rs @@ -194,9 +194,7 @@ impl DateFormatter { + DataProvider + ?Sized, { - if locale.get_unicode_ext(&key!("ca")) == Some(value!("ethioaa")) { - locale.set_unicode_ext(key!("ca"), value!("ethiopic")); - } + debug_assert!(locale.get_unicode_ext(&key!("ca")) != Some(value!("ethioaa"))); let patterns = provider::date_time::pattern_for_date_length(length, patterns_data.clone()); let generic_pattern = @@ -398,10 +396,8 @@ impl DateTimeFormatter { + DataProvider + ?Sized, { + debug_assert!(locale.get_unicode_ext(&key!("ca")) != Some(value!("ethioaa"))); let cal = locale.get_unicode_ext(&key!("ca")); - if cal == Some(value!("ethioaa")) { - locale.set_unicode_ext(key!("ca"), value!("ethiopic")); - } let required = datetime::analyze_patterns(&patterns.get().0, false) .map_err(|field| DateTimeFormatterError::UnsupportedField(field.symbol))?; diff --git a/components/datetime/src/zoned_datetime.rs b/components/datetime/src/zoned_datetime.rs index 2ab526c248f..a1570046511 100644 --- a/components/datetime/src/zoned_datetime.rs +++ b/components/datetime/src/zoned_datetime.rs @@ -131,7 +131,7 @@ impl TypedZonedDateTimeFormatter { let patterns = PatternSelector::for_options( provider, calendar::load_lengths_for_cldr_calendar::(provider, locale)?, - &locale, + &locale_with_cal, &date_time_format_options, )?; Ok(Self( @@ -180,7 +180,7 @@ impl TypedZonedDateTimeFormatter { let patterns = PatternSelector::for_options( provider, calendar::load_lengths_for_cldr_calendar::(provider, locale)?, - &locale, + &locale_with_cal, &date_time_format_options, )?; Ok(Self( diff --git a/components/datetime/tests/datetime.rs b/components/datetime/tests/datetime.rs index 1378f546d9a..998db2ec619 100644 --- a/components/datetime/tests/datetime.rs +++ b/components/datetime/tests/datetime.rs @@ -192,7 +192,7 @@ fn assert_fixture_element( &locale.into(), options.clone(), ) - .unwrap(); + .expect(description); let result = dtf.format_to_string(input_value); assert_eq!(result, output_value, "{}", description); From 0451796654c460a1a967fe26b203b2a519e123df Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Fri, 12 Aug 2022 13:42:05 -0700 Subject: [PATCH 06/17] Work toward fixing datagen --- components/icu/Cargo.toml | 2 +- provider/datagen/Cargo.toml | 2 +- provider/datagen/src/databake.rs | 23 ++++---- provider/datagen/src/registry.rs | 2 +- .../src/transform/cldr/datetime/mod.rs | 59 ++++++++++++------- 5 files changed, 51 insertions(+), 37 deletions(-) diff --git a/components/icu/Cargo.toml b/components/icu/Cargo.toml index a39ef70de0a..1aaf1cefd42 100644 --- a/components/icu/Cargo.toml +++ b/components/icu/Cargo.toml @@ -70,7 +70,7 @@ serde = [ serde_human = [ "icu_list/serde_human" ] -experimental = ["icu_segmenter", "icu_timezone"] +experimental = ["icu_segmenter", "icu_timezone", "icu_datetime/experimental"] [[example]] name = "tui" diff --git a/provider/datagen/Cargo.toml b/provider/datagen/Cargo.toml index a6bb961b7d1..b24f20f1ed2 100644 --- a/provider/datagen/Cargo.toml +++ b/provider/datagen/Cargo.toml @@ -92,7 +92,7 @@ icu_testdata = { path = "../testdata", features = ["metadata"] } [features] default = [] -experimental = ["icu_casemapping", "icu_segmenter"] +experimental = ["icu_casemapping", "icu_segmenter", "icu_datetime/experimental"] bin = ["clap", "eyre", "simple_logger"] [[bin]] diff --git a/provider/datagen/src/databake.rs b/provider/datagen/src/databake.rs index 6968b52556d..6ed956ea144 100644 --- a/provider/datagen/src/databake.rs +++ b/provider/datagen/src/databake.rs @@ -214,19 +214,18 @@ impl DataExporter for BakedDataExporter { supers = quote! { super:: #supers }; } - let struct_type = - if key == icu_datetime::provider::calendar::DateSkeletonPatternsV1Marker::KEY { - quote! { - [( - &'static [::icu_datetime::fields::Field], - ::icu_datetime::pattern::runtime::PatternPlurals<'static> - )] - } - } else { - quote! { - <#marker as ::icu_provider::DataMarker>::Yokeable - } + let mut struct_type = quote! { + <#marker as ::icu_provider::DataMarker>::Yokeable + }; + #[cfg(feature = "experimental")] + if key == icu_datetime::provider::calendar::DateSkeletonPatternsV1Marker::KEY { + struct_type = quote! { + [( + &'static [::icu_datetime::fields::Field], + ::icu_datetime::pattern::runtime::PatternPlurals<'static> + )] }; + } self.write_to_file( &path, diff --git a/provider/datagen/src/registry.rs b/provider/datagen/src/registry.rs index d0ef80d1a26..861ddc4a54d 100644 --- a/provider/datagen/src/registry.rs +++ b/provider/datagen/src/registry.rs @@ -99,7 +99,6 @@ registry!( CopticDateLengthsV1Marker, CopticDateSymbolsV1Marker, DashV1Marker, - DateSkeletonPatternsV1Marker, DecimalSymbolsV1Marker, DefaultIgnorableCodePointV1Marker, DeprecatedV1Marker, @@ -192,6 +191,7 @@ registry!( #[cfg(feature = "experimental")] { CaseMappingV1Marker, + DateSkeletonPatternsV1Marker, GraphemeClusterBreakDataV1Marker, LineBreakDataV1Marker, LstmDataV1Marker, diff --git a/provider/datagen/src/transform/cldr/datetime/mod.rs b/provider/datagen/src/transform/cldr/datetime/mod.rs index ed8d918fb46..709cebff123 100644 --- a/provider/datagen/src/transform/cldr/datetime/mod.rs +++ b/provider/datagen/src/transform/cldr/datetime/mod.rs @@ -14,6 +14,7 @@ use std::collections::HashSet; use std::str::FromStr; mod patterns; +#[cfg(feature = "experimental")] mod skeletons; mod symbols; pub mod week_data; @@ -34,8 +35,7 @@ lazy_static! { } macro_rules! impl_data_provider { - ($(($marker:ident, $expr:expr, calendared = $calendared:expr)),+) => { - $( + ($marker:ident, $expr:expr, calendared = $calendared:expr) => { impl DataProvider<$marker> for crate::DatagenProvider { fn load( &self, @@ -205,97 +205,112 @@ macro_rules! impl_data_provider { Ok(r) } } - )+ }; } -impl_data_provider!( +impl_data_provider! ( GregorianDateSymbolsV1Marker, symbols::convert_dates, calendared = "gregory" - ), + ); +impl_data_provider! ( BuddhistDateSymbolsV1Marker, symbols::convert_dates, calendared = "buddhist" - ), + ); +impl_data_provider! ( JapaneseDateSymbolsV1Marker, symbols::convert_dates, calendared = "japanese" - ), + ); +impl_data_provider! ( JapaneseExtendedDateSymbolsV1Marker, symbols::convert_dates, calendared = "japanext" - ), + ); +impl_data_provider! ( CopticDateSymbolsV1Marker, symbols::convert_dates, calendared = "coptic" - ), + ); +impl_data_provider! ( IndianDateSymbolsV1Marker, symbols::convert_dates, calendared = "indian" - ), + ); +impl_data_provider! ( EthiopicDateSymbolsV1Marker, symbols::convert_dates, calendared = "ethiopic" - ), + ); +impl_data_provider! ( TimeSymbolsV1Marker, |dates, _| { symbols::convert_times(dates) }, calendared = "false" - ), + ); +#[cfg(feature = "experimental")] +impl_data_provider! ( DateSkeletonPatternsV1Marker, |dates, _| { DateSkeletonPatternsV1::from(dates) }, calendared = "locale" - ), + ); +impl_data_provider! ( GregorianDateLengthsV1Marker, |dates, _| DateLengthsV1::from(dates), calendared = "gregory" - ), + ); +impl_data_provider! ( BuddhistDateLengthsV1Marker, |dates, _| DateLengthsV1::from(dates), calendared = "buddhist" - ), + ); +impl_data_provider! ( JapaneseDateLengthsV1Marker, |dates, _| DateLengthsV1::from(dates), calendared = "japanese" - ), + ); +impl_data_provider! ( JapaneseExtendedDateLengthsV1Marker, |dates, _| DateLengthsV1::from(dates), calendared = "japanext" - ), + ); +impl_data_provider! ( CopticDateLengthsV1Marker, |dates, _| DateLengthsV1::from(dates), calendared = "coptic" - ), + ); +impl_data_provider! ( IndianDateLengthsV1Marker, |dates, _| DateLengthsV1::from(dates), calendared = "indian" - ), + ); +impl_data_provider! ( EthiopicDateLengthsV1Marker, |dates, _| DateLengthsV1::from(dates), calendared = "ethiopic" - ), + ); +impl_data_provider! ( TimeLengthsV1Marker, |dates, _| TimeLengthsV1::from(dates), calendared = "false" - ) -); + ); #[cfg(test)] mod test { From a3faef0b1d0e335e133e52cdc38540743ae0a55a Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Fri, 12 Aug 2022 14:12:50 -0700 Subject: [PATCH 07/17] Datagen compiling --- components/datetime/Cargo.toml | 7 +++-- components/datetime/src/fields/mod.rs | 2 +- components/datetime/src/fields/symbols.rs | 4 +-- components/datetime/src/lib.rs | 2 +- components/datetime/src/options/mod.rs | 2 +- components/datetime/src/pattern/hour_cycle.rs | 4 +-- .../datetime/src/pattern/runtime/helpers.rs | 2 +- .../datetime/src/provider/calendar/mod.rs | 4 +-- .../src/provider/calendar/skeletons.rs | 28 ++++++++++++++----- .../src/transform/cldr/datetime/mod.rs | 1 - 10 files changed, 36 insertions(+), 20 deletions(-) diff --git a/components/datetime/Cargo.toml b/components/datetime/Cargo.toml index 8010800d59e..8968967e755 100644 --- a/components/datetime/Cargo.toml +++ b/components/datetime/Cargo.toml @@ -72,9 +72,12 @@ bench = false # This option is required for Benchmark CI std = ["icu_provider/std", "icu_locid/std", "icu_calendar/std"] default = [] bench = ["serde"] -experimental = [] +# experimental_skeleton_matching is the minimal set of skeleton features required for datagen. +experimental_skeleton_matching = [] +# experimental is the full set of skeleton and component APIs. +experimental = ["experimental_skeleton_matching"] serde = ["dep:serde", "litemap/serde", "zerovec/serde", "tinystr/serde", "smallvec/serde", "icu_calendar/serde", "icu_decimal/serde", "icu_provider/serde", "icu_plurals/serde", "icu_timezone/serde"] -datagen = ["serde", "icu_calendar/datagen", "icu_timezone/datagen", "icu_provider/datagen", "std", "databake"] +datagen = ["serde", "experimental_skeleton_matching", "icu_calendar/datagen", "icu_timezone/datagen", "icu_provider/datagen", "std", "databake"] [[bench]] name = "datetime" diff --git a/components/datetime/src/fields/mod.rs b/components/datetime/src/fields/mod.rs index 90c704a3c3b..a3fa362fe4d 100644 --- a/components/datetime/src/fields/mod.rs +++ b/components/datetime/src/fields/mod.rs @@ -55,7 +55,7 @@ pub struct Field { } impl Field { - #[cfg(feature = "experimental")] // only referenced in experimental code + #[cfg(feature = "experimental_skeleton_matching")] // only referenced in experimental code pub(crate) fn get_length_type(&self) -> TextOrNumeric { match self.symbol { FieldSymbol::Era => TextOrNumeric::Text, diff --git a/components/datetime/src/fields/symbols.rs b/components/datetime/src/fields/symbols.rs index 10aeb2cd220..0af54a26bd2 100644 --- a/components/datetime/src/fields/symbols.rs +++ b/components/datetime/src/fields/symbols.rs @@ -138,7 +138,7 @@ impl FieldSymbol { } /// Returns the index associated with this FieldSymbol. - #[cfg(feature = "experimental")] // only referenced in experimental code + #[cfg(feature = "experimental_skeleton_matching")] // only referenced in experimental code fn discriminant_idx(&self) -> u8 { match self { FieldSymbol::Era => 0, @@ -157,7 +157,7 @@ impl FieldSymbol { /// Compares this enum with other solely based on the enum variant, /// ignoring the enum's data. - #[cfg(feature = "experimental")] // only referenced in experimental code + #[cfg(feature = "experimental_skeleton_matching")] // only referenced in experimental code pub(crate) fn discriminant_cmp(&self, other: &Self) -> Ordering { self.discriminant_idx().cmp(&other.discriminant_idx()) } diff --git a/components/datetime/src/lib.rs b/components/datetime/src/lib.rs index 95a141c0072..4eda0d671ea 100644 --- a/components/datetime/src/lib.rs +++ b/components/datetime/src/lib.rs @@ -120,7 +120,7 @@ pub mod provider; pub(crate) mod raw; #[doc(hidden)] #[allow(clippy::exhaustive_structs, clippy::exhaustive_enums)] // private-ish module -#[cfg(feature = "experimental")] +#[cfg(feature = "experimental_skeleton_matching")] pub mod skeleton; #[allow(missing_docs)] // TODO(#686) - Add missing docs. pub mod time_zone; diff --git a/components/datetime/src/options/mod.rs b/components/datetime/src/options/mod.rs index 495848781da..dfe9f0683a5 100644 --- a/components/datetime/src/options/mod.rs +++ b/components/datetime/src/options/mod.rs @@ -23,7 +23,7 @@ //! At the moment only the [`length::Bag`] works, and we plan to extend that to support //! `ECMA402`-like components bag later. -#[cfg(feature = "experimental")] +#[cfg(feature = "experimental_skeleton_matching")] pub mod components; pub mod length; pub mod preferences; diff --git a/components/datetime/src/pattern/hour_cycle.rs b/components/datetime/src/pattern/hour_cycle.rs index fcc53bfa519..becc38f7e8d 100644 --- a/components/datetime/src/pattern/hour_cycle.rs +++ b/components/datetime/src/pattern/hour_cycle.rs @@ -4,7 +4,7 @@ use super::{reference, runtime, PatternItem}; use crate::{fields, options::preferences}; -#[cfg(all(feature = "datagen", feature = "experimental"))] +#[cfg(all(feature = "datagen"))] use crate::{provider, skeleton}; use icu_provider::{yoke, zerofrom}; @@ -56,7 +56,7 @@ impl CoarseHourCycle { /// Invoke the pattern matching machinery to transform the hour cycle of a pattern. This provides /// a safe mapping from a h11/h12 to h23/h24 for transforms. #[doc(hidden)] - #[cfg(all(feature = "datagen", feature = "experimental"))] + #[cfg(all(feature = "datagen"))] pub fn apply_on_pattern<'data>( &self, date_time: &provider::calendar::patterns::GenericLengthPatternsV1<'data>, diff --git a/components/datetime/src/pattern/runtime/helpers.rs b/components/datetime/src/pattern/runtime/helpers.rs index 80df7adf080..e14d2f32269 100644 --- a/components/datetime/src/pattern/runtime/helpers.rs +++ b/components/datetime/src/pattern/runtime/helpers.rs @@ -38,7 +38,7 @@ pub fn maybe_replace_first(pattern: &mut Pattern, f: impl Fn(&PatternItem) -> Op /// /// For a variant that replaces just the first matching instance, /// see `maybe_replace_first`. -#[cfg(feature = "experimental")] // only referenced in experimental code +#[cfg(feature = "experimental_skeleton_matching")] // only referenced in experimental code pub fn maybe_replace(pattern: &mut Pattern, f: impl Fn(&PatternItem) -> Option) { let result = pattern .items diff --git a/components/datetime/src/provider/calendar/mod.rs b/components/datetime/src/provider/calendar/mod.rs index e5dbb66f974..efc6c52a029 100644 --- a/components/datetime/src/provider/calendar/mod.rs +++ b/components/datetime/src/provider/calendar/mod.rs @@ -6,14 +6,14 @@ #![allow(missing_docs)] // TODO(#686) - Add missing docs. -#[cfg(feature = "experimental")] +#[cfg(feature = "experimental_skeleton_matching")] mod skeletons; mod symbols; use crate::pattern; use icu_provider::prelude::*; use icu_provider::{yoke, zerofrom}; -#[cfg(feature = "experimental")] +#[cfg(feature = "experimental_skeleton_matching")] pub use skeletons::*; pub use symbols::*; diff --git a/components/datetime/src/provider/calendar/skeletons.rs b/components/datetime/src/provider/calendar/skeletons.rs index 3c1d3e982ac..83961a58f47 100644 --- a/components/datetime/src/provider/calendar/skeletons.rs +++ b/components/datetime/src/provider/calendar/skeletons.rs @@ -9,14 +9,17 @@ use crate::{ skeleton::{reference::Skeleton, SkeletonError}, }; use core::convert::TryFrom; +use icu_provider::prelude::*; use icu_provider::{yoke, zerofrom}; use litemap::LiteMap; -#[icu_provider::data_struct(marker( - DateSkeletonPatternsV1Marker, - "datetime/skeletons@1", - extension_key = "ca" -))] +// Manually implement DataMarker so that we can keep it in the proper experimental feature +// #[icu_provider::data_struct(marker( +// DateSkeletonPatternsV1Marker, +// "datetime/skeletons@1", +// extension_key = "ca" +// ))] +#[derive(yoke::Yokeable, zerofrom::ZeroFrom)] #[derive(Debug, PartialEq, Clone, Default)] #[cfg_attr(feature = "datagen", derive(serde::Serialize))] #[cfg_attr(feature = "serde", derive(serde::Deserialize))] @@ -26,6 +29,17 @@ pub struct DateSkeletonPatternsV1<'data>( pub LiteMap>, ); +#[cfg(feature = "experimental")] +pub struct DateSkeletonPatternsV1Marker; +#[cfg(feature = "experimental")] +impl DataMarker for DateSkeletonPatternsV1Marker { + type Yokeable = DateSkeletonPatternsV1<'static>; +} +#[cfg(feature = "experimental")] +impl KeyedDataMarker for DateSkeletonPatternsV1Marker { + const KEY: DataKey = icu_provider::data_key!("datetime/skeletons@1[u-ca]"); +} + /// This struct is a public wrapper around the internal `Skeleton` struct. This allows /// access to the serialization and deserialization capabilities, without exposing the /// internals of the skeleton machinery. @@ -72,14 +86,14 @@ impl databake::Bake for DateSkeletonPatternsV1<'_> { } } -#[cfg(feature = "datagen")] +#[cfg(all(feature = "datagen", feature = "experimental"))] impl Default for DateSkeletonPatternsV1Marker { fn default() -> Self { Self } } -#[cfg(feature = "datagen")] +#[cfg(all(feature = "datagen", feature = "experimental"))] impl databake::Bake for DateSkeletonPatternsV1Marker { fn bake(&self, env: &databake::CrateEnv) -> databake::TokenStream { env.insert("icu_datetime"); diff --git a/provider/datagen/src/transform/cldr/datetime/mod.rs b/provider/datagen/src/transform/cldr/datetime/mod.rs index 709cebff123..3f2c9d9ff79 100644 --- a/provider/datagen/src/transform/cldr/datetime/mod.rs +++ b/provider/datagen/src/transform/cldr/datetime/mod.rs @@ -14,7 +14,6 @@ use std::collections::HashSet; use std::str::FromStr; mod patterns; -#[cfg(feature = "experimental")] mod skeletons; mod symbols; pub mod week_data; From 95a691dbac73fb084e364ee328a3084680bc389c Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Fri, 12 Aug 2022 14:24:11 -0700 Subject: [PATCH 08/17] Small fixes --- components/datetime/src/raw/datetime.rs | 5 ++--- provider/datagen/src/transform/cldr/datetime/mod.rs | 1 + 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/components/datetime/src/raw/datetime.rs b/components/datetime/src/raw/datetime.rs index c911b161102..f5da1bbfc27 100644 --- a/components/datetime/src/raw/datetime.rs +++ b/components/datetime/src/raw/datetime.rs @@ -185,7 +185,7 @@ impl DateFormatter { data_provider: &D, patterns_data: DataPayload, symbols_data_fn: impl FnOnce() -> Result, DataError>, - mut locale: DataLocale, + locale: DataLocale, length: length::Date, ) -> Result where @@ -386,7 +386,7 @@ impl DateTimeFormatter { data_provider: &D, patterns: DataPayload, symbols_data_fn: impl FnOnce() -> Result, DataError>, - mut locale: DataLocale, + locale: DataLocale, ) -> Result where D: DataProvider @@ -397,7 +397,6 @@ impl DateTimeFormatter { + ?Sized, { debug_assert!(locale.get_unicode_ext(&key!("ca")) != Some(value!("ethioaa"))); - let cal = locale.get_unicode_ext(&key!("ca")); let required = datetime::analyze_patterns(&patterns.get().0, false) .map_err(|field| DateTimeFormatterError::UnsupportedField(field.symbol))?; diff --git a/provider/datagen/src/transform/cldr/datetime/mod.rs b/provider/datagen/src/transform/cldr/datetime/mod.rs index 3f2c9d9ff79..a28d4436aeb 100644 --- a/provider/datagen/src/transform/cldr/datetime/mod.rs +++ b/provider/datagen/src/transform/cldr/datetime/mod.rs @@ -355,6 +355,7 @@ mod test { } #[test] + #[cfg(feature = "experimental")] fn test_datetime_skeletons() { use std::convert::TryFrom; From a20f85f25925d50afdf4eb067ccbcdb2950044a9 Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Fri, 12 Aug 2022 14:24:26 -0700 Subject: [PATCH 09/17] fmt --- .../src/provider/calendar/skeletons.rs | 3 +- components/datetime/src/provider/date_time.rs | 8 +- components/datetime/tests/datetime.rs | 21 +- .../src/transform/cldr/datetime/mod.rs | 551 ++++++++++-------- 4 files changed, 322 insertions(+), 261 deletions(-) diff --git a/components/datetime/src/provider/calendar/skeletons.rs b/components/datetime/src/provider/calendar/skeletons.rs index 83961a58f47..b8e432a9ba5 100644 --- a/components/datetime/src/provider/calendar/skeletons.rs +++ b/components/datetime/src/provider/calendar/skeletons.rs @@ -19,8 +19,7 @@ use litemap::LiteMap; // "datetime/skeletons@1", // extension_key = "ca" // ))] -#[derive(yoke::Yokeable, zerofrom::ZeroFrom)] -#[derive(Debug, PartialEq, Clone, Default)] +#[derive(yoke::Yokeable, zerofrom::ZeroFrom, Debug, PartialEq, Clone, Default)] #[cfg_attr(feature = "datagen", derive(serde::Serialize))] #[cfg_attr(feature = "serde", derive(serde::Deserialize))] pub struct DateSkeletonPatternsV1<'data>( diff --git a/components/datetime/src/provider/date_time.rs b/components/datetime/src/provider/date_time.rs index 8a293f6bee4..4355a1914b4 100644 --- a/components/datetime/src/provider/date_time.rs +++ b/components/datetime/src/provider/date_time.rs @@ -145,7 +145,9 @@ where locale: &'a DataLocale, options: &DateTimeFormatterOptions, ) -> Result> { - debug_assert!(locale.get_unicode_ext(&icu_locid::extensions_unicode_key!("ca")).is_some()); + debug_assert!(locale + .get_unicode_ext(&icu_locid::extensions_unicode_key!("ca")) + .is_some()); let selector = PatternSelector { data_provider, date_patterns_data, @@ -227,7 +229,9 @@ where locale: &'a DataLocale, options: &DateTimeFormatterOptions, ) -> Result> { - debug_assert!(locale.get_unicode_ext(&icu_locid::extensions_unicode_key!("ca")).is_some()); + debug_assert!(locale + .get_unicode_ext(&icu_locid::extensions_unicode_key!("ca")) + .is_some()); let selector = PatternSelector { data_provider, date_patterns_data, diff --git a/components/datetime/tests/datetime.rs b/components/datetime/tests/datetime.rs index 998db2ec619..996ce39a1af 100644 --- a/components/datetime/tests/datetime.rs +++ b/components/datetime/tests/datetime.rs @@ -183,7 +183,7 @@ fn assert_fixture_element( A: AsCalendar, A::Calendar: CldrCalendar, A::Calendar: IncludedInAnyCalendar, - D: BufferProvider + D: BufferProvider, { let any_input = input_value.to_any(); let iso_any_input = input_iso.to_any(); @@ -198,7 +198,8 @@ fn assert_fixture_element( assert_eq!(result, output_value, "{}", description); let any_dtf = - DateTimeFormatter::try_new_with_buffer_provider(provider, &locale.into(), options.clone()).unwrap(); + DateTimeFormatter::try_new_with_buffer_provider(provider, &locale.into(), options.clone()) + .unwrap(); let result = any_dtf.format_to_string(&any_input).unwrap(); assert_eq!(result, output_value, "(DateTimeFormatter) {}", description); @@ -231,8 +232,12 @@ fn assert_fixture_element( bag.date.unwrap(), ) .unwrap(); - let tf = TimeFormatter::try_new_with_buffer_provider(provider, &locale.into(), bag.time.unwrap()) - .unwrap(); + let tf = TimeFormatter::try_new_with_buffer_provider( + provider, + &locale.into(), + bag.time.unwrap(), + ) + .unwrap(); let dtf = TypedDateTimeFormatter::try_from_date_and_time(df, tf).unwrap(); let result = dtf.format_to_string(input_value); @@ -273,8 +278,12 @@ fn assert_fixture_element( write!(s, "{}", fdt).unwrap(); assert_eq!(s, output_value, "{}", description); } else if bag.time.is_some() { - let tf = TimeFormatter::try_new_with_buffer_provider(provider, &locale.into(), bag.time.unwrap()) - .unwrap(); + let tf = TimeFormatter::try_new_with_buffer_provider( + provider, + &locale.into(), + bag.time.unwrap(), + ) + .unwrap(); let result = tf.format_to_string(input_value); diff --git a/provider/datagen/src/transform/cldr/datetime/mod.rs b/provider/datagen/src/transform/cldr/datetime/mod.rs index a28d4436aeb..4781bb0bebd 100644 --- a/provider/datagen/src/transform/cldr/datetime/mod.rs +++ b/provider/datagen/src/transform/cldr/datetime/mod.rs @@ -35,143 +35,206 @@ lazy_static! { macro_rules! impl_data_provider { ($marker:ident, $expr:expr, calendared = $calendared:expr) => { - impl DataProvider<$marker> for crate::DatagenProvider { - fn load( - &self, - req: DataRequest, - ) -> Result, DataError> { - if $calendared == "locale" && req.locale.is_empty() { - return Err(DataErrorKind::NeedsLocale.into_error()); - } - - let langid = req.locale.get_langid(); - let calendar = if $calendared == "locale" { - req - .locale - .get_unicode_ext(&key!("ca")) - .ok_or_else(|| DataErrorKind::MissingLocale.into_error())? - } else if $calendared == "false" { - value!("gregory") - } else { - value!($calendared) - }; - - let cldr_cal = SUPPORTED_CALS - .get(&calendar) - .ok_or_else(|| DataErrorKind::MissingLocale.into_error())?; + impl DataProvider<$marker> for crate::DatagenProvider { + fn load(&self, req: DataRequest) -> Result, DataError> { + if $calendared == "locale" && req.locale.is_empty() { + return Err(DataErrorKind::NeedsLocale.into_error()); + } - let resource: &cldr_serde::ca::Resource = self + let langid = req.locale.get_langid(); + let calendar = if $calendared == "locale" { + req.locale + .get_unicode_ext(&key!("ca")) + .ok_or_else(|| DataErrorKind::MissingLocale.into_error())? + } else if $calendared == "false" { + value!("gregory") + } else { + value!($calendared) + }; + + let cldr_cal = SUPPORTED_CALS + .get(&calendar) + .ok_or_else(|| DataErrorKind::MissingLocale.into_error())?; + + let resource: &cldr_serde::ca::Resource = self + .source + .cldr()? + .dates(cldr_cal) + .read_and_parse(&langid, &format!("ca-{}.json", cldr_cal))?; + + let mut data = resource + .main + .0 + .get(&langid) + .expect("CLDR file contains the expected language") + .dates + .calendars + .get(*cldr_cal) + .expect("CLDR file contains the expected calendar") + .clone(); + + // CLDR treats ethiopic and ethioaa as separate calendars; however we treat them as a single resource key that + // supports symbols for both era patterns based on the settings on the date. Load in ethioaa data as well when dealing with + // ethiopic. + if calendar == value!("ethiopic") { + let ethioaa: &cldr_serde::ca::Resource = self .source .cldr()? - .dates(cldr_cal).read_and_parse(&langid, &format!("ca-{}.json", cldr_cal))?; - - let mut data = - resource - .main - .0 - .get(&langid) - .expect("CLDR file contains the expected language") - .dates - .calendars - .get(*cldr_cal) - .expect("CLDR file contains the expected calendar") - .clone(); - - // CLDR treats ethiopic and ethioaa as separate calendars; however we treat them as a single resource key that - // supports symbols for both era patterns based on the settings on the date. Load in ethioaa data as well when dealing with - // ethiopic. - if calendar == value!("ethiopic") { - let ethioaa: &cldr_serde::ca::Resource = self.source.cldr()?.dates("ethiopic").read_and_parse(&langid, "ca-ethiopic-amete-alem.json")?; - - let ethioaa_data = ethioaa - .main - .0 - .get(&langid) - .expect("CLDR ca-ethiopic-amete-alem.json contains the expected language") - .dates - .calendars - .get("ethiopic-amete-alem") - .expect("CLDR ca-ethiopic-amete-alem.json contains the expected calendar") - .clone(); - - let mundi_name = ethioaa_data.eras.names.get("0").expect("ethiopic-amete-alem calendar must have 0 era"); - let mundi_abbr = ethioaa_data.eras.abbr.get("0").expect("ethiopic-amete-alem calendar must have 0 era"); - let mundi_narrow = ethioaa_data.eras.narrow.get("0").expect("ethiopic-amete-alem calendar must have 0 era"); - - data.eras.names.insert("2".to_string(), mundi_name.clone()); - data.eras.abbr.insert("2".to_string(), mundi_abbr.clone()); - data.eras.narrow.insert("2".to_string(), mundi_narrow.clone()); - } + .dates("ethiopic") + .read_and_parse(&langid, "ca-ethiopic-amete-alem.json")?; + + let ethioaa_data = ethioaa + .main + .0 + .get(&langid) + .expect("CLDR ca-ethiopic-amete-alem.json contains the expected language") + .dates + .calendars + .get("ethiopic-amete-alem") + .expect("CLDR ca-ethiopic-amete-alem.json contains the expected calendar") + .clone(); + + let mundi_name = ethioaa_data + .eras + .names + .get("0") + .expect("ethiopic-amete-alem calendar must have 0 era"); + let mundi_abbr = ethioaa_data + .eras + .abbr + .get("0") + .expect("ethiopic-amete-alem calendar must have 0 era"); + let mundi_narrow = ethioaa_data + .eras + .narrow + .get("0") + .expect("ethiopic-amete-alem calendar must have 0 era"); + + data.eras.names.insert("2".to_string(), mundi_name.clone()); + data.eras.abbr.insert("2".to_string(), mundi_abbr.clone()); + data.eras + .narrow + .insert("2".to_string(), mundi_narrow.clone()); + } - if calendar == value!("japanese") { - let era_dates: &cldr_serde::japanese::Resource = self - .source - .cldr()? - .core() - .read_and_parse("supplemental/calendarData.json")?; - let mut set = HashSet::::new(); - for (era_index, date) in era_dates.supplemental.calendar_data.japanese.eras.iter() { - let start_date = EraStartDate::from_str(&date.start).map_err(|_| { - DataError::custom("calendarData.json contains unparseable data for a japanese era") - .with_display_context(&format!("era index {}", era_index)) - })?; - - if start_date.year >= 1868 { - set.insert(era_index.into()); - } + if calendar == value!("japanese") { + let era_dates: &cldr_serde::japanese::Resource = self + .source + .cldr()? + .core() + .read_and_parse("supplemental/calendarData.json")?; + let mut set = HashSet::::new(); + for (era_index, date) in + era_dates.supplemental.calendar_data.japanese.eras.iter() + { + let start_date = EraStartDate::from_str(&date.start).map_err(|_| { + DataError::custom( + "calendarData.json contains unparseable data for a japanese era", + ) + .with_display_context(&format!("era index {}", era_index)) + })?; + + if start_date.year >= 1868 { + set.insert(era_index.into()); } - - data.eras.names.retain(|e, _| set.contains(e)); - data.eras.abbr.retain(|e, _| set.contains(e)); - data.eras.narrow.retain(|e, _| set.contains(e)); - } - if calendar == value!("japanese") || calendar == value!("japanext") { - - // Splice in gregorian data for pre-meiji - let greg_resource: &cldr_serde::ca::Resource = self - .source - .cldr()? - .dates("gregorian").read_and_parse(&langid, "ca-gregorian.json")?; - - let greg = - greg_resource - .main - .0 - .get(&langid) - .expect("CLDR file contains the expected language") - .dates - .calendars - .get("gregorian") - .expect("CLDR file contains a gregorian calendar") - .clone(); - - // The "eras" map is largely keyed by a number, but instead of trying to - // come up with a number that the japanese era map would not use, we just use a regular string - data.eras.names.insert("bce".into(), greg.eras.names.get("0").expect("Gregorian calendar must have data for BC").into()); - data.eras.names.insert("ce".into(), greg.eras.names.get("1").expect("Gregorian calendar must have data for AD").into()); - data.eras.abbr.insert("bce".into(), greg.eras.abbr.get("0").expect("Gregorian calendar must have data for BC").into()); - data.eras.abbr.insert("ce".into(), greg.eras.abbr.get("1").expect("Gregorian calendar must have data for AD").into()); - data.eras.narrow.insert("bce".into(), greg.eras.narrow.get("0").expect("Gregorian calendar must have data for BC").into()); - data.eras.narrow.insert("ce".into(), greg.eras.narrow.get("1").expect("Gregorian calendar must have data for AD").into()); } - Ok(DataResponse { - metadata: Default::default(), - #[allow(clippy::redundant_closure_call)] - payload: Some(DataPayload::from_owned(($expr)(&data, &calendar.to_string()))), - }) + data.eras.names.retain(|e, _| set.contains(e)); + data.eras.abbr.retain(|e, _| set.contains(e)); + data.eras.narrow.retain(|e, _| set.contains(e)); + } + if calendar == value!("japanese") || calendar == value!("japanext") { + // Splice in gregorian data for pre-meiji + let greg_resource: &cldr_serde::ca::Resource = self + .source + .cldr()? + .dates("gregorian") + .read_and_parse(&langid, "ca-gregorian.json")?; + + let greg = greg_resource + .main + .0 + .get(&langid) + .expect("CLDR file contains the expected language") + .dates + .calendars + .get("gregorian") + .expect("CLDR file contains a gregorian calendar") + .clone(); + + // The "eras" map is largely keyed by a number, but instead of trying to + // come up with a number that the japanese era map would not use, we just use a regular string + data.eras.names.insert( + "bce".into(), + greg.eras + .names + .get("0") + .expect("Gregorian calendar must have data for BC") + .into(), + ); + data.eras.names.insert( + "ce".into(), + greg.eras + .names + .get("1") + .expect("Gregorian calendar must have data for AD") + .into(), + ); + data.eras.abbr.insert( + "bce".into(), + greg.eras + .abbr + .get("0") + .expect("Gregorian calendar must have data for BC") + .into(), + ); + data.eras.abbr.insert( + "ce".into(), + greg.eras + .abbr + .get("1") + .expect("Gregorian calendar must have data for AD") + .into(), + ); + data.eras.narrow.insert( + "bce".into(), + greg.eras + .narrow + .get("0") + .expect("Gregorian calendar must have data for BC") + .into(), + ); + data.eras.narrow.insert( + "ce".into(), + greg.eras + .narrow + .get("1") + .expect("Gregorian calendar must have data for AD") + .into(), + ); } - } - impl IterableDataProvider<$marker> for crate::DatagenProvider { - fn supported_locales(&self) -> Result, DataError> { - let mut r = Vec::new(); - if $calendared == "locale" { - for (cal_value, cldr_cal) in &*SUPPORTED_CALS { - r.extend(self - .source - .cldr()? - .dates(cldr_cal).list_langs()? + Ok(DataResponse { + metadata: Default::default(), + #[allow(clippy::redundant_closure_call)] + payload: Some(DataPayload::from_owned(($expr)( + &data, + &calendar.to_string(), + ))), + }) + } + } + + impl IterableDataProvider<$marker> for crate::DatagenProvider { + fn supported_locales(&self) -> Result, DataError> { + let mut r = Vec::new(); + if $calendared == "locale" { + for (cal_value, cldr_cal) in &*SUPPORTED_CALS { + r.extend( + self.source + .cldr()? + .dates(cldr_cal) + .list_langs()? .map(|lid| { let mut locale: Locale = lid.into(); locale @@ -180,136 +243,122 @@ macro_rules! impl_data_provider { .keywords .set(key!("ca"), cal_value.clone()); DataLocale::from(locale) - })); - } - } else { - let calendar = if $calendared == "false" { - value!("gregory") - } else { - value!($calendared) - }; - let cldr_cal = SUPPORTED_CALS - .get(&calendar) - .ok_or_else(|| DataErrorKind::MissingLocale.into_error())?; - r.extend(self - .source - .cldr()? - .dates(cldr_cal).list_langs()? - .map(|lid| { - let locale: Locale = lid.into(); - DataLocale::from(locale) - })); + }), + ); } - - Ok(r) + } else { + let calendar = if $calendared == "false" { + value!("gregory") + } else { + value!($calendared) + }; + let cldr_cal = SUPPORTED_CALS + .get(&calendar) + .ok_or_else(|| DataErrorKind::MissingLocale.into_error())?; + r.extend( + self.source + .cldr()? + .dates(cldr_cal) + .list_langs()? + .map(|lid| { + let locale: Locale = lid.into(); + DataLocale::from(locale) + }), + ); } + + Ok(r) } + } }; } -impl_data_provider! - ( - GregorianDateSymbolsV1Marker, - symbols::convert_dates, - calendared = "gregory" - ); -impl_data_provider! - ( - BuddhistDateSymbolsV1Marker, - symbols::convert_dates, - calendared = "buddhist" - ); -impl_data_provider! - ( - JapaneseDateSymbolsV1Marker, - symbols::convert_dates, - calendared = "japanese" - ); -impl_data_provider! - ( - JapaneseExtendedDateSymbolsV1Marker, - symbols::convert_dates, - calendared = "japanext" - ); -impl_data_provider! - ( - CopticDateSymbolsV1Marker, - symbols::convert_dates, - calendared = "coptic" - ); -impl_data_provider! - ( - IndianDateSymbolsV1Marker, - symbols::convert_dates, - calendared = "indian" - ); -impl_data_provider! - ( - EthiopicDateSymbolsV1Marker, - symbols::convert_dates, - calendared = "ethiopic" - ); -impl_data_provider! - ( - TimeSymbolsV1Marker, - |dates, _| { symbols::convert_times(dates) }, - calendared = "false" - ); +impl_data_provider!( + GregorianDateSymbolsV1Marker, + symbols::convert_dates, + calendared = "gregory" +); +impl_data_provider!( + BuddhistDateSymbolsV1Marker, + symbols::convert_dates, + calendared = "buddhist" +); +impl_data_provider!( + JapaneseDateSymbolsV1Marker, + symbols::convert_dates, + calendared = "japanese" +); +impl_data_provider!( + JapaneseExtendedDateSymbolsV1Marker, + symbols::convert_dates, + calendared = "japanext" +); +impl_data_provider!( + CopticDateSymbolsV1Marker, + symbols::convert_dates, + calendared = "coptic" +); +impl_data_provider!( + IndianDateSymbolsV1Marker, + symbols::convert_dates, + calendared = "indian" +); +impl_data_provider!( + EthiopicDateSymbolsV1Marker, + symbols::convert_dates, + calendared = "ethiopic" +); +impl_data_provider!( + TimeSymbolsV1Marker, + |dates, _| { symbols::convert_times(dates) }, + calendared = "false" +); #[cfg(feature = "experimental")] -impl_data_provider! - ( - DateSkeletonPatternsV1Marker, - |dates, _| { DateSkeletonPatternsV1::from(dates) }, - calendared = "locale" - ); -impl_data_provider! - ( - GregorianDateLengthsV1Marker, - |dates, _| DateLengthsV1::from(dates), - calendared = "gregory" - ); -impl_data_provider! - ( - BuddhistDateLengthsV1Marker, - |dates, _| DateLengthsV1::from(dates), - calendared = "buddhist" - ); -impl_data_provider! - ( - JapaneseDateLengthsV1Marker, - |dates, _| DateLengthsV1::from(dates), - calendared = "japanese" - ); -impl_data_provider! - ( - JapaneseExtendedDateLengthsV1Marker, - |dates, _| DateLengthsV1::from(dates), - calendared = "japanext" - ); -impl_data_provider! - ( - CopticDateLengthsV1Marker, - |dates, _| DateLengthsV1::from(dates), - calendared = "coptic" - ); -impl_data_provider! - ( - IndianDateLengthsV1Marker, - |dates, _| DateLengthsV1::from(dates), - calendared = "indian" - ); -impl_data_provider! - ( - EthiopicDateLengthsV1Marker, - |dates, _| DateLengthsV1::from(dates), - calendared = "ethiopic" - ); -impl_data_provider! - ( - TimeLengthsV1Marker, - |dates, _| TimeLengthsV1::from(dates), - calendared = "false" - ); +impl_data_provider!( + DateSkeletonPatternsV1Marker, + |dates, _| { DateSkeletonPatternsV1::from(dates) }, + calendared = "locale" +); +impl_data_provider!( + GregorianDateLengthsV1Marker, + |dates, _| DateLengthsV1::from(dates), + calendared = "gregory" +); +impl_data_provider!( + BuddhistDateLengthsV1Marker, + |dates, _| DateLengthsV1::from(dates), + calendared = "buddhist" +); +impl_data_provider!( + JapaneseDateLengthsV1Marker, + |dates, _| DateLengthsV1::from(dates), + calendared = "japanese" +); +impl_data_provider!( + JapaneseExtendedDateLengthsV1Marker, + |dates, _| DateLengthsV1::from(dates), + calendared = "japanext" +); +impl_data_provider!( + CopticDateLengthsV1Marker, + |dates, _| DateLengthsV1::from(dates), + calendared = "coptic" +); +impl_data_provider!( + IndianDateLengthsV1Marker, + |dates, _| DateLengthsV1::from(dates), + calendared = "indian" +); +impl_data_provider!( + EthiopicDateLengthsV1Marker, + |dates, _| DateLengthsV1::from(dates), + calendared = "ethiopic" +); +impl_data_provider!( + TimeLengthsV1Marker, + |dates, _| TimeLengthsV1::from(dates), + calendared = "false" +); #[cfg(test)] mod test { From fa0fdccf8b74f41bfa8a006cc0cbae89642fec46 Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Fri, 12 Aug 2022 14:26:22 -0700 Subject: [PATCH 10/17] clippy --- provider/datagen/src/databake.rs | 1 + provider/datagen/src/transform/cldr/datetime/mod.rs | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/provider/datagen/src/databake.rs b/provider/datagen/src/databake.rs index 6ed956ea144..f8cd9d3a43c 100644 --- a/provider/datagen/src/databake.rs +++ b/provider/datagen/src/databake.rs @@ -214,6 +214,7 @@ impl DataExporter for BakedDataExporter { supers = quote! { super:: #supers }; } + #[allow(unused_mut)] let mut struct_type = quote! { <#marker as ::icu_provider::DataMarker>::Yokeable }; diff --git a/provider/datagen/src/transform/cldr/datetime/mod.rs b/provider/datagen/src/transform/cldr/datetime/mod.rs index 4781bb0bebd..6e27f7b8a81 100644 --- a/provider/datagen/src/transform/cldr/datetime/mod.rs +++ b/provider/datagen/src/transform/cldr/datetime/mod.rs @@ -363,9 +363,7 @@ impl_data_provider!( #[cfg(test)] mod test { use super::*; - use icu_datetime::pattern::runtime::{Pattern, PluralPattern}; use icu_locid::locale; - use icu_plurals::PluralCategory; #[test] fn test_basic_patterns() { @@ -406,6 +404,8 @@ mod test { #[test] #[cfg(feature = "experimental")] fn test_datetime_skeletons() { + use icu_datetime::pattern::runtime::{Pattern, PluralPattern}; + use icu_plurals::PluralCategory; use std::convert::TryFrom; let provider = crate::DatagenProvider::for_test(); From 5cc4e384665490da651ee4c95153e3bef6b29b86 Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Fri, 12 Aug 2022 15:49:26 -0700 Subject: [PATCH 11/17] Merge fixes --- components/datetime/src/any/datetime.rs | 19 ++++--------------- components/datetime/src/any/zoned_datetime.rs | 19 ++++--------------- components/datetime/tests/datetime.rs | 2 +- 3 files changed, 9 insertions(+), 31 deletions(-) diff --git a/components/datetime/src/any/datetime.rs b/components/datetime/src/any/datetime.rs index 0c370830ccb..9b8b53b7975 100644 --- a/components/datetime/src/any/datetime.rs +++ b/components/datetime/src/any/datetime.rs @@ -310,25 +310,14 @@ impl DateTimeFormatter { // separately into the raw formatter. let mut locale_with_cal = locale.clone(); - // TODO (#2038), DO NOT SHIP 1.0 without fixing this - let kind = if let Ok(kind) = AnyCalendarKind::from_data_locale(&locale_with_cal) { - kind - } else { - locale_with_cal.set_unicode_ext(key!("ca"), value!("gregory")); - AnyCalendarKind::Gregorian - }; - - // We share data under ethiopic - if kind == AnyCalendarKind::Ethioaa { - locale_with_cal.set_unicode_ext(key!("ca"), value!("ethiopic")); - } - - let calendar = AnyCalendar::try_new_unstable(data_provider, kind)?; + let calendar = AnyCalendar::try_new_for_locale_unstable(data_provider, &locale_with_cal)?; + let kind = calendar.kind(); + kind.set_on_data_locale(&mut locale_with_cal); let patterns = PatternSelector::for_options( data_provider, calendar::load_lengths_for_any_calendar_kind(data_provider, locale, kind)?, - &locale, + &locale_with_cal, &options, )?; diff --git a/components/datetime/src/any/zoned_datetime.rs b/components/datetime/src/any/zoned_datetime.rs index a3ad986e48f..ac4e4f24ce3 100644 --- a/components/datetime/src/any/zoned_datetime.rs +++ b/components/datetime/src/any/zoned_datetime.rs @@ -222,25 +222,14 @@ impl ZonedDateTimeFormatter { // separately into the raw formatter. let mut locale_with_cal = locale.clone(); - // TODO (#2038), DO NOT SHIP 1.0 without fixing this - let kind = if let Ok(kind) = AnyCalendarKind::from_data_locale(&locale_with_cal) { - kind - } else { - locale_with_cal.set_unicode_ext(key!("ca"), value!("gregory")); - AnyCalendarKind::Gregorian - }; - - // We share data under ethiopic - if kind == AnyCalendarKind::Ethioaa { - locale_with_cal.set_unicode_ext(key!("ca"), value!("ethiopic")); - } - - let calendar = AnyCalendar::try_new_unstable(provider, kind)?; + let calendar = AnyCalendar::try_new_for_locale_unstable(data_provider, &locale_with_cal)?; + let kind = calendar.kind(); + kind.set_on_data_locale(&mut locale_with_cal); let patterns = PatternSelector::for_options( provider, calendar::load_lengths_for_any_calendar_kind(provider, locale, kind)?, - &locale, + &locale_with_cal, &date_time_format_options, )?; diff --git a/components/datetime/tests/datetime.rs b/components/datetime/tests/datetime.rs index 996ce39a1af..6ab6d893fe1 100644 --- a/components/datetime/tests/datetime.rs +++ b/components/datetime/tests/datetime.rs @@ -199,7 +199,7 @@ fn assert_fixture_element( let any_dtf = DateTimeFormatter::try_new_with_buffer_provider(provider, &locale.into(), options.clone()) - .unwrap(); + .expect(description); let result = any_dtf.format_to_string(&any_input).unwrap(); assert_eq!(result, output_value, "(DateTimeFormatter) {}", description); From 138f9bacc57f30fc9fa64454f013d90e55290a48 Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Fri, 12 Aug 2022 18:06:16 -0700 Subject: [PATCH 12/17] Assorted feature tweaks --- Cargo.lock | 1 - components/datetime/Cargo.toml | 3 +-- components/datetime/src/any/datetime.rs | 1 + components/datetime/src/any/zoned_datetime.rs | 2 +- components/datetime/src/options/components.rs | 3 +++ components/datetime/src/provider/calendar/skeletons.rs | 7 +++---- components/icu/Cargo.toml | 4 ++-- components/icu/src/lib.rs | 1 - 8 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 202def61efc..9f22a48f1d4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1543,7 +1543,6 @@ dependencies = [ "icu", "icu_benchmark_macros", "icu_calendar", - "icu_datetime", "icu_decimal", "icu_locid", "icu_plurals", diff --git a/components/datetime/Cargo.toml b/components/datetime/Cargo.toml index 8968967e755..79d7803ed43 100644 --- a/components/datetime/Cargo.toml +++ b/components/datetime/Cargo.toml @@ -52,13 +52,12 @@ fixed_decimal = { version = "0.4", path = "../../utils/fixed_decimal" } [dev-dependencies] criterion = "0.3" -icu = { path = "../icu", default-features = false, features = ["experimental"] } +icu = { path = "../icu" } icu_benchmark_macros = { version = "0.7", path = "../../tools/benchmark/macros" } icu_provider = { version = "1.0.0-beta1", path = "../../provider/core" } icu_provider_adapters = { path = "../../provider/adapters" } icu_testdata = { path = "../../provider/testdata" } icu_calendar = { version = "1.0.0-beta1", path = "../calendar", features = ["serde"] } -icu_datetime = { path = "../../components/datetime", features = ["datagen"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" diff --git a/components/datetime/src/any/datetime.rs b/components/datetime/src/any/datetime.rs index 9b8b53b7975..1b1a6592ef5 100644 --- a/components/datetime/src/any/datetime.rs +++ b/components/datetime/src/any/datetime.rs @@ -513,6 +513,7 @@ where { } #[cfg(test)] +#[cfg(feature = "serde")] mod tests { use core::str::FromStr; use icu::calendar::{AnyCalendar, DateTime}; diff --git a/components/datetime/src/any/zoned_datetime.rs b/components/datetime/src/any/zoned_datetime.rs index ac4e4f24ce3..1c40ec68509 100644 --- a/components/datetime/src/any/zoned_datetime.rs +++ b/components/datetime/src/any/zoned_datetime.rs @@ -222,7 +222,7 @@ impl ZonedDateTimeFormatter { // separately into the raw formatter. let mut locale_with_cal = locale.clone(); - let calendar = AnyCalendar::try_new_for_locale_unstable(data_provider, &locale_with_cal)?; + let calendar = AnyCalendar::try_new_for_locale_unstable(provider, &locale_with_cal)?; let kind = calendar.kind(); kind.set_on_data_locale(&mut locale_with_cal); diff --git a/components/datetime/src/options/components.rs b/components/datetime/src/options/components.rs index 7bab67e1810..908263bbf58 100644 --- a/components/datetime/src/options/components.rs +++ b/components/datetime/src/options/components.rs @@ -70,11 +70,13 @@ //! *Note*: The exact result returned from [`TypedDateTimeFormatter`](crate::TypedDateTimeFormatter) is a subject to change over //! time. Formatted result should be treated as opaque and displayed to the user as-is, //! and it is strongly recommended to never write tests that expect a particular formatted output. + use crate::{ fields::{self, Field, FieldLength, FieldSymbol}, pattern::{runtime::PatternPlurals, PatternItem}, }; +#[cfg(feature = "experimental")] use alloc::vec::Vec; use super::preferences; @@ -127,6 +129,7 @@ impl Bag { /// Converts the components::Bag into a Vec. The fields will be ordered in from most /// significant field to least significant. This is the order the fields are listed in /// the UTS 35 table - https://unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table + #[cfg(feature = "experimental")] // only used in experimental code pub(crate) fn to_vec_fields(&self) -> Vec { let mut fields = Vec::new(); if let Some(era) = self.era { diff --git a/components/datetime/src/provider/calendar/skeletons.rs b/components/datetime/src/provider/calendar/skeletons.rs index b8e432a9ba5..63d3ecea1db 100644 --- a/components/datetime/src/provider/calendar/skeletons.rs +++ b/components/datetime/src/provider/calendar/skeletons.rs @@ -9,7 +9,6 @@ use crate::{ skeleton::{reference::Skeleton, SkeletonError}, }; use core::convert::TryFrom; -use icu_provider::prelude::*; use icu_provider::{yoke, zerofrom}; use litemap::LiteMap; @@ -31,12 +30,12 @@ pub struct DateSkeletonPatternsV1<'data>( #[cfg(feature = "experimental")] pub struct DateSkeletonPatternsV1Marker; #[cfg(feature = "experimental")] -impl DataMarker for DateSkeletonPatternsV1Marker { +impl icu_provider::DataMarker for DateSkeletonPatternsV1Marker { type Yokeable = DateSkeletonPatternsV1<'static>; } #[cfg(feature = "experimental")] -impl KeyedDataMarker for DateSkeletonPatternsV1Marker { - const KEY: DataKey = icu_provider::data_key!("datetime/skeletons@1[u-ca]"); +impl icu_provider::KeyedDataMarker for DateSkeletonPatternsV1Marker { + const KEY: icu_provider::DataKey = icu_provider::data_key!("datetime/skeletons@1[u-ca]"); } /// This struct is a public wrapper around the internal `Skeleton` struct. This allows diff --git a/components/icu/Cargo.toml b/components/icu/Cargo.toml index 1aaf1cefd42..3189b6de12c 100644 --- a/components/icu/Cargo.toml +++ b/components/icu/Cargo.toml @@ -38,7 +38,7 @@ icu_locid = { version = "1.0.0-beta1", path = "../locid", default-features = fal icu_normalizer = { version = "1.0.0-beta1", path = "../normalizer", default-features = false } icu_plurals = { version = "1.0.0-beta1", path = "../plurals", default-features = false } icu_properties = { version = "1.0.0-beta1", path = "../properties", default-features = false } -icu_timezone = { version = "1.0.0-beta1", path = "../timezone", default-features = false, optional = true } +icu_timezone = { version = "1.0.0-beta1", path = "../timezone", default-features = false } icu_segmenter = { version = "1.0.0-alpha1", path = "../../experimental/segmenter", default-features = false, optional = true } @@ -70,7 +70,7 @@ serde = [ serde_human = [ "icu_list/serde_human" ] -experimental = ["icu_segmenter", "icu_timezone", "icu_datetime/experimental"] +experimental = ["icu_segmenter", "icu_datetime/experimental"] [[example]] name = "tui" diff --git a/components/icu/src/lib.rs b/components/icu/src/lib.rs index eddc5e565ad..2e3bb5d898d 100644 --- a/components/icu/src/lib.rs +++ b/components/icu/src/lib.rs @@ -140,6 +140,5 @@ pub use icu_collections as collections; #[doc(inline)] pub use icu_segmenter as segmenter; -#[cfg(feature = "experimental")] #[doc(inline)] pub use icu_timezone as timezone; From cebb1960ef496480ba6c1844aa933f66924e3f56 Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Fri, 12 Aug 2022 18:22:28 -0700 Subject: [PATCH 13/17] More ethioaa refactoring to get tests to pass --- components/datetime/src/calendar.rs | 4 ---- components/datetime/src/provider/date_time.rs | 20 ++++++++++++------- components/datetime/src/raw/datetime.rs | 4 ---- components/datetime/src/raw/zoned_datetime.rs | 7 +------ 4 files changed, 14 insertions(+), 21 deletions(-) diff --git a/components/datetime/src/calendar.rs b/components/datetime/src/calendar.rs index 8c75eab0208..74178959d0e 100644 --- a/components/datetime/src/calendar.rs +++ b/components/datetime/src/calendar.rs @@ -105,10 +105,6 @@ pub(crate) fn potentially_fixup_calendar( locale.set_unicode_ext(key!("ca"), C::DEFAULT_BCP_47_IDENTIFIER); } - if locale.get_unicode_ext(&key!("ca")) == Some(value!("ethioaa")) { - locale.set_unicode_ext(key!("ca"), value!("ethiopic")); - } - Ok(()) } diff --git a/components/datetime/src/provider/date_time.rs b/components/datetime/src/provider/date_time.rs index 4355a1914b4..b602a6bcf61 100644 --- a/components/datetime/src/provider/date_time.rs +++ b/components/datetime/src/provider/date_time.rs @@ -145,9 +145,6 @@ where locale: &'a DataLocale, options: &DateTimeFormatterOptions, ) -> Result> { - debug_assert!(locale - .get_unicode_ext(&icu_locid::extensions_unicode_key!("ca")) - .is_some()); let selector = PatternSelector { data_provider, date_patterns_data, @@ -229,9 +226,6 @@ where locale: &'a DataLocale, options: &DateTimeFormatterOptions, ) -> Result> { - debug_assert!(locale - .get_unicode_ext(&icu_locid::extensions_unicode_key!("ca")) - .is_some()); let selector = PatternSelector { data_provider, date_patterns_data, @@ -272,10 +266,22 @@ where #[cfg(feature = "experimental")] fn skeleton_data_payload(&self) -> Result> { + use alloc::borrow::Cow; + use icu_locid::{extensions_unicode_key as key, extensions_unicode_value as value}; + let cal = self.locale.get_unicode_ext(&key!("ca")); + debug_assert!(cal.is_some()); + // Skeleton data for ethioaa is stored under ethiopic + let locale = if cal == Some(value!("ethioaa")) { + let mut locale = self.locale.clone(); + locale.set_unicode_ext(key!("ca"), value!("ethiopic")); + Cow::Owned(locale) + } else { + Cow::Borrowed(self.locale) + }; let data = self .data_provider .load(DataRequest { - locale: self.locale, + locale: &locale, metadata: Default::default(), })? .take_payload()?; diff --git a/components/datetime/src/raw/datetime.rs b/components/datetime/src/raw/datetime.rs index f5da1bbfc27..aab563c549f 100644 --- a/components/datetime/src/raw/datetime.rs +++ b/components/datetime/src/raw/datetime.rs @@ -30,7 +30,6 @@ use icu_decimal::{ provider::DecimalSymbolsV1Marker, FixedDecimalFormatter, }; -use icu_locid::{extensions_unicode_key as key, extensions_unicode_value as value}; use icu_plurals::{provider::OrdinalV1Marker, PluralRules}; use icu_provider::prelude::*; @@ -194,7 +193,6 @@ impl DateFormatter { + DataProvider + ?Sized, { - debug_assert!(locale.get_unicode_ext(&key!("ca")) != Some(value!("ethioaa"))); let patterns = provider::date_time::pattern_for_date_length(length, patterns_data.clone()); let generic_pattern = @@ -396,8 +394,6 @@ impl DateTimeFormatter { + DataProvider + ?Sized, { - debug_assert!(locale.get_unicode_ext(&key!("ca")) != Some(value!("ethioaa"))); - let required = datetime::analyze_patterns(&patterns.get().0, false) .map_err(|field| DateTimeFormatterError::UnsupportedField(field.symbol))?; diff --git a/components/datetime/src/raw/zoned_datetime.rs b/components/datetime/src/raw/zoned_datetime.rs index dd19905b216..ed0457009e7 100644 --- a/components/datetime/src/raw/zoned_datetime.rs +++ b/components/datetime/src/raw/zoned_datetime.rs @@ -8,7 +8,6 @@ use icu_decimal::{ provider::DecimalSymbolsV1Marker, FixedDecimalFormatter, }; -use icu_locid::{extensions_unicode_key as key, extensions_unicode_value as value}; use icu_plurals::{provider::OrdinalV1Marker, PluralRules}; use icu_provider::prelude::*; @@ -51,7 +50,7 @@ impl ZonedDateTimeFormatter { provider: &P, patterns: DataPayload, symbols_data_fn: impl FnOnce() -> Result, DataError>, - mut locale: DataLocale, + locale: DataLocale, time_zone_format_options: TimeZoneFormatterOptions, ) -> Result where @@ -68,10 +67,6 @@ impl ZonedDateTimeFormatter { + DataProvider + ?Sized, { - if locale.get_unicode_ext(&key!("ca")) == Some(value!("ethioaa")) { - locale.set_unicode_ext(key!("ca"), value!("ethiopic")); - } - let required = datetime::analyze_patterns(&patterns.get().0, true) .map_err(|field| DateTimeFormatterError::UnsupportedField(field.symbol))?; From 472566aa27777054860f50f3dd21ec87bc56cca0 Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Tue, 16 Aug 2022 12:22:23 -0700 Subject: [PATCH 14/17] Fix datagen tests --- provider/datagen/Cargo.toml | 1 + provider/datagen/src/lib.rs | 8 +++----- provider/datagen/tests/data/work_log+keys.txt | 1 - provider/datagen/tests/data/work_log.wasm | Bin 155340 -> 121231 bytes 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/provider/datagen/Cargo.toml b/provider/datagen/Cargo.toml index b24f20f1ed2..dcca70431d4 100644 --- a/provider/datagen/Cargo.toml +++ b/provider/datagen/Cargo.toml @@ -103,3 +103,4 @@ required-features = ["bin"] [[test]] name = "icu4x-verify-zero-copy" path = "tests/verify-zero-copy.rs" +required-features = ["experimental"] diff --git a/provider/datagen/src/lib.rs b/provider/datagen/src/lib.rs index dec39616f2c..96222efdaba 100644 --- a/provider/datagen/src/lib.rs +++ b/provider/datagen/src/lib.rs @@ -355,12 +355,12 @@ fn test_keys() { keys(&[ "list/and@1", "datetime/gregory/datelengths@1", - "datetime/skeletons@1[u-ca]", + "decimal/symbols@1[u-nu]", "trash", ]), vec![ icu_list::provider::AndListV1Marker::KEY, - icu_datetime::provider::calendar::DateSkeletonPatternsV1Marker::KEY, + icu_decimal::provider::DecimalSymbolsV1Marker::KEY, icu_datetime::provider::calendar::GregorianDateLengthsV1Marker::KEY, ] ); @@ -374,7 +374,6 @@ fn test_keys_from_file() { ) .unwrap(), vec![ - icu_datetime::provider::calendar::DateSkeletonPatternsV1Marker::KEY, icu_decimal::provider::DecimalSymbolsV1Marker::KEY, icu_datetime::provider::calendar::GregorianDateLengthsV1Marker::KEY, icu_datetime::provider::calendar::GregorianDateSymbolsV1Marker::KEY, @@ -388,13 +387,12 @@ fn test_keys_from_file() { #[test] fn test_keys_from_bin() { // File obtained by changing work_log.rs to use `icu_testdata::get_smaller_postcard_provider` - // and running `cargo +nightly wasm-build-release --examples -p icu_datetime --features serde \ + // and running `cargo +nightly-2022-04-05 wasm-build-release --examples -p icu_datetime --features serde \ // && cp target/wasm32-unknown-unknown/release-opt-size/examples/work_log.wasm provider/datagen/tests/data/` assert_eq!( keys_from_bin(PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests/data/work_log.wasm")) .unwrap(), vec![ - icu_datetime::provider::calendar::DateSkeletonPatternsV1Marker::KEY, icu_decimal::provider::DecimalSymbolsV1Marker::KEY, icu_datetime::provider::calendar::GregorianDateLengthsV1Marker::KEY, icu_datetime::provider::calendar::GregorianDateSymbolsV1Marker::KEY, diff --git a/provider/datagen/tests/data/work_log+keys.txt b/provider/datagen/tests/data/work_log+keys.txt index db3323493aa..c29e5e6e74b 100644 --- a/provider/datagen/tests/data/work_log+keys.txt +++ b/provider/datagen/tests/data/work_log+keys.txt @@ -1,5 +1,4 @@ datetime/gregory/datelengths@1 -datetime/skeletons@1[u-ca] datetime/gregory/datesymbols@1 datetime/timesymbols@1 datetime/week_data@1[R] diff --git a/provider/datagen/tests/data/work_log.wasm b/provider/datagen/tests/data/work_log.wasm index 9876be3aa08c77e49d1905224da200680e4856e5..18e79dd1f9f81b9c24239483b23940c591505aa8 100755 GIT binary patch literal 121231 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 literal 155340 zcmbrn51d`sRo{Egxp(H?`F}O~uaT^CuO)fL)_5exk!+1+>nO1t#{@?q6k2FwLtMhh zfk+W<_%v9PAn5QSUIq|lNK_EuV1>vk38w%S%ywsPen<7vd!RSEc5of^zw<8~6ZJQmyF^?RLirAl3E&nSDSJ8u~+dsG7uGmV!q1U$rZK zPdq%_Rf(gxdqw3?oJ}8(`wm6f|Myw@nSL?ut8K1!zx#=IfB%6W1pjwG{=MH9_4dBw z9q)Yn;N$Oj;``oNiTmF1j(0ur_

*U5~%_iAvIw#!(jcExC2W124o6zJA+1_x^PJ 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 Date: Tue, 16 Aug 2022 12:24:23 -0700 Subject: [PATCH 15/17] Fix ffi build --- ffi/diplomat/src/errors.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ffi/diplomat/src/errors.rs b/ffi/diplomat/src/errors.rs index 8204575d6d0..bad72246074 100644 --- a/ffi/diplomat/src/errors.rs +++ b/ffi/diplomat/src/errors.rs @@ -170,7 +170,8 @@ impl From for ICU4XError { DateTimeFormatterError::MissingInputField(_) => { ICU4XError::DateTimeFormatMissingInputFieldError } - DateTimeFormatterError::Skeleton(_) => ICU4XError::DateTimeFormatSkeletonError, + // TODO(#1324): Add back skeleton errors + // DateTimeFormatterError::Skeleton(_) => ICU4XError::DateTimeFormatSkeletonError, DateTimeFormatterError::UnsupportedField(_) => { ICU4XError::DateTimeFormatUnsupportedFieldError } From 6c4dbca3824af574e194412a555d7226c07fffab Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Tue, 16 Aug 2022 12:28:50 -0700 Subject: [PATCH 16/17] Fix docs link --- components/datetime/src/datetime.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/components/datetime/src/datetime.rs b/components/datetime/src/datetime.rs index 35770387a74..5708e0db8a8 100644 --- a/components/datetime/src/datetime.rs +++ b/components/datetime/src/datetime.rs @@ -23,6 +23,9 @@ use crate::{ DateTimeFormatterError, FormattedDateTime, }; +#[cfg(feature = "experimental")] +use crate::options::components; + /// [`TimeFormatter`] is a structure of the [`icu_datetime`] component that provides time formatting only. /// When constructed, it uses data from the [data provider], selected locale and provided preferences to /// collect all data necessary to format any time into that locale. @@ -692,7 +695,7 @@ where { /// assert_eq!(dtf.resolve_components(), expected_components_bag); /// ``` #[cfg(feature = "experimental")] - pub fn resolve_components(&self) -> crate::options::components::Bag { + pub fn resolve_components(&self) -> components::Bag { self.0.resolve_components() } } From cbf0e17e54a751313892890f48b200c31c9458b5 Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Tue, 16 Aug 2022 15:13:44 -0700 Subject: [PATCH 17/17] Fix more build errors --- components/datetime/benches/datetime.rs | 22 ++++++++++--------- components/datetime/benches/fixtures/mod.rs | 9 +++++--- .../datetime/benches/fixtures/structs.rs | 4 ++++ components/datetime/src/format/datetime.rs | 1 + components/datetime/src/options/components.rs | 2 +- components/datetime/src/skeleton/mod.rs | 2 +- provider/testdata/Cargo.toml | 2 +- 7 files changed, 26 insertions(+), 16 deletions(-) diff --git a/components/datetime/benches/datetime.rs b/components/datetime/benches/datetime.rs index 067debef81d..8eded1aea80 100644 --- a/components/datetime/benches/datetime.rs +++ b/components/datetime/benches/datetime.rs @@ -35,7 +35,7 @@ fn datetime_benches(c: &mut Criterion) { .collect(); for setup in &fx.setups { let locale: Locale = setup.locale.parse().expect("Failed to parse locale."); - let options = fixtures::get_options(&setup.options); + let options = fixtures::get_options(&setup.options).unwrap(); let dtf = TypedDateTimeFormatter::::try_new_unstable( &provider, &locale.into(), @@ -58,6 +58,8 @@ fn datetime_benches(c: &mut Criterion) { }; bench_datetime_with_fixture("lengths"); + + #[cfg(feature = "experimental")] bench_datetime_with_fixture("components"); let fxs = fixtures::get_fixture("lengths_with_zones").unwrap(); @@ -71,7 +73,7 @@ fn datetime_benches(c: &mut Criterion) { .collect(); for setup in &fx.setups { let locale: Locale = setup.locale.parse().unwrap(); - let options = fixtures::get_options(&setup.options); + let options = fixtures::get_options(&setup.options).unwrap(); let dtf = TypedZonedDateTimeFormatter::::try_new_unstable( &provider, &locale.into(), @@ -110,7 +112,7 @@ fn datetime_benches(c: &mut Criterion) { for setup in &fx.setups { let locale: Locale = setup.locale.parse().unwrap(); - let options = fixtures::get_options(&setup.options); + let options = fixtures::get_options(&setup.options).unwrap(); let dtf = TypedDateTimeFormatter::::try_new_unstable( &provider, &locale.into(), @@ -140,7 +142,7 @@ fn datetime_benches(c: &mut Criterion) { for setup in &fx.setups { let locale: Locale = setup.locale.parse().unwrap(); - let options = fixtures::get_options(&setup.options); + let options = fixtures::get_options(&setup.options).unwrap(); let dtf = TypedDateTimeFormatter::::try_new_unstable( &provider, &locale.into(), @@ -167,7 +169,7 @@ fn datetime_benches(c: &mut Criterion) { for setup in &fx.setups { let locale: Locale = setup.locale.parse().unwrap(); - let options = fixtures::get_options(&setup.options); + let options = fixtures::get_options(&setup.options).unwrap(); let dtf = TypedDateTimeFormatter::::try_new_unstable( &provider, &locale.into(), @@ -198,7 +200,7 @@ fn datetime_benches(c: &mut Criterion) { for setup in &fx.setups { let locale: Locale = setup.locale.parse().unwrap(); - let options = fixtures::get_options(&setup.options); + let options = fixtures::get_options(&setup.options).unwrap(); let dtf = TypedDateTimeFormatter::::try_new_unstable( &provider, &locale.into(), @@ -227,7 +229,7 @@ fn datetime_benches(c: &mut Criterion) { for setup in &fx.setups { let locale: Locale = setup.locale.parse().unwrap(); - let options = fixtures::get_options(&setup.options); + let options = fixtures::get_options(&setup.options).unwrap(); let dtf = TypedZonedDateTimeFormatter::::try_new_unstable( &provider, &locale.into(), @@ -258,7 +260,7 @@ fn datetime_benches(c: &mut Criterion) { for setup in &fx.setups { let locale: Locale = setup.locale.parse().unwrap(); - let options = fixtures::get_options(&setup.options); + let options = fixtures::get_options(&setup.options).unwrap(); let dtf = TypedZonedDateTimeFormatter::::try_new_unstable( &provider, &locale.into(), @@ -286,7 +288,7 @@ fn datetime_benches(c: &mut Criterion) { for setup in &fx.setups { let locale: Locale = setup.locale.parse().unwrap(); - let options = fixtures::get_options(&setup.options); + let options = fixtures::get_options(&setup.options).unwrap(); let dtf = TypedZonedDateTimeFormatter::::try_new_unstable( &provider, &locale.into(), @@ -318,7 +320,7 @@ fn datetime_benches(c: &mut Criterion) { for setup in &fx.setups { let locale: Locale = setup.locale.parse().unwrap(); - let options = fixtures::get_options(&setup.options); + let options = fixtures::get_options(&setup.options).unwrap(); let dtf = TypedZonedDateTimeFormatter::::try_new_unstable( &provider, &locale.into(), diff --git a/components/datetime/benches/fixtures/mod.rs b/components/datetime/benches/fixtures/mod.rs index 49799cc7485..1bc1f4d9f76 100644 --- a/components/datetime/benches/fixtures/mod.rs +++ b/components/datetime/benches/fixtures/mod.rs @@ -25,9 +25,12 @@ pub fn get_patterns_fixture() -> std::io::Result { } #[allow(dead_code)] -pub fn get_options(input: &structs::TestOptions) -> DateTimeFormatterOptions { +pub fn get_options(input: &structs::TestOptions) -> Option { match input { - structs::TestOptions::Length(bag) => (*bag).into(), - structs::TestOptions::Components(bag) => (*bag).into(), + structs::TestOptions::Length(bag) => Some((*bag).into()), + #[cfg(feature = "experimental")] + structs::TestOptions::Components(bag) => Some((*bag).into()), + #[cfg(not(feature = "experimental"))] + structs::TestOptions::Components(_) => None, } } diff --git a/components/datetime/benches/fixtures/structs.rs b/components/datetime/benches/fixtures/structs.rs index 4cb283c67b4..9598060477e 100644 --- a/components/datetime/benches/fixtures/structs.rs +++ b/components/datetime/benches/fixtures/structs.rs @@ -25,7 +25,11 @@ pub enum TestOptions { #[serde(rename = "length")] Length(options::length::Bag), #[serde(rename = "components")] + #[cfg(feature = "experimental")] Components(options::components::Bag), + #[serde(rename = "components")] + #[cfg(not(feature = "experimental"))] + Components(serde_json::Value), } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] diff --git a/components/datetime/src/format/datetime.rs b/components/datetime/src/format/datetime.rs index f10643779f1..26c4d7968ee 100644 --- a/components/datetime/src/format/datetime.rs +++ b/components/datetime/src/format/datetime.rs @@ -501,6 +501,7 @@ pub fn analyze_patterns( } #[cfg(test)] +#[allow(unused_imports)] mod tests { use super::*; use icu_decimal::options::{FixedDecimalFormatterOptions, GroupingStrategy}; diff --git a/components/datetime/src/options/components.rs b/components/datetime/src/options/components.rs index 908263bbf58..679c11b77f8 100644 --- a/components/datetime/src/options/components.rs +++ b/components/datetime/src/options/components.rs @@ -129,7 +129,7 @@ impl Bag { /// Converts the components::Bag into a Vec. The fields will be ordered in from most /// significant field to least significant. This is the order the fields are listed in /// the UTS 35 table - https://unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table - #[cfg(feature = "experimental")] // only used in experimental code + #[cfg(any(test, feature = "experimental"))] // only used in experimental code pub(crate) fn to_vec_fields(&self) -> Vec { let mut fields = Vec::new(); if let Some(era) = self.era { diff --git a/components/datetime/src/skeleton/mod.rs b/components/datetime/src/skeleton/mod.rs index f3ba5afabce..291053815f4 100644 --- a/components/datetime/src/skeleton/mod.rs +++ b/components/datetime/src/skeleton/mod.rs @@ -13,7 +13,7 @@ mod serde; pub use error::*; pub use helpers::*; -#[cfg(all(test, feature = "datagen"))] +#[cfg(all(test, feature = "datagen", feature = "experimental"))] mod test { use super::reference::Skeleton; use super::*; diff --git a/provider/testdata/Cargo.toml b/provider/testdata/Cargo.toml index 7130f31e842..c38fe431ff5 100644 --- a/provider/testdata/Cargo.toml +++ b/provider/testdata/Cargo.toml @@ -306,7 +306,7 @@ writeable = { version = "0.4", path = "../../utils/writeable", optional = true } icu_calendar = { version = "1.0.0-beta1", path = "../../components/calendar", optional = true } icu_casemapping = { version = "0.2", path = "../../experimental/casemapping", optional = true } icu_collator = { version = "1.0.0-beta1", path = "../../components/collator", optional = true } -icu_datetime = { version = "1.0.0-beta1", path = "../../components/datetime", optional = true } +icu_datetime = { version = "1.0.0-beta1", path = "../../components/datetime", features = ["experimental"], optional = true } icu_decimal = { version = "1.0.0-beta1", path = "../../components/decimal", optional = true } icu_list = { version = "1.0.0-beta1", path = "../../components/list", optional = true } icu_locid_transform = { version = "1.0.0-beta1", path = "../../components/locid_transform", optional = true }