From 637f9851b6092cbfe0103729c13a33cab64df7ac Mon Sep 17 00:00:00 2001 From: Robert Bastian Date: Fri, 28 Jan 2022 16:49:19 +0100 Subject: [PATCH] Fixing Option borrows --- Cargo.lock | 17 ++ components/datetime/Cargo.toml | 3 +- .../datetime/src/provider/calendar/symbols.rs | 242 +++++++++++++----- 3 files changed, 199 insertions(+), 63 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 75ceb9596b5..9ea173f808b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1150,6 +1150,7 @@ dependencies = [ "serde", "serde-tuple-vec-map", "serde_json", + "serde_with", "smallvec", "tinystr", "writeable", @@ -2274,6 +2275,12 @@ dependencies = [ "semver 1.0.4", ] +[[package]] +name = "rustversion" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f" + [[package]] name = "ryu" version = "1.0.5" @@ -2458,6 +2465,16 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_with" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad6056b4cb69b6e43e3a0f055def223380baecc99da683884f205bf347f7c4b3" +dependencies = [ + "rustversion", + "serde", +] + [[package]] name = "simple_logger" version = "1.13.0" diff --git a/components/datetime/Cargo.toml b/components/datetime/Cargo.toml index 35555035bbd..dc3f8ac188e 100644 --- a/components/datetime/Cargo.toml +++ b/components/datetime/Cargo.toml @@ -46,6 +46,7 @@ smallvec = "1.6" displaydoc = { version = "0.2.3", default-features = false } either = { version = "1.6.1", default-features = false } num_enum = { version = "0.5", default_features = false } +serde_with = { version = "1.11.0", default_features = false, optional = true} [dev-dependencies] criterion = "0.3" @@ -67,7 +68,7 @@ bench = false # This option is required for Benchmark CI std = ["icu_provider/std", "icu_locid/std", "icu_calendar/std"] default = ["provider_serde"] bench = [] -provider_serde = ["serde", "litemap/serde_serialize", "smallvec/serde", "litemap/serde", "zerovec/serde", "tinystr/serde"] +provider_serde = ["serde", "litemap/serde_serialize", "smallvec/serde", "litemap/serde", "zerovec/serde", "tinystr/serde", "serde_with"] provider_transform_internals = ["std"] [[bench]] diff --git a/components/datetime/src/provider/calendar/symbols.rs b/components/datetime/src/provider/calendar/symbols.rs index c0954485cfa..d0fbef0c387 100644 --- a/components/datetime/src/provider/calendar/symbols.rs +++ b/components/datetime/src/provider/calendar/symbols.rs @@ -42,61 +42,14 @@ pub struct Eras<'data> { } macro_rules! symbols { - ($name: ident, $expr: ty) => { - pub mod $name { - use super::*; + ($name: ident, $symbols: item) => { + pub mod $name { + use super::*; - #[derive(Debug, PartialEq, Clone, Default, ZeroCopyFrom, Yokeable)] - #[cfg_attr(feature="provider_serde", derive(serde::Serialize, serde::Deserialize))] - pub struct SymbolsV1<'data>(#[cfg_attr(feature="provider_serde", serde(borrow))] pub $expr); + #[derive(Debug, PartialEq, Clone, Default, ZeroCopyFrom, Yokeable)] + #[cfg_attr(feature="provider_serde", derive(serde::Serialize, serde::Deserialize))] + $symbols - symbols!(); - } - }; - ($name: ident { $($tokens: tt)* }) => { - symbols!($name { $($tokens)* } -> ()); - }; - ($name: ident { $element: ident: Option<$ty: ty>, $($tokens: tt)+ } -> ($($members:tt)*)) => { - symbols!($name { $($tokens)* } -> ( - $($members)* - #[cfg_attr(feature = "provider_serde", serde(borrow))] - pub $element: Option<$ty>, - )); - }; - ($name: ident { $element: ident: $ty: ty, $($tokens: tt)+ } -> ($($members:tt)*)) => { - symbols!($name { $($tokens)* } -> ( - $($members)* - #[cfg_attr(feature = "provider_serde", serde(borrow))] - pub $element: $ty, - )); - }; - ($name: ident { $element: ident: Option<$ty: ty> $(,)? } -> ($($members:tt)*)) => { - symbols!($name { } -> ( - $($members)* - #[cfg_attr(feature = "provider_serde", serde(borrow))] - pub $element: Option<$ty>, - )); - }; - ($name: ident { $element: ident: $ty: ty $(,)? } -> ($($members:tt)*)) => { - symbols!($name { } -> ( - $($members)* - #[cfg_attr(feature = "provider_serde", serde(borrow))] - pub $element: $ty, - )); - }; - ($name: ident { } -> ($($members: tt)*)) => { - pub mod $name { - use super::*; - - #[derive(Debug, PartialEq, Clone, Default, Yokeable, ZeroCopyFrom)] - #[cfg_attr(feature="provider_serde", derive(serde::Serialize, serde::Deserialize))] - pub struct SymbolsV1<'data> { - $($members)* - } - symbols!(); - } - }; - () => { // UTS 35 specifies that `format` widths are mandatory // except of `short`. #[derive(Debug, PartialEq, Clone, Default, Yokeable, ZeroCopyFrom)] @@ -134,18 +87,183 @@ macro_rules! symbols { #[cfg_attr(feature = "provider_serde", serde(borrow))] pub stand_alone: Option>, } - }; - } + } + }; +} -symbols!(months, [Cow<'data, str>; 12]); +symbols!( + months, + pub struct SymbolsV1<'data>( + #[cfg_attr( + feature = "provider_serde", + serde(borrow, with = "serde_with::As::<[serde_with::BorrowCow; 12]>") + )] + pub [Cow<'data, str>; 12], + ); +); -symbols!(weekdays, [Cow<'data, str>; 7]); +symbols!( + weekdays, + pub struct SymbolsV1<'data>( + #[cfg_attr( + feature = "provider_serde", + serde(borrow, with = "serde_with::As::<[serde_with::BorrowCow; 7]>") + )] + pub [Cow<'data, str>; 7], + ); +); symbols!( - day_periods { - am: Cow<'data, str>, - pm: Cow<'data, str>, - noon: Option>, - midnight: Option>, + day_periods, + pub struct SymbolsV1<'data> { + #[cfg_attr(feature = "provider_serde", serde(borrow))] + pub am: Cow<'data, str>, + #[cfg_attr(feature = "provider_serde", serde(borrow))] + pub pm: Cow<'data, str>, + #[cfg_attr( + feature = "provider_serde", + serde(borrow, with = "serde_with::As::>") + )] + pub noon: Option>, + #[cfg_attr( + feature = "provider_serde", + serde(borrow, with = "serde_with::As::>") + )] + pub midnight: Option>, } ); + +#[cfg(all(test, feature = "provider_serde"))] +mod test { + use super::*; + + fn serialize() -> Vec { + let months = months::SymbolsV1([ + Cow::Owned("January".to_string()), + Cow::Owned("February".to_string()), + Cow::Owned("March".to_string()), + Cow::Owned("April".to_string()), + Cow::Owned("May".to_string()), + Cow::Owned("June".to_string()), + Cow::Owned("July".to_string()), + Cow::Owned("August".to_string()), + Cow::Owned("September".to_string()), + Cow::Owned("October".to_string()), + Cow::Owned("November".to_string()), + Cow::Owned("December".to_string()), + ]); + + let weekdays = weekdays::SymbolsV1([ + Cow::Owned("Monday".to_string()), + Cow::Owned("Tuesday".to_string()), + Cow::Owned("Wednesday".to_string()), + Cow::Owned("Thursday".to_string()), + Cow::Owned("Friday".to_string()), + Cow::Owned("Saturday".to_string()), + Cow::Owned("Sunday".to_string()), + ]); + + let day_periods = day_periods::SymbolsV1 { + am: Cow::Owned("am".to_string()), + pm: Cow::Owned("pm".to_string()), + noon: Some(Cow::Owned("noon".to_string())), + midnight: None, + }; + + bincode::serialize(&DateSymbolsV1 { + months: months::ContextsV1 { + format: months::FormatWidthsV1 { + abbreviated: months.clone(), + narrow: months.clone(), + short: Some(months.clone()), + wide: months.clone(), + }, + stand_alone: Some(months::StandAloneWidthsV1 { + abbreviated: Some(months.clone()), + narrow: Some(months.clone()), + short: Some(months.clone()), + wide: Some(months.clone()), + }), + }, + weekdays: weekdays::ContextsV1 { + format: weekdays::FormatWidthsV1 { + abbreviated: weekdays.clone(), + narrow: weekdays.clone(), + short: Some(weekdays.clone()), + wide: weekdays.clone(), + }, + stand_alone: Some(weekdays::StandAloneWidthsV1 { + abbreviated: Some(weekdays.clone()), + narrow: Some(weekdays.clone()), + short: Some(weekdays.clone()), + wide: Some(weekdays.clone()), + }), + }, + day_periods: day_periods::ContextsV1 { + format: day_periods::FormatWidthsV1 { + abbreviated: day_periods.clone(), + narrow: day_periods.clone(), + short: Some(day_periods.clone()), + wide: day_periods.clone(), + }, + stand_alone: Some(day_periods::StandAloneWidthsV1 { + abbreviated: Some(day_periods.clone()), + narrow: Some(day_periods.clone()), + short: Some(day_periods.clone()), + wide: Some(day_periods.clone()), + }), + }, + eras: Eras { + names: ZeroMap::new(), + abbr: ZeroMap::new(), + narrow: ZeroMap::new(), + }, + }) + .unwrap() + } + + #[test] + fn months_borrows() { + let bytes = serialize(); + let de = bincode::deserialize::(&bytes).unwrap(); + + assert!(matches!(de.months.format.narrow.0[2], Cow::Borrowed(_))); + assert!(matches!( + de.months.format.short.as_ref().unwrap().0[11], + Cow::Borrowed(_) + )); + } + + #[test] + fn weekdays_borrows() { + let bytes = serialize(); + let de = bincode::deserialize::(&bytes).unwrap(); + + assert!(matches!(de.weekdays.format.narrow.0[2], Cow::Borrowed(_))); + assert!(matches!( + de.weekdays.format.short.as_ref().unwrap().0[4], + Cow::Borrowed(_) + )); + } + + #[test] + fn day_periods_borrows() { + let bytes = serialize(); + let de = bincode::deserialize::(&bytes).unwrap(); + + assert!(matches!( + de.day_periods.format.narrow.noon, + Some(Cow::Borrowed(_)) + )); + assert!(matches!( + de.day_periods.format.short.as_ref().unwrap().noon, + Some(Cow::Borrowed(_)) + )); + + assert!(matches!(de.day_periods.format.narrow.am, Cow::Borrowed(_))); + assert!(matches!( + de.day_periods.format.short.as_ref().unwrap().am, + Cow::Borrowed(_) + )); + } +}