Skip to content

Commit faa9644

Browse files
committed
impl Serde for PatternsPackedV1
1 parent 934301e commit faa9644

File tree

2 files changed

+114
-4
lines changed

2 files changed

+114
-4
lines changed

components/datetime/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ datagen = [
8888
"dep:litemap",
8989
"icu_calendar/datagen",
9090
"icu_timezone/datagen",
91+
"icu_plurals/datagen",
9192
"serde",
9293
"std",
9394
]

components/datetime/src/provider/packed_pattern.rs

Lines changed: 113 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ use crate::pattern::runtime::Pattern;
2020

2121
/// A field of [`PackedPatternsBuilder`].
2222
#[derive(Debug, Clone, PartialEq, Eq)]
23+
#[cfg_attr(feature = "serde", derive(serde::Deserialize))] // human-readable only
24+
#[cfg_attr(feature = "datagen", derive(serde::Serialize))] // human-readable only
2325
pub struct LengthPluralElements<T> {
2426
/// The "long" length pattern plural elements.
2527
pub long: PluralElements<T>,
@@ -31,12 +33,19 @@ pub struct LengthPluralElements<T> {
3133

3234
/// A builder for a [`PackedPatternsV1`].
3335
#[derive(Debug, Clone, PartialEq, Eq)]
36+
#[cfg_attr(feature = "serde", derive(serde::Deserialize))] // human-readable only
37+
#[cfg_attr(feature = "datagen", derive(serde::Serialize))] // human-readable only
3438
pub struct PackedPatternsBuilder<'a> {
3539
/// Patterns always available.
40+
#[cfg_attr(feature = "serde", serde(borrow))]
3641
pub standard: LengthPluralElements<Pattern<'a>>,
3742
/// Patterns for variant 0. If `None`, falls back to standard.
43+
#[cfg_attr(feature = "serde", serde(borrow))]
44+
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
3845
pub variant0: Option<LengthPluralElements<Pattern<'a>>>,
3946
/// Patterns for variant 1. If `None`, falls back to standard.
47+
#[cfg_attr(feature = "serde", serde(borrow))]
48+
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
4049
pub variant1: Option<LengthPluralElements<Pattern<'a>>>,
4150
}
4251

@@ -362,6 +371,61 @@ impl PackedPatternsV1<'_> {
362371
}
363372
}
364373

374+
#[cfg(feature = "serde")]
375+
mod _serde {
376+
use super::*;
377+
use zerovec::VarZeroSlice;
378+
379+
#[cfg(feature = "serde")]
380+
#[derive(serde::Deserialize)]
381+
#[cfg_attr(feature = "datagen", derive(serde::Serialize))]
382+
struct PackedPatternsMachine<'data> {
383+
pub header: u32,
384+
#[serde(borrow)]
385+
pub elements: &'data VarZeroSlice<PluralElementsPackedULE<ZeroSlice<PatternItem>>>,
386+
}
387+
388+
impl<'de, 'data> serde::Deserialize<'de> for PackedPatternsV1<'data>
389+
where
390+
'de: 'data,
391+
{
392+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
393+
where
394+
D: serde::Deserializer<'de>,
395+
{
396+
if deserializer.is_human_readable() {
397+
let builder = <PackedPatternsBuilder>::deserialize(deserializer)?;
398+
Ok(builder.build())
399+
} else {
400+
let machine = <PackedPatternsMachine>::deserialize(deserializer)?;
401+
Ok(Self {
402+
header: machine.header,
403+
elements: machine.elements.as_varzerovec(),
404+
})
405+
}
406+
}
407+
}
408+
409+
#[cfg(feature = "datagen")]
410+
impl serde::Serialize for PackedPatternsV1<'_> {
411+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
412+
where
413+
S: serde::Serializer,
414+
{
415+
if serializer.is_human_readable() {
416+
let builder = self.to_builder();
417+
builder.serialize(serializer)
418+
} else {
419+
let machine = PackedPatternsMachine {
420+
header: self.header,
421+
elements: &*self.elements,
422+
};
423+
machine.serialize(serializer)
424+
}
425+
}
426+
}
427+
}
428+
365429
#[cfg(test)]
366430
pub mod tests {
367431
use super::*;
@@ -379,16 +443,20 @@ pub mod tests {
379443
"y MMMM",
380444
];
381445

382-
#[test]
383-
fn test_basic() {
384-
let patterns = PATTERN_STRS
446+
fn get_patterns() -> Vec<Pattern<'static>> {
447+
PATTERN_STRS
385448
.iter()
386449
.map(|s| {
387450
s.parse::<reference::Pattern>()
388451
.unwrap()
389452
.to_runtime_pattern()
390453
})
391-
.collect::<Vec<_>>();
454+
.collect()
455+
}
456+
457+
#[test]
458+
fn test_basic() {
459+
let patterns = get_patterns();
392460
let mut it = patterns.iter().cloned();
393461
let lms0 = LengthPluralElements {
394462
long: PluralElements::new(it.next().unwrap()),
@@ -501,4 +569,45 @@ pub mod tests {
501569
assert_eq!(builder, recovered_builder);
502570
}
503571
}
572+
573+
#[cfg(feature = "datagen")]
574+
#[test]
575+
fn test_serde() {
576+
let patterns = get_patterns();
577+
let lms0a = LengthPluralElements {
578+
long: PluralElements::new(patterns[0].clone()),
579+
medium: PluralElements::new(patterns[0].clone()),
580+
short: PluralElements::new(patterns[1].clone()),
581+
};
582+
let lms1 = LengthPluralElements {
583+
long: PluralElements::new(patterns[3].clone()),
584+
medium: PluralElements::new(patterns[4].clone()),
585+
short: PluralElements::new(patterns[5].clone()),
586+
};
587+
588+
let builder = PackedPatternsBuilder {
589+
standard: lms0a,
590+
variant0: Some(lms1),
591+
variant1: None,
592+
};
593+
let packed = builder.clone().build();
594+
595+
let bincode_bytes = bincode::serialize(&packed).unwrap();
596+
assert_eq!(
597+
bincode_bytes.as_slice(),
598+
&[
599+
26, 11, 0, 0, 76, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 16, 0, 26, 0, 30, 0, 46,
600+
0, 0, 128, 32, 1, 0, 0, 47, 128, 64, 1, 0, 0, 47, 128, 16, 1, 2, 128, 114, 2, 0, 0,
601+
58, 128, 128, 2, 0, 128, 80, 1, 0, 128, 80, 1, 0, 0, 32, 128, 32, 3, 0, 0, 32, 128,
602+
64, 1, 0, 128, 64, 2, 0, 0, 46, 128, 32, 2, 0, 0, 46, 128, 16, 2
603+
][..]
604+
);
605+
let bincode_recovered = bincode::deserialize::<PackedPatternsV1>(&bincode_bytes).unwrap();
606+
assert_eq!(builder, bincode_recovered.to_builder());
607+
608+
let json_str = serde_json::to_string(&packed).unwrap();
609+
assert_eq!(json_str, "{\"standard\":{\"long\":{\"other\":\"M/d/y\"},\"medium\":{\"other\":\"M/d/y\"},\"short\":{\"other\":\"HH:mm\"}},\"variant0\":{\"long\":{\"other\":\"E\"},\"medium\":{\"other\":\"E MMM d\"},\"short\":{\"other\":\"dd.MM.yy\"}}}");
610+
let json_recovered = serde_json::from_str::<PackedPatternsV1>(&json_str).unwrap();
611+
assert_eq!(builder, json_recovered.to_builder());
612+
}
504613
}

0 commit comments

Comments
 (0)