diff --git a/components/datetime/src/any/zoned_datetime.rs b/components/datetime/src/any/zoned_datetime.rs index 3d4320969eb..ce0a5407134 100644 --- a/components/datetime/src/any/zoned_datetime.rs +++ b/components/datetime/src/any/zoned_datetime.rs @@ -51,20 +51,16 @@ use icu_plurals::provider::OrdinalV1Marker; /// use icu::datetime::{options::length, ZonedDateTimeFormatter}; /// use icu::locid::locale; /// use icu_datetime::TimeZoneFormatterOptions; -/// use icu_provider::inv::InvariantDataProvider; /// -/// let date_provider = InvariantDataProvider; -/// let zone_provider = InvariantDataProvider; -/// let plural_provider = InvariantDataProvider; -/// let decimal_provider = InvariantDataProvider; +/// let provider = icu_testdata::get_provider(); /// /// let options = length::Bag::from_date_time_style(length::Date::Medium, length::Time::Short); /// let zdtf = ZonedDateTimeFormatter::::try_new( /// locale!("en"), -/// &date_provider, -/// &zone_provider, -/// &plural_provider, -/// &decimal_provider, +/// &provider, +/// &provider, +/// &provider, +/// &provider, /// &options.into(), /// &TimeZoneFormatterOptions::default(), /// ) @@ -96,7 +92,6 @@ impl ZonedAnyDateTimeFormatter { /// use icu::datetime::{DateTimeFormatterOptions, any::ZonedAnyDateTimeFormatter}; /// use icu::locid::Locale; /// use icu::datetime::TimeZoneFormatterOptions; - /// use icu_provider::inv::InvariantDataProvider; /// use std::str::FromStr; /// /// let provider = icu_testdata::get_provider(); diff --git a/components/datetime/src/datetime.rs b/components/datetime/src/datetime.rs index 7e094c5468c..c276d245f89 100644 --- a/components/datetime/src/datetime.rs +++ b/components/datetime/src/datetime.rs @@ -39,19 +39,24 @@ use crate::{ /// /// ``` /// use icu::calendar::{DateTime, Gregorian}; -/// use icu::datetime::{TimeFormatter, options::length::Time}; +/// use icu::datetime::{options::length::Time, TimeFormatter}; /// use icu::locid::locale; -/// use icu_provider::inv::InvariantDataProvider; +/// use writeable::assert_writeable_eq; /// -/// let provider = InvariantDataProvider; +/// let provider = icu_testdata::get_provider(); /// -/// let tf = TimeFormatter::::try_new(locale!("en"), &provider, Time::Full, None) -/// .expect("Failed to create DateTimeFormatter instance."); +/// let tf = TimeFormatter::::try_new( +/// locale!("en"), +/// &provider, +/// Time::Short, +/// None, +/// ) +/// .expect("Failed to create TimeFormatter instance."); /// /// let datetime = DateTime::new_gregorian_datetime(2020, 9, 1, 12, 34, 28) /// .expect("Failed to construct DateTime."); /// -/// let value = tf.format_to_string(&datetime); +/// assert_writeable_eq!(tf.format(&datetime), "12:34 PM"); /// ``` /// /// This model replicates that of `ICU` and `ECMA402`. @@ -68,15 +73,18 @@ impl TimeFormatter { /// /// ``` /// use icu::calendar::Gregorian; - /// use icu::datetime::{TimeFormatter, options::length::Time}; + /// use icu::datetime::{options::length::Time, TimeFormatter}; /// use icu::locid::locale; - /// use icu_provider::inv::InvariantDataProvider; /// - /// let provider = InvariantDataProvider; - /// - /// let tf = TimeFormatter::::try_new(locale!("en"), &provider, Time::Short, None); + /// let provider = icu_testdata::get_provider(); /// - /// assert_eq!(tf.is_ok(), true); + /// TimeFormatter::::try_new( + /// locale!("en"), + /// &provider, + /// Time::Short, + /// None, + /// ) + /// .unwrap(); /// ``` /// /// [data provider]: icu_provider @@ -109,19 +117,18 @@ impl TimeFormatter { /// /// ``` /// use icu::calendar::{DateTime, Gregorian}; - /// use icu::datetime::{TimeFormatter, options::length::Time}; - /// use icu_provider::inv::InvariantDataProvider; + /// use icu::datetime::{options::length::Time, TimeFormatter}; + /// use writeable::assert_writeable_eq; /// # let locale = icu::locid::locale!("en"); - /// # let provider = InvariantDataProvider; - /// let tf = TimeFormatter::::try_new(locale, &provider, Time::Full, None) - /// .expect("Failed to create TimeFormatter instance."); + /// # let provider = icu_testdata::get_provider(); + /// let tf = + /// TimeFormatter::::try_new(locale, &provider, Time::Short, None) + /// .expect("Failed to create TimeFormatter instance."); /// /// let datetime = DateTime::new_gregorian_datetime(2020, 9, 1, 12, 34, 28) /// .expect("Failed to construct DateTime."); /// - /// let formatted = tf.format(&datetime); - /// - /// let _ = format!("Time: {}", formatted); + /// assert_writeable_eq!(tf.format(&datetime), "12:34 PM"); /// ``` /// /// At the moment, there's little value in using that over one of the other `format` methods, @@ -142,12 +149,12 @@ impl TimeFormatter { /// /// ``` /// use icu::calendar::{DateTime, Gregorian}; - /// use icu::datetime::{TimeFormatter, options::length::Time}; - /// use icu_provider::inv::InvariantDataProvider; + /// use icu::datetime::{options::length::Time, TimeFormatter}; /// # let locale = icu::locid::locale!("en"); - /// # let provider = InvariantDataProvider; - /// let tf = TimeFormatter::::try_new(locale, &provider, Time::Short, None) - /// .expect("Failed to create TimeFormatter instance."); + /// # let provider = icu_testdata::get_provider(); + /// let tf = + /// TimeFormatter::::try_new(locale, &provider, Time::Short, None) + /// .expect("Failed to create TimeFormatter instance."); /// /// let datetime = DateTime::new_gregorian_datetime(2020, 9, 1, 12, 34, 28) /// .expect("Failed to construct DateTime."); @@ -156,7 +163,7 @@ impl TimeFormatter { /// tf.format_to_write(&mut buffer, &datetime) /// .expect("Failed to write to a buffer."); /// - /// let _ = format!("Time: {}", buffer); + /// assert_eq!(buffer, "12:34 PM"); /// ``` #[inline] pub fn format_to_write( @@ -173,17 +180,17 @@ impl TimeFormatter { /// /// ``` /// use icu::calendar::{DateTime, Gregorian}; - /// use icu::datetime::{TimeFormatter, options::length::Time}; - /// use icu_provider::inv::InvariantDataProvider; + /// use icu::datetime::{options::length::Time, TimeFormatter}; /// # let locale = icu::locid::locale!("en"); - /// # let provider = InvariantDataProvider; - /// let tf = TimeFormatter::::try_new(locale, &provider, Time::Long, None) - /// .expect("Failed to create TimeFormatter instance."); + /// # let provider = icu_testdata::get_provider(); + /// let tf = + /// TimeFormatter::::try_new(locale, &provider, Time::Short, None) + /// .expect("Failed to create TimeFormatter instance."); /// /// let datetime = DateTime::new_gregorian_datetime(2020, 9, 1, 12, 34, 28) /// .expect("Failed to construct DateTime."); /// - /// let _ = tf.format_to_string(&datetime); + /// assert_eq!(tf.format_to_string(&datetime), "12:34 PM"); /// ``` #[inline] pub fn format_to_string(&self, value: &impl DateTimeInput) -> String { @@ -205,11 +212,10 @@ impl TimeFormatter { /// /// ``` /// use icu::calendar::{DateTime, Gregorian}; -/// use icu::datetime::{DateFormatter, options::length::Date}; +/// use icu::datetime::{options::length::Date, DateFormatter}; /// use icu::locid::locale; -/// use icu_provider::inv::InvariantDataProvider; /// -/// let provider = InvariantDataProvider; +/// let provider = icu_testdata::get_provider(); /// /// let df = DateFormatter::::try_new(locale!("en"), &provider, Date::Full) /// .expect("Failed to create DateFormatter instance."); @@ -217,7 +223,7 @@ impl TimeFormatter { /// let datetime = DateTime::new_gregorian_datetime(2020, 9, 1, 12, 34, 28) /// .expect("Failed to construct DateTime."); /// -/// let value = df.format_to_string(&datetime); +/// assert_eq!(df.format_to_string(&datetime), "Tuesday, September 1, 2020"); /// ``` /// /// This model replicates that of `ICU` and `ECMA402`. @@ -233,15 +239,13 @@ impl DateFormatter { /// /// ``` /// use icu::calendar::Gregorian; - /// use icu::datetime::{DateFormatter, options::length::Date}; + /// use icu::datetime::{options::length::Date, DateFormatter}; /// use icu::locid::locale; - /// use icu_provider::inv::InvariantDataProvider; /// - /// let provider = InvariantDataProvider; - /// - /// let df = DateFormatter::::try_new(locale!("en"), &provider, Date::Full); + /// let provider = icu_testdata::get_provider(); /// - /// assert_eq!(df.is_ok(), true); + /// DateFormatter::::try_new(locale!("en"), &provider, Date::Full) + /// .unwrap(); /// ``` /// /// [data provider]: icu_provider @@ -274,19 +278,17 @@ impl DateFormatter { /// /// ``` /// use icu::calendar::{DateTime, Gregorian}; - /// use icu::datetime::{DateFormatter, options::length::Date}; - /// use icu_provider::inv::InvariantDataProvider; + /// use icu::datetime::{options::length::Date, DateFormatter}; + /// use writeable::assert_writeable_eq; /// # let locale = icu::locid::locale!("en"); - /// # let provider = InvariantDataProvider; + /// # let provider = icu_testdata::get_provider(); /// let df = DateFormatter::::try_new(locale, &provider, Date::Full) /// .expect("Failed to create DateFormatter instance."); /// /// let datetime = DateTime::new_gregorian_datetime(2020, 9, 1, 12, 34, 28) /// .expect("Failed to construct DateTime."); /// - /// let formatted = df.format(&datetime); - /// - /// let _ = format!("Time: {}", formatted); + /// assert_writeable_eq!(df.format(&datetime), "Tuesday, September 1, 2020"); /// ``` /// /// At the moment, there's little value in using that over one of the other `format` methods, @@ -307,10 +309,9 @@ impl DateFormatter { /// /// ``` /// use icu::calendar::{DateTime, Gregorian}; - /// use icu::datetime::{DateFormatter, options::length::Date}; - /// use icu_provider::inv::InvariantDataProvider; + /// use icu::datetime::{options::length::Date, DateFormatter}; /// # let locale = icu::locid::locale!("en"); - /// # let provider = InvariantDataProvider; + /// # let provider = icu_testdata::get_provider(); /// let df = DateFormatter::::try_new(locale, &provider, Date::Short) /// .expect("Failed to create DateFormatter instance."); /// @@ -321,7 +322,7 @@ impl DateFormatter { /// df.format_to_write(&mut buffer, &datetime) /// .expect("Failed to write to a buffer."); /// - /// let _ = format!("Time: {}", buffer); + /// assert_eq!(buffer, "9/1/20"); /// ``` #[inline] pub fn format_to_write( @@ -338,17 +339,16 @@ impl DateFormatter { /// /// ``` /// use icu::calendar::{DateTime, Gregorian}; - /// use icu::datetime::{DateFormatter, options::length::Date}; - /// use icu_provider::inv::InvariantDataProvider; + /// use icu::datetime::{options::length::Date, DateFormatter}; /// # let locale = icu::locid::locale!("en"); - /// # let provider = InvariantDataProvider; + /// # let provider = icu_testdata::get_provider(); /// let df = DateFormatter::::try_new(locale, &provider, Date::Short) /// .expect("Failed to create DateTimeFormatter instance."); /// /// let datetime = DateTime::new_gregorian_datetime(2020, 9, 1, 12, 34, 28) /// .expect("Failed to construct DateTime."); /// - /// let _ = df.format_to_string(&datetime); + /// assert_eq!(df.format_to_string(&datetime), "9/1/20"); /// ``` #[inline] pub fn format_to_string(&self, value: &impl DateTimeInput) -> String { @@ -372,20 +372,25 @@ impl DateFormatter { /// use icu::calendar::{DateTime, Gregorian}; /// use icu::datetime::{options::length, DateTimeFormatter}; /// use icu::locid::locale; -/// use icu_provider::inv::InvariantDataProvider; -/// -/// let provider = InvariantDataProvider; /// -/// let mut options = length::Bag::from_date_time_style(length::Date::Medium, length::Time::Short); +/// let provider = icu_testdata::get_provider(); /// -/// let dtf = DateTimeFormatter::::try_new(locale!("en"), &provider, &options.into()) -/// .expect("Failed to create DateTimeFormatter instance."); +/// let mut options = length::Bag::from_date_time_style( +/// length::Date::Medium, +/// length::Time::Short, +/// ); /// +/// let dtf = DateTimeFormatter::::try_new( +/// locale!("en"), +/// &provider, +/// &options.into(), +/// ) +/// .expect("Failed to create DateTimeFormatter instance."); /// /// let datetime = DateTime::new_gregorian_datetime(2020, 9, 1, 12, 34, 28) /// .expect("Failed to construct DateTime."); /// -/// let value = dtf.format_to_string(&datetime); +/// assert_eq!(dtf.format_to_string(&datetime), "Sep 1, 2020, 12:34 PM"); /// ``` /// /// This model replicates that of `ICU` and `ECMA402`. @@ -400,19 +405,28 @@ impl DateTimeFormatter { /// /// ``` /// use icu::calendar::Gregorian; - /// use icu::datetime::{options::length, DateFormatter, DateTimeFormatter, TimeFormatter}; + /// use icu::datetime::{ + /// options::length, DateFormatter, DateTimeFormatter, TimeFormatter, + /// }; /// use icu::locid::locale; - /// use icu_provider::inv::InvariantDataProvider; /// - /// let provider = InvariantDataProvider; - /// - /// let tf = TimeFormatter::::try_new(locale!("en"), &provider, length::Time::Short, None) - /// .expect("Failed to create TimeFormatter instance."); - /// let df = DateFormatter::::try_new(locale!("en"), &provider, length::Date::Short) - /// .expect("Failed to create DateFormatter instance."); - /// let dtf = DateTimeFormatter::::try_from_date_and_time(df, tf); + /// let provider = icu_testdata::get_provider(); /// - /// assert_eq!(dtf.is_ok(), true); + /// let tf = TimeFormatter::::try_new( + /// locale!("en"), + /// &provider, + /// length::Time::Short, + /// None, + /// ) + /// .expect("Failed to create TimeFormatter instance."); + /// let df = DateFormatter::::try_new( + /// locale!("en"), + /// &provider, + /// length::Date::Short, + /// ) + /// .expect("Failed to create DateFormatter instance."); + /// + /// DateTimeFormatter::::try_from_date_and_time(df, tf).unwrap(); /// ``` /// /// [data provider]: icu_provider @@ -435,17 +449,19 @@ where { /// /// ``` /// use icu::calendar::Gregorian; - /// use icu::datetime::{DateTimeFormatter, DateTimeFormatterOptions}; + /// use icu::datetime::{options::length, DateTimeFormatter}; /// use icu::locid::locale; - /// use icu_provider::inv::InvariantDataProvider; - /// - /// let provider = InvariantDataProvider; /// - /// let options = DateTimeFormatterOptions::default(); + /// let provider = icu_testdata::get_provider(); /// - /// let dtf = DateTimeFormatter::::try_new(locale!("en"), &provider, &options); + /// let options = length::Bag::from_time_style(length::Time::Medium); /// - /// assert_eq!(dtf.is_ok(), true); + /// DateTimeFormatter::::try_new( + /// locale!("en"), + /// &provider, + /// &options.into(), + /// ) + /// .unwrap(); /// ``` /// /// [data provider]: icu_provider @@ -482,20 +498,18 @@ where { /// /// ``` /// use icu::calendar::{DateTime, Gregorian}; - /// use icu::datetime::{DateTimeFormatter, DateTimeFormatterOptions}; - /// use icu_provider::inv::InvariantDataProvider; + /// use icu::datetime::DateTimeFormatter; + /// use writeable::assert_writeable_eq; /// # let locale = icu::locid::locale!("en"); - /// # let provider = InvariantDataProvider; - /// # let options = DateTimeFormatterOptions::default(); - /// let dtf = DateTimeFormatter::::try_new(locale, &provider, &options) + /// # let provider = icu_testdata::get_provider(); + /// # let options = icu::datetime::options::length::Bag::from_time_style(icu::datetime::options::length::Time::Medium); + /// let dtf = DateTimeFormatter::::try_new(locale, &provider, &options.into()) /// .expect("Failed to create DateTimeFormatter instance."); /// /// let datetime = DateTime::new_gregorian_datetime(2020, 9, 1, 12, 34, 28) /// .expect("Failed to construct DateTime."); /// - /// let formatted_date = dtf.format(&datetime); - /// - /// let _ = format!("Date: {}", formatted_date); + /// assert_writeable_eq!(dtf.format(&datetime), "12:34:28 PM"); /// ``` /// /// At the moment, there's little value in using that over one of the other `format` methods, @@ -516,11 +530,10 @@ where { /// /// ``` /// use icu::calendar::{DateTime, Gregorian}; - /// use icu::datetime::{DateTimeFormatter, DateTimeFormatterOptions}; - /// use icu_provider::inv::InvariantDataProvider; + /// use icu::datetime::DateTimeFormatter; /// # let locale = icu::locid::locale!("en"); - /// # let provider = InvariantDataProvider; - /// # let options = DateTimeFormatterOptions::default(); + /// # let provider = icu_testdata::get_provider(); + /// # let options = icu::datetime::options::length::Bag::from_time_style(icu::datetime::options::length::Time::Medium); /// let dtf = DateTimeFormatter::::try_new(locale, &provider, &options.into()) /// .expect("Failed to create DateTimeFormatter instance."); /// @@ -531,7 +544,7 @@ where { /// dtf.format_to_write(&mut buffer, &datetime) /// .expect("Failed to write to a buffer."); /// - /// let _ = format!("Date: {}", buffer); + /// assert_eq!(buffer, "12:34:28 PM"); /// ``` #[inline] pub fn format_to_write( @@ -548,18 +561,17 @@ where { /// /// ``` /// use icu::calendar::{DateTime, Gregorian}; - /// use icu::datetime::{DateTimeFormatter, DateTimeFormatterOptions}; - /// use icu_provider::inv::InvariantDataProvider; + /// use icu::datetime::DateTimeFormatter; /// # let locale = icu::locid::locale!("en"); - /// # let provider = InvariantDataProvider; - /// # let options = DateTimeFormatterOptions::default(); + /// # let provider = icu_testdata::get_provider(); + /// # let options = icu::datetime::options::length::Bag::from_time_style(icu::datetime::options::length::Time::Medium); /// let dtf = DateTimeFormatter::::try_new(locale, &provider, &options.into()) /// .expect("Failed to create DateTimeFormatter instance."); /// /// let datetime = DateTime::new_gregorian_datetime(2020, 9, 1, 12, 34, 28) /// .expect("Failed to construct DateTime."); /// - /// let _ = dtf.format_to_string(&datetime); + /// assert_eq!(dtf.format_to_string(&datetime), "12:34:28 PM"); /// ``` #[inline] pub fn format_to_string(&self, value: &impl DateTimeInput) -> String { @@ -584,8 +596,12 @@ where { /// let options = length::Bag::from_date_style(length::Date::Medium).into(); /// /// let provider = icu_testdata::get_provider(); - /// let dtf = DateTimeFormatter::::try_new(locale!("en"), &provider, &options) - /// .expect("Failed to create DateTimeFormatter instance."); + /// let dtf = DateTimeFormatter::::try_new( + /// locale!("en"), + /// &provider, + /// &options, + /// ) + /// .expect("Failed to create DateTimeFormatter instance."); /// /// let mut expected_components_bag = components::Bag::default(); /// expected_components_bag.year = Some(components::Year::Numeric); diff --git a/components/datetime/src/format/datetime.rs b/components/datetime/src/format/datetime.rs index b2204076809..a7a8195bf39 100644 --- a/components/datetime/src/format/datetime.rs +++ b/components/datetime/src/format/datetime.rs @@ -33,11 +33,11 @@ use writeable::Writeable; /// /// # Examples /// -/// ``` +/// ```no_run /// use icu::calendar::{DateTime, Gregorian}; /// use icu::datetime::DateTimeFormatter; /// use icu::locid::locale; -/// # let provider = icu_provider::inv::InvariantDataProvider; +/// # let provider = icu_testdata::get_provider(); /// # let options = icu::datetime::DateTimeFormatterOptions::default(); /// let dtf = DateTimeFormatter::::try_new(locale!("en"), &provider, &options) /// .expect("Failed to create DateTimeFormatter instance."); diff --git a/components/datetime/src/time_zone.rs b/components/datetime/src/time_zone.rs index 624bd85aed9..f0a08836e91 100644 --- a/components/datetime/src/time_zone.rs +++ b/components/datetime/src/time_zone.rs @@ -65,9 +65,8 @@ where /// use icu_datetime::mock::time_zone::MockTimeZone; /// use icu_datetime::{TimeZoneFormatter, TimeZoneFormatterConfig, TimeZoneFormatterOptions}; /// use icu_locid::locale; -/// use icu_provider::inv::InvariantDataProvider; /// -/// let provider = InvariantDataProvider; +/// let provider = icu_testdata::get_provider(); /// /// let tzf = TimeZoneFormatter::try_from_config( /// locale!("en"), @@ -352,9 +351,8 @@ impl TimeZoneFormatter { /// use icu_datetime::mock::time_zone::MockTimeZone; /// use icu_datetime::{TimeZoneFormatter, TimeZoneFormatterConfig, TimeZoneFormatterOptions}; /// use icu_locid::locale; - /// use icu_provider::inv::InvariantDataProvider; /// - /// let provider = InvariantDataProvider; + /// let provider = icu_testdata::get_provider(); /// /// let tzf = TimeZoneFormatter::try_from_config( /// locale!("en"), @@ -612,9 +610,8 @@ impl TimeZoneFormatter { /// use icu_datetime::mock::time_zone::MockTimeZone; /// use icu_datetime::{TimeZoneFormatter, TimeZoneFormatterConfig, TimeZoneFormatterOptions}; /// use icu_locid::locale; - /// use icu_provider::inv::InvariantDataProvider; /// - /// let provider = InvariantDataProvider; + /// let provider = icu_testdata::get_provider(); /// /// let tzf = TimeZoneFormatter::try_from_config( /// locale!("en"), @@ -648,9 +645,8 @@ impl TimeZoneFormatter { /// use icu_datetime::mock::time_zone::MockTimeZone; /// use icu_datetime::{TimeZoneFormatter, TimeZoneFormatterConfig, TimeZoneFormatterOptions}; /// use icu_locid::locale; - /// use icu_provider::inv::InvariantDataProvider; /// - /// let provider = InvariantDataProvider; + /// let provider = icu_testdata::get_provider(); /// /// let tzf = TimeZoneFormatter::try_from_config( /// locale!("en"), @@ -685,9 +681,8 @@ impl TimeZoneFormatter { /// use icu_datetime::mock::time_zone::MockTimeZone; /// use icu_datetime::{TimeZoneFormatter, TimeZoneFormatterConfig, TimeZoneFormatterOptions}; /// use icu_locid::locale; - /// use icu_provider::inv::InvariantDataProvider; /// - /// let provider = InvariantDataProvider; + /// let provider = icu_testdata::get_provider(); /// /// let tzf = TimeZoneFormatter::try_from_config( /// locale!("en"), diff --git a/components/datetime/src/zoned_datetime.rs b/components/datetime/src/zoned_datetime.rs index d11467deffa..9f52e8ca9e7 100644 --- a/components/datetime/src/zoned_datetime.rs +++ b/components/datetime/src/zoned_datetime.rs @@ -48,20 +48,16 @@ use crate::{ /// use icu::datetime::{options::length, ZonedDateTimeFormatter}; /// use icu::locid::locale; /// use icu_datetime::TimeZoneFormatterOptions; -/// use icu_provider::inv::InvariantDataProvider; /// -/// let date_provider = InvariantDataProvider; -/// let zone_provider = InvariantDataProvider; -/// let plural_provider = InvariantDataProvider; -/// let decimal_provider = InvariantDataProvider; +/// let provider = icu_testdata::get_provider(); /// /// let options = length::Bag::from_date_time_style(length::Date::Medium, length::Time::Short); /// let zdtf = ZonedDateTimeFormatter::::try_new( /// locale!("en"), -/// &date_provider, -/// &zone_provider, -/// &plural_provider, -/// &decimal_provider, +/// &provider, +/// &provider, +/// &provider, +/// &provider, /// &options.into(), /// &TimeZoneFormatterOptions::default(), /// ) @@ -88,21 +84,17 @@ impl ZonedDateTimeFormatter { /// use icu::datetime::{DateTimeFormatterOptions, ZonedDateTimeFormatter}; /// use icu::locid::locale; /// use icu_datetime::TimeZoneFormatterOptions; - /// use icu_provider::inv::InvariantDataProvider; /// - /// let date_provider = InvariantDataProvider; - /// let zone_provider = InvariantDataProvider; - /// let plural_provider = InvariantDataProvider; - /// let decimal_provider = InvariantDataProvider; + /// let provider = icu_testdata::get_provider(); /// /// let options = DateTimeFormatterOptions::default(); /// /// let zdtf = ZonedDateTimeFormatter::::try_new( /// locale!("en"), - /// &date_provider, - /// &zone_provider, - /// &plural_provider, - /// &decimal_provider, + /// &provider, + /// &provider, + /// &provider, + /// &provider, /// &options, /// &TimeZoneFormatterOptions::default(), /// ); @@ -167,19 +159,15 @@ impl ZonedDateTimeFormatter { /// use icu::datetime::mock::zoned_datetime::MockZonedDateTime; /// use icu::datetime::ZonedDateTimeFormatter; /// use icu_datetime::TimeZoneFormatterOptions; - /// use icu_provider::inv::InvariantDataProvider; /// # let locale = icu::locid::locale!("en"); - /// # let date_provider = InvariantDataProvider; - /// # let zone_provider = InvariantDataProvider; - /// # let plural_provider = InvariantDataProvider; - /// # let decimal_provider = InvariantDataProvider; + /// # let provider = icu_testdata::get_provider(); /// # let options = icu::datetime::DateTimeFormatterOptions::default(); /// let zdtf = ZonedDateTimeFormatter::::try_new( /// locale, - /// &date_provider, - /// &zone_provider, - /// &plural_provider, - /// &decimal_provider, + /// &provider, + /// &provider, + /// &provider, + /// &provider, /// &options, /// &TimeZoneFormatterOptions::default(), /// ) @@ -215,19 +203,15 @@ impl ZonedDateTimeFormatter { /// use icu::datetime::mock::zoned_datetime::MockZonedDateTime; /// use icu::datetime::ZonedDateTimeFormatter; /// use icu_datetime::TimeZoneFormatterOptions; - /// # use icu_provider::inv::InvariantDataProvider; /// # let locale = icu::locid::locale!("en"); - /// # let date_provider = InvariantDataProvider; - /// # let zone_provider = InvariantDataProvider; - /// # let plural_provider = InvariantDataProvider; - /// # let decimal_provider = InvariantDataProvider; + /// # let provider = icu_testdata::get_provider(); /// # let options = icu::datetime::DateTimeFormatterOptions::default(); /// let zdtf = ZonedDateTimeFormatter::::try_new( /// locale, - /// &date_provider, - /// &zone_provider, - /// &plural_provider, - /// &decimal_provider, + /// &provider, + /// &provider, + /// &provider, + /// &provider, /// &options.into(), /// &TimeZoneFormatterOptions::default(), /// ) @@ -261,19 +245,15 @@ impl ZonedDateTimeFormatter { /// use icu::datetime::mock::zoned_datetime::MockZonedDateTime; /// use icu::datetime::ZonedDateTimeFormatter; /// use icu_datetime::TimeZoneFormatterOptions; - /// use icu_provider::inv::InvariantDataProvider; /// # let locale = icu::locid::locale!("en"); - /// # let date_provider = InvariantDataProvider; - /// # let zone_provider = InvariantDataProvider; - /// # let plural_provider = InvariantDataProvider; - /// # let decimal_provider = InvariantDataProvider; + /// # let provider = icu_testdata::get_provider(); /// # let options = icu::datetime::DateTimeFormatterOptions::default(); /// let zdtf = ZonedDateTimeFormatter::::try_new( /// locale, - /// &date_provider, - /// &zone_provider, - /// &plural_provider, - /// &decimal_provider, + /// &provider, + /// &provider, + /// &provider, + /// &provider, /// &options.into(), /// &TimeZoneFormatterOptions::default(), /// ) diff --git a/components/datetime/tests/datetime.rs b/components/datetime/tests/datetime.rs index 0835fa4b8d3..4e7578f3363 100644 --- a/components/datetime/tests/datetime.rs +++ b/components/datetime/tests/datetime.rs @@ -39,8 +39,8 @@ use icu_locid::{ }; use icu_plurals::provider::OrdinalV1Marker; use icu_provider::prelude::*; +use icu_provider_adapters::any_payload::AnyPayloadProvider; use icu_provider_adapters::fork::by_key::MultiForkByKeyProvider; -use icu_provider_adapters::struct_provider::AnyPayloadProvider; use patterns::{ get_dayperiod_tests, get_time_zone_tests, structs::{ diff --git a/components/decimal/README.md b/components/decimal/README.md index 92cf9ef6ab1..6b9032051b4 100644 --- a/components/decimal/README.md +++ b/components/decimal/README.md @@ -36,7 +36,7 @@ use icu::decimal::FixedDecimalFormatter; use icu::locid::Locale; use writeable::Writeable; -let provider = icu_provider::inv::InvariantDataProvider; +let provider = icu_testdata::get_provider(); let fdf = FixedDecimalFormatter::try_new(Locale::UND, &provider, Default::default()) .expect("Data should load successfully"); diff --git a/components/decimal/benches/fixed_decimal_format.rs b/components/decimal/benches/fixed_decimal_format.rs index 5b32d70d9b9..659af4f6f59 100644 --- a/components/decimal/benches/fixed_decimal_format.rs +++ b/components/decimal/benches/fixed_decimal_format.rs @@ -9,8 +9,10 @@ use rand_pcg::Lcg64Xsh32; use criterion::{black_box, criterion_group, criterion_main, Criterion}; use fixed_decimal::FixedDecimal; +use icu_decimal::provider::DecimalSymbolsV1Marker; use icu_decimal::FixedDecimalFormatter; use icu_locid::Locale; +use icu_provider_adapters::any_payload::AnyPayloadProvider; use writeable::Writeable; fn triangular_nums(range: f64) -> Vec { @@ -26,19 +28,17 @@ fn triangular_nums(range: f64) -> Vec { fn overview_bench(c: &mut Criterion) { let nums = triangular_nums(1e9); + let provider = AnyPayloadProvider::new_default::(); c.bench_function("icu_decimal/overview", |b| { - #[allow(clippy::suspicious_map)] b.iter(|| { // This benchmark demonstrates the performance of the format function on 1000 numbers // ranging from -1e9 to 1e9. - let provider = icu_provider::inv::InvariantDataProvider; let fdf = FixedDecimalFormatter::try_new(Locale::UND, &provider, Default::default()).unwrap(); - nums.iter() - .map(|v| black_box(*v)) - .map(FixedDecimal::from) - .map(|n| fdf.format(&n).write_to_string().into_owned()) - .count(); + for &num in &nums { + let fd = FixedDecimal::from(black_box(num)); + fdf.format(&fd).write_to_string().into_owned(); + } }); }); } diff --git a/components/decimal/src/grouper.rs b/components/decimal/src/grouper.rs index 2944caa75e7..fbf147482f3 100644 --- a/components/decimal/src/grouper.rs +++ b/components/decimal/src/grouper.rs @@ -59,7 +59,7 @@ fn test_grouper() { use fixed_decimal::FixedDecimal; use icu_locid::LanguageIdentifier; use icu_provider::prelude::*; - use icu_provider_adapters::struct_provider::AnyPayloadProvider; + use icu_provider_adapters::any_payload::AnyPayloadProvider; use writeable::Writeable; let western_sizes = GroupingSizesV1 { @@ -157,15 +157,12 @@ fn test_grouper() { let dec = FixedDecimal::from(1) .multiplied_pow10((i as i16) + 3) .unwrap(); - let data_struct = crate::provider::DecimalSymbolsV1 { - grouping_sizes: cas.sizes, - ..Default::default() - }; - let provider = AnyPayloadProvider { - key: DecimalSymbolsV1Marker::KEY, - data: DataPayload::::from_owned(data_struct) - .wrap_into_any_payload(), - }; + let provider = AnyPayloadProvider::new_owned::( + crate::provider::DecimalSymbolsV1 { + grouping_sizes: cas.sizes, + ..Default::default() + }, + ); let options = options::FixedDecimalFormatterOptions { grouping_strategy: cas.strategy, ..Default::default() diff --git a/components/decimal/src/lib.rs b/components/decimal/src/lib.rs index 7ceecdb6245..4e223843d7d 100644 --- a/components/decimal/src/lib.rs +++ b/components/decimal/src/lib.rs @@ -40,7 +40,7 @@ //! use icu::locid::Locale; //! use writeable::Writeable; //! -//! let provider = icu_provider::inv::InvariantDataProvider; +//! let provider = icu_testdata::get_provider(); //! let fdf = FixedDecimalFormatter::try_new(Locale::UND, &provider, Default::default()) //! .expect("Data should load successfully"); //! diff --git a/components/decimal/src/options.rs b/components/decimal/src/options.rs index 4e4ff3a2519..f79d8cfe706 100644 --- a/components/decimal/src/options.rs +++ b/components/decimal/src/options.rs @@ -25,7 +25,7 @@ pub struct FixedDecimalFormatterOptions { /// use writeable::Writeable; /// /// let locale = Locale::UND; -/// let provider = icu_provider::inv::InvariantDataProvider; +/// let provider = icu_testdata::get_provider(); /// let mut options: options::FixedDecimalFormatterOptions = Default::default(); /// options.grouping_strategy = options::GroupingStrategy::Min2; /// let fdf = FixedDecimalFormatter::try_new(locale, &provider, options) diff --git a/components/icu/src/lib.rs b/components/icu/src/lib.rs index db0069f36f0..807a0d08edf 100644 --- a/components/icu/src/lib.rs +++ b/components/icu/src/lib.rs @@ -170,7 +170,7 @@ pub mod decimal { //! use icu::locid::Locale; //! use writeable::Writeable; //! - //! let provider = icu_provider::inv::InvariantDataProvider; + //! let provider = icu_testdata::get_provider(); //! let fdf = FixedDecimalFormatter::try_new(Locale::UND, &provider, Default::default()) //! .expect("Data should load successfully"); //! diff --git a/components/plurals/src/lib.rs b/components/plurals/src/lib.rs index aff851161ec..6a85f61d525 100644 --- a/components/plurals/src/lib.rs +++ b/components/plurals/src/lib.rs @@ -138,9 +138,8 @@ pub enum PluralRuleType { /// ``` /// use icu::locid::locale; /// use icu::plurals::{PluralCategory, PluralRuleType, PluralRules}; -/// use icu_provider::inv::InvariantDataProvider; /// -/// let dp = InvariantDataProvider; +/// let dp = icu_testdata::get_provider(); /// /// let pr = PluralRules::try_new(locale!("en"), &dp, PluralRuleType::Cardinal) /// .expect("Failed to construct a PluralRules struct."); @@ -265,9 +264,8 @@ impl PluralCategory { /// ``` /// use icu::locid::locale; /// use icu::plurals::{PluralCategory, PluralRuleType, PluralRules}; -/// use icu_provider::inv::InvariantDataProvider; /// -/// let dp = InvariantDataProvider; +/// let dp = icu_testdata::get_provider(); /// /// let pr = PluralRules::try_new(locale!("en"), &dp, PluralRuleType::Cardinal) /// .expect("Failed to construct a PluralRules struct."); @@ -293,11 +291,10 @@ impl PluralRules { /// ``` /// use icu::locid::locale; /// use icu::plurals::{PluralRuleType, PluralRules}; - /// use icu_provider::inv::InvariantDataProvider; /// /// let lid = locale!("en"); /// - /// let dp = InvariantDataProvider; + /// let dp = icu_testdata::get_provider(); /// /// let _ = PluralRules::try_new(lid, &dp, PluralRuleType::Cardinal); /// ``` @@ -414,9 +411,8 @@ impl PluralRules { /// ``` /// use icu::locid::locale; /// use icu::plurals::{PluralCategory, PluralRuleType, PluralRules}; - /// use icu_provider::inv::InvariantDataProvider; /// - /// let dp = InvariantDataProvider; + /// let dp = icu_testdata::get_provider(); /// /// let pr = PluralRules::try_new(locale!("en"), &dp, PluralRuleType::Cardinal) /// .expect("Failed to construct a PluralRules struct."); @@ -442,10 +438,9 @@ impl PluralRules { /// use icu::locid::locale; /// use icu::plurals::{PluralCategory, PluralOperands}; /// use icu::plurals::{PluralRuleType, PluralRules}; - /// use icu_provider::inv::InvariantDataProvider; /// use std::convert::TryFrom; /// # - /// # let dp = InvariantDataProvider; + /// # let dp = icu_testdata::get_provider(); /// # /// # let pr = PluralRules::try_new(locale!("en"), &dp, PluralRuleType::Cardinal) /// # .expect("Failed to construct a PluralRules struct."); @@ -492,7 +487,6 @@ impl PluralRules { /// ``` /// use icu::locid::locale; /// use icu::plurals::{PluralCategory, PluralRuleType, PluralRules}; - /// use icu_provider::inv::InvariantDataProvider; /// /// let dp = icu_testdata::get_provider(); /// diff --git a/ffi/diplomat/src/decimal.rs b/ffi/diplomat/src/decimal.rs index 7ba397d9123..7769b27f0e8 100644 --- a/ffi/diplomat/src/decimal.rs +++ b/ffi/diplomat/src/decimal.rs @@ -14,7 +14,7 @@ pub mod ffi { use icu_locid::Locale; use icu_provider::ResourceMarker; use icu_provider::ResourceProvider; - use icu_provider_adapters::struct_provider::AnyPayloadProvider; + use icu_provider_adapters::any_payload::AnyPayloadProvider; use writeable::Writeable; use crate::{ diff --git a/ffi/ecma402/src/pluralrules.rs b/ffi/ecma402/src/pluralrules.rs index 8de1c3607c2..2a2dd1a3360 100644 --- a/ffi/ecma402/src/pluralrules.rs +++ b/ffi/ecma402/src/pluralrules.rs @@ -236,7 +236,7 @@ pub struct PluralRules { impl ecma402_traits::pluralrules::PluralRules for PluralRules { type Error = PluralRulesError; - fn try_new(l: L, opts: ecma402_traits::pluralrules::Options) -> Result + fn try_new(_l: L, _opts: ecma402_traits::pluralrules::Options) -> Result where L: ecma402_traits::Locale, Self: Sized, diff --git a/provider/adapters/src/struct_provider.rs b/provider/adapters/src/any_payload.rs similarity index 54% rename from provider/adapters/src/struct_provider.rs rename to provider/adapters/src/any_payload.rs index 2c6de86b129..9bb8f2b0584 100644 --- a/provider/adapters/src/struct_provider.rs +++ b/provider/adapters/src/any_payload.rs @@ -9,30 +9,23 @@ use yoke::trait_hack::YokeTraitHack; use yoke::Yokeable; use zerofrom::ZeroFrom; -/// A data provider that returns clones of a constant type-erased payload. +/// A data provider that returns clones of a fixed type-erased payload. /// /// # Examples /// /// ``` /// use icu_provider::hello_world::*; /// use icu_provider::prelude::*; -/// use icu_provider_adapters::struct_provider::AnyPayloadProvider; +/// use icu_provider_adapters::any_payload::AnyPayloadProvider; /// use std::borrow::Cow; /// -/// const CONST_DATA: HelloWorldV1<'static> = HelloWorldV1 { -/// message: Cow::Borrowed("hello world"), -/// }; -/// -/// // A placeholder key to use to serve the data struct -/// const SAMPLE_KEY: ResourceKey = icu_provider::resource_key!("xyz/example@1"); -/// -/// let provider = AnyPayloadProvider { -/// key: SAMPLE_KEY, -/// data: AnyPayload::from_static_ref(&CONST_DATA), -/// }; +/// let provider = AnyPayloadProvider::new_static::( +/// &HelloWorldV1 { +/// message: Cow::Borrowed("hello world"), +/// }); /// /// let payload: DataPayload = provider -/// .load_any(SAMPLE_KEY, &DataRequest::default()) +/// .load_any(HelloWorldV1Marker::KEY, &Default::default()) /// .expect("Load should succeed") /// .downcast() /// .expect("Types should match") @@ -47,6 +40,34 @@ pub struct AnyPayloadProvider { pub data: AnyPayload, } +impl AnyPayloadProvider { + /// Creates an `AnyPayloadProvider` with an owned (allocated) payload of the given data. + pub fn new_owned(data: M::Yokeable) -> Self { + AnyPayloadProvider { + key: M::KEY, + data: AnyPayload::from_rc_payload::(alloc::rc::Rc::from(DataPayload::from_owned( + data, + ))), + } + } + + /// Creates an `AnyPayloadProvider` with a statically borrowed payload of the given data. + pub fn new_static(data: &'static M::Yokeable) -> Self { + AnyPayloadProvider { + key: M::KEY, + data: AnyPayload::from_static_ref(data), + } + } + + /// Creates an `AnyPayloadProvider` with the default (allocated) version of the data struct. + pub fn new_default() -> Self + where + M::Yokeable: Default, + { + Self::new_owned::(M::Yokeable::default()) + } +} + impl AnyProvider for AnyPayloadProvider { fn load_any(&self, key: ResourceKey, _: &DataRequest) -> Result { key.match_key(self.key)?; diff --git a/provider/adapters/src/lib.rs b/provider/adapters/src/lib.rs index a6f4c1727ac..038d718f478 100644 --- a/provider/adapters/src/lib.rs +++ b/provider/adapters/src/lib.rs @@ -25,9 +25,9 @@ extern crate alloc; +pub mod any_payload; pub mod either; pub mod fallback; pub mod filter; pub mod fork; mod helpers; -pub mod struct_provider; diff --git a/provider/core/README.md b/provider/core/README.md index 32723a974a3..7eb163139f1 100644 --- a/provider/core/README.md +++ b/provider/core/README.md @@ -56,13 +56,15 @@ Examples of Type 2 providers: - [`FsDataProvider`] reads individual buffers from the filesystem. - [`BlobDataProvider`] reads buffers from a large in-memory blob. -#### Special-Purpose Providers +#### Testing Provider -This crate also contains some concrete implementations for testing purposes: +This crate also contains a concrete provider for testing purposes: -- [`InvariantDataProvider`] returns fixed data that does not vary by locale. - [`HelloWorldProvider`] returns "hello world" strings in several languages. +If you need a testing provider that contains the actual resource keys used by ICU4X features, +see the [`icu_testdata`] crate. + ### Provider Adapters ICU4X offers several built-in modules to combine providers in interesting ways. @@ -76,25 +78,12 @@ associated with a marker type implementing [`DataMarker`]. Data structs should generally have one lifetime argument: `'data`. This lifetime allows data structs to borrow zero-copy data. -### Additional Traits - -#### `DataProvider` - -*Enabled with the "datagen" feature* - -Data providers capable of returning opaque `erased_serde::Serialize` trait objects can be use -as input to a data exporter, such as when writing data to the filesystem. - -This trait is normally implemented using the [`impl_dyn_provider!`] macro. - -#### `IterableDataProvider` - -*Enabled with the "datagen" feature* +### Data generation API -Data providers can implement [`IterableDynProvider`]/[`IterableResourceProvider`], allowing -iteration over all [`ResourceOptions`] instances supported for a certain key in the data provider. +*This functionality is enabled with the "datagen" feature* -This trait is normally implemented using the [`impl_dyn_provider!`] macro using the `ITERABLE_SERDE_SE` option. +The [`datagen`] module contains several APIs for data generation. See [`icu_datagen`] for the reference +data generation implementation. [`ICU4X`]: ../icu/index.html [`DataProvider`]: data_provider::DataProvider @@ -102,8 +91,7 @@ This trait is normally implemented using the [`impl_dyn_provider!`] macro using [`ResourceOptions`]: resource::ResourceOptions [`IterableDynProvider`]: datagen::IterableDynProvider [`IterableResourceProvider`]: datagen::IterableResourceProvider -[`InvariantDataProvider`]: inv::InvariantDataProvider -[`AnyPayloadProvider`]: ../icu_provider_adapters/struct_provider/struct.AnyPayloadProvider.html +[`AnyPayloadProvider`]: ../icu_provider_adapters/any_payload/struct.AnyPayloadProvider.html [`HelloWorldProvider`]: hello_world::HelloWorldProvider [`AnyProvider`]: any::AnyProvider [`Yokeable`]: yoke::Yokeable @@ -114,6 +102,8 @@ This trait is normally implemented using the [`impl_dyn_provider!`] macro using [`CldrJsonDataProvider`]: ../icu_datagen/cldr/struct.CldrJsonDataProvider.html [`FsDataProvider`]: ../icu_provider_fs/struct.FsDataProvider.html [`BlobDataProvider`]: ../icu_provider_blob/struct.BlobDataProvider.html +[`icu_testdata`]: ../icu_testdata/index.html +[`icu_datagen`]: ../icu_datagen/index.html ## More Information diff --git a/provider/core/src/any.rs b/provider/core/src/any.rs index 564ec182f1f..aab5420e81f 100644 --- a/provider/core/src/any.rs +++ b/provider/core/src/any.rs @@ -249,36 +249,30 @@ impl AnyResponse { /// /// # Examples /// -/// [`AnyPayloadProvider`] implements `AnyProvider`. -/// /// ``` /// use icu_provider::hello_world::*; /// use icu_provider::prelude::*; -/// use icu_provider_adapters::struct_provider::AnyPayloadProvider; /// use std::borrow::Cow; /// -/// const CONST_DATA: HelloWorldV1<'static> = HelloWorldV1 { -/// message: Cow::Borrowed("Custom Hello World"), -/// }; -/// -/// let provider = AnyPayloadProvider { -/// key: HelloWorldV1Marker::KEY, -/// data: AnyPayload::from_static_ref(&CONST_DATA), -/// }; -/// -/// let any_response = provider -/// .load_any(HelloWorldV1Marker::KEY, &DataRequest::default()) +/// let any_response = HelloWorldProvider +/// .as_any_provider() +/// .load_any( +/// HelloWorldV1Marker::KEY, +/// &DataRequest { +/// options: icu_locid::locale!("de").into(), +/// metadata: Default::default(), +/// }, +/// ) /// .expect("Load should succeed"); /// /// // Downcast to something useful -/// let response: DataResponse = any_response.downcast().expect("Types match"); +/// let response: DataResponse = +/// any_response.downcast().expect("Types match"); /// /// let payload = response.take_payload().expect("Data should be present"); /// -/// assert_eq!(payload.get().message, "Custom Hello World"); +/// assert_eq!(payload.get().message, "Hallo Welt"); /// ``` -/// -/// [`AnyPayloadProvider`]: ../icu_provider_adapters/struct_provider/struct.AnyPayloadProvider.html pub trait AnyProvider { fn load_any(&self, key: ResourceKey, req: &DataRequest) -> Result; } diff --git a/provider/core/src/datagen/mod.rs b/provider/core/src/datagen/mod.rs index e143a512d08..01f7709290b 100644 --- a/provider/core/src/datagen/mod.rs +++ b/provider/core/src/datagen/mod.rs @@ -3,10 +3,10 @@ // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). //! This module contains various utilities required to generate ICU4X data files, typically -//! via the `icu4x-datagen` tool. End users should not need to consume anything in this module -//! as a library unless defining new types that integrate with `icu4x-datagen`. +//! via the `icu_datagen` reference crate. End users should not need to consume anything in +//! this module as a library unless defining new types that integrate with `icu_datagen`. //! -//! This module can be enabled with the `datagen` feature on `icu4x-provider-core`. +//! This module can be enabled with the `datagen` feature on `icu_provider`. mod data_conversion; mod heap_measure; @@ -14,7 +14,11 @@ mod iter; mod payload; pub use data_conversion::{DataConverter, ReturnedPayloadError}; pub use heap_measure::{HeapStats, HeapStatsMarker}; -pub use iter::{IterableDynProvider, IterableResourceProvider}; +pub use iter::IterableResourceProvider; + +#[doc(hidden)] // exposed for make_exportable_provider +pub use iter::IterableDynProvider; +#[doc(hidden)] // exposed for make_exportable_provider pub use payload::{ExportBox, ExportMarker}; use crate::prelude::*; @@ -45,9 +49,23 @@ pub trait DataExporter: Sync { } /// A [`DynProvider`] that can be used for exporting data. +/// +/// Use [`make_exportable_provider`] to implement this. pub trait ExportableProvider: IterableDynProvider + Sync {} impl ExportableProvider for T where T: IterableDynProvider + Sync {} +/// This macro can be used on a data provider to allow it to be used for data generation. +/// +/// Data generation 'compiles' data by using this data provider (which usually translates data from +/// different sources and doesn't have to be efficient) to generate data structs, and then writing +/// them to an efficient format like [`BlobDataProvider`] or [`BakedDataProvider`]. The requirements +/// for `make_exportable_provider` are: +/// * The data struct has to implement [`serde::Serialize`](::serde::Serialize) and [`databake::Bake`] +/// * The provider needs to implement [`IterableResourceProvider`] for all specified [`ResourceMarker`]s. +/// This allows the generating code to know which [`ResourceOptions`] to collect. +/// +/// [`BlobDataProvider`]: ../../icu_provider_blob/struct.BlobDataProvider.html +/// [`BakedDataProvider`]: ../../icu_datagen/index.html #[macro_export] macro_rules! make_exportable_provider { ($provider:ty, [ $($struct_m:ident),+, ]) => { diff --git a/provider/core/src/dynutil.rs b/provider/core/src/dynutil.rs index 62a11a62b27..17073a83b4a 100644 --- a/provider/core/src/dynutil.rs +++ b/provider/core/src/dynutil.rs @@ -49,55 +49,40 @@ where /// ## Wrapping ResourceProvider /// /// If your type implements [`ResourceProvider`], pass a list of markers as the second argument. -/// This results in a `DynProvider` that delegates to a specific marker if the key +/// This results in a `DynProvider` that delegates to a specific marker if the key /// matches or else returns [`DataErrorKind::MissingResourceKey`]. /// /// ``` -/// use icu_provider::datagen::*; -/// use icu_provider::hello_world::*; -/// use icu_provider::inv::InvariantDataProvider; /// use icu_provider::prelude::*; -/// -/// // Example struct that implements ResourceProvider -/// struct MyProvider; -/// impl ResourceProvider for MyProvider { -/// fn load_resource( -/// &self, -/// req: &DataRequest, -/// ) -> Result, DataError> { -/// let provider = InvariantDataProvider; -/// provider.load_resource(req) -/// } -/// } -/// -/// impl IterableResourceProvider for MyProvider { -/// fn supported_options( -/// &self, -/// ) -> Result, DataError> { -/// Ok(vec![Default::default()]) -/// } -/// } -/// -/// // Implement DataProvider on this struct -/// icu_provider::impl_dyn_provider!(MyProvider, [HelloWorldV1Marker,], AnyMarker); -/// -/// let provider = MyProvider; -/// -/// // Successful result if the key matches: -/// assert!(matches!( -/// provider.load_payload(HelloWorldV1Marker::KEY, &Default::default()), -/// Ok(_) -/// )); -/// -/// // Failure if the key does not match: -/// let DUMMY_KEY = icu_provider::resource_key!("dummy@1"); -/// assert!(matches!( -/// provider.load_payload(DUMMY_KEY, &Default::default()), -/// Err(DataError { -/// kind: DataErrorKind::MissingResourceKey, -/// .. -/// }) -/// )); +/// use icu_provider::hello_world::*; +/// # +/// # // Duplicating HelloWorldProvider because the real one already implements DynProvider +/// # struct HelloWorldProvider; +/// # impl ResourceProvider for HelloWorldProvider { +/// # fn load_resource( +/// # &self, +/// # req: &DataRequest, +/// # ) -> Result, DataError> { +/// # icu_provider::hello_world::HelloWorldProvider.load_resource(req) +/// # } +/// # } +/// +/// // Implement DataProvider on HelloWorldProvider: ResourceProvider +/// icu_provider::impl_dyn_provider!(HelloWorldProvider, [HelloWorldV1Marker,], AnyMarker); +/// +/// let req = DataRequest { +/// options: icu_locid::locale!("de").into(), +/// metadata: Default::default(), +/// }; +/// +/// // Successful because the key matches: +/// HelloWorldProvider.load_payload(HelloWorldV1Marker::KEY, &req).unwrap(); +/// +/// // MissingResourceKey error as the key does not match: +/// assert_eq!( +/// HelloWorldProvider.load_payload(icu_provider::resource_key!("dummy@1"), &req).unwrap_err().kind, +/// DataErrorKind::MissingResourceKey, +/// ); /// ``` /// /// ## Wrapping DynProvider @@ -107,50 +92,34 @@ where /// /// ``` /// use icu_provider::prelude::*; -/// use icu_provider::datagen::*; /// use icu_provider::hello_world::*; -/// use icu_provider::inv::InvariantDataProvider; -/// -/// // Example struct that implements DynProvider -/// struct MyProvider; -/// impl DynProvider for MyProvider { -/// fn load_payload(&self, key: ResourceKey, req: &DataRequest) -/// -> Result, DataError> { -/// let provider = InvariantDataProvider; -/// provider.load_resource(req) -/// } -/// } -/// -/// impl IterableDynProvider for MyProvider { -/// fn supported_options_for_key(&self, _: ResourceKey) -/// -> Result, DataError> { -/// Ok(vec![Default::default()]) -/// } -/// } -/// -/// // Implement DataProvider on this struct. -/// // Match HelloWorldV1Marker::KEY and delegate to DynProvider. -/// // Send the wildcard match also to DynProvider. -/// icu_provider::impl_dyn_provider!(MyProvider, { +/// # +/// # struct HelloWorldProvider; +/// # impl DynProvider for HelloWorldProvider { +/// # fn load_payload(&self, key: ResourceKey, req: &DataRequest) +/// # -> Result, DataError> { +/// # icu_provider::hello_world::HelloWorldProvider.load_resource(req) +/// # } +/// # } +/// +/// // Implement DataProvider on HelloWorldProvider: DynProvider +/// icu_provider::impl_dyn_provider!(HelloWorldProvider, { +/// // Match HelloWorldV1Marker::KEY and delegate to DynProvider. /// HW = HelloWorldV1Marker::KEY => HelloWorldV1Marker, +/// // Send the wildcard match also to DynProvider. /// _ => HelloWorldV1Marker, /// }, AnyMarker); /// -/// let provider = MyProvider; -/// let provider = provider.as_any_provider(); +/// let req = DataRequest { +/// options: icu_locid::locale!("de").into(), +/// metadata: Default::default(), +/// }; /// -/// // Successful result if the key matches: -/// assert!(matches!( -/// provider.load_any(HelloWorldV1Marker::KEY, &Default::default()), -/// Ok(_) -/// )); +/// // Successful because the key matches: +/// HelloWorldProvider.as_any_provider().load_any(HelloWorldV1Marker::KEY, &req).unwrap(); /// -/// // Because of the wildcard, non-matching requests are captured: -/// let DUMMY_KEY = icu_provider::resource_key!("dummy@1"); -/// assert!(matches!( -/// provider.load_any(DUMMY_KEY, &Default::default()), -/// Ok(_) -/// )); +/// // Because of the wildcard, any key actually works: +/// HelloWorldProvider.as_any_provider().load_any(icu_provider::resource_key!("dummy@1"), &req).unwrap(); /// ``` /// /// [`DynProvider`]: crate::DynProvider diff --git a/provider/core/src/inv.rs b/provider/core/src/inv.rs deleted file mode 100644 index 4f125b838c1..00000000000 --- a/provider/core/src/inv.rs +++ /dev/null @@ -1,59 +0,0 @@ -// This file is part of ICU4X. For terms of use, please see the file -// called LICENSE at the top level of the ICU4X source tree -// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). - -//! Locale-invariant data provider that requires no I/O. - -use crate::prelude::*; - -/// A locale-invariant data provider. Sometimes useful for testing. Not intended to be used in -/// production environments. -/// -/// The objects returned by [`InvariantDataProvider`] are guaranteed to conform to the correct struct -/// definition, so [`InvariantDataProvider`] can also be used to validate unknown data providers. -/// -/// # Examples -/// -/// ``` -/// use icu_provider::hello_world::HelloWorldV1Marker; -/// use icu_provider::inv::InvariantDataProvider; -/// use icu_provider::prelude::*; -/// use std::borrow::Cow; -/// -/// let provider = InvariantDataProvider; -/// let result: DataPayload = provider -/// .load_resource(&DataRequest::default()) -/// .unwrap() -/// .take_payload() -/// .unwrap(); -/// -/// assert_eq!("(und) Hello World", result.get().message); -/// ``` -#[allow(clippy::exhaustive_structs)] // stable type -pub struct InvariantDataProvider; - -impl ResourceProvider for InvariantDataProvider -where - M: ResourceMarker, - M::Yokeable: Default, -{ - fn load_resource(&self, _: &DataRequest) -> Result, DataError> { - Ok(DataResponse { - metadata: DataResponseMetadata::default(), - payload: Some(DataPayload::from_owned(M::Yokeable::default())), - }) - } -} - -impl DynProvider for InvariantDataProvider -where - M: DataMarker, - M::Yokeable: Default, -{ - fn load_payload(&self, _: ResourceKey, _: &DataRequest) -> Result, DataError> { - Ok(DataResponse { - metadata: DataResponseMetadata::default(), - payload: Some(DataPayload::from_owned(M::Yokeable::default())), - }) - } -} diff --git a/provider/core/src/lib.rs b/provider/core/src/lib.rs index aa336cd7c53..7d38ffe1efe 100644 --- a/provider/core/src/lib.rs +++ b/provider/core/src/lib.rs @@ -58,13 +58,15 @@ //! - [`FsDataProvider`] reads individual buffers from the filesystem. //! - [`BlobDataProvider`] reads buffers from a large in-memory blob. //! -//! ### Special-Purpose Providers +//! ### Testing Provider //! -//! This crate also contains some concrete implementations for testing purposes: +//! This crate also contains a concrete provider for testing purposes: //! -//! - [`InvariantDataProvider`] returns fixed data that does not vary by locale. //! - [`HelloWorldProvider`] returns "hello world" strings in several languages. //! +//! If you need a testing provider that contains the actual resource keys used by ICU4X features, +//! see the [`icu_testdata`] crate. +//! //! ## Provider Adapters //! //! ICU4X offers several built-in modules to combine providers in interesting ways. @@ -78,25 +80,12 @@ //! Data structs should generally have one lifetime argument: `'data`. This lifetime allows data //! structs to borrow zero-copy data. //! -//! ## Additional Traits -//! -//! ### `DataProvider` -//! -//! *Enabled with the "datagen" feature* -//! -//! Data providers capable of returning opaque `erased_serde::Serialize` trait objects can be use -//! as input to a data exporter, such as when writing data to the filesystem. -//! -//! This trait is normally implemented using the [`impl_dyn_provider!`] macro. -//! -//! ### `IterableDataProvider` -//! -//! *Enabled with the "datagen" feature* +//! ## Data generation API //! -//! Data providers can implement [`IterableDynProvider`]/[`IterableResourceProvider`], allowing -//! iteration over all [`ResourceOptions`] instances supported for a certain key in the data provider. +//! *This functionality is enabled with the "datagen" feature* //! -//! This trait is normally implemented using the [`impl_dyn_provider!`] macro using the `ITERABLE_SERDE_SE` option. +//! The [`datagen`] module contains several APIs for data generation. See [`icu_datagen`] for the reference +//! data generation implementation. //! //! [`ICU4X`]: ../icu/index.html //! [`DataProvider`]: data_provider::DataProvider @@ -104,8 +93,7 @@ //! [`ResourceOptions`]: resource::ResourceOptions //! [`IterableDynProvider`]: datagen::IterableDynProvider //! [`IterableResourceProvider`]: datagen::IterableResourceProvider -//! [`InvariantDataProvider`]: inv::InvariantDataProvider -//! [`AnyPayloadProvider`]: ../icu_provider_adapters/struct_provider/struct.AnyPayloadProvider.html +//! [`AnyPayloadProvider`]: ../icu_provider_adapters/any_payload/struct.AnyPayloadProvider.html //! [`HelloWorldProvider`]: hello_world::HelloWorldProvider //! [`AnyProvider`]: any::AnyProvider //! [`Yokeable`]: yoke::Yokeable @@ -116,6 +104,8 @@ //! [`CldrJsonDataProvider`]: ../icu_datagen/cldr/struct.CldrJsonDataProvider.html //! [`FsDataProvider`]: ../icu_provider_fs/struct.FsDataProvider.html //! [`BlobDataProvider`]: ../icu_provider_blob/struct.BlobDataProvider.html +//! [`icu_testdata`]: ../icu_testdata/index.html +//! [`icu_datagen`]: ../icu_datagen/index.html // https://github.com/unicode-org/icu4x/blob/main/docs/process/boilerplate.md#library-annotations #![cfg_attr(not(any(test, feature = "std")), no_std)] @@ -144,7 +134,6 @@ pub mod dynutil; mod error; pub mod hello_world; mod helpers; -pub mod inv; #[macro_use] pub mod marker; #[macro_use]