@@ -20,6 +20,8 @@ use crate::pattern::runtime::Pattern;
20
20
21
21
/// A field of [`PackedPatternsBuilder`].
22
22
#[ 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
23
25
pub struct LengthPluralElements < T > {
24
26
/// The "long" length pattern plural elements.
25
27
pub long : PluralElements < T > ,
@@ -31,12 +33,19 @@ pub struct LengthPluralElements<T> {
31
33
32
34
/// A builder for a [`PackedPatternsV1`].
33
35
#[ 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
34
38
pub struct PackedPatternsBuilder < ' a > {
35
39
/// Patterns always available.
40
+ #[ cfg_attr( feature = "serde" , serde( borrow) ) ]
36
41
pub standard : LengthPluralElements < Pattern < ' a > > ,
37
42
/// 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" ) ) ]
38
45
pub variant0 : Option < LengthPluralElements < Pattern < ' a > > > ,
39
46
/// 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" ) ) ]
40
49
pub variant1 : Option < LengthPluralElements < Pattern < ' a > > > ,
41
50
}
42
51
@@ -362,6 +371,61 @@ impl PackedPatternsV1<'_> {
362
371
}
363
372
}
364
373
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
+
365
429
#[ cfg( test) ]
366
430
pub mod tests {
367
431
use super :: * ;
@@ -379,16 +443,20 @@ pub mod tests {
379
443
"y MMMM" ,
380
444
] ;
381
445
382
- #[ test]
383
- fn test_basic ( ) {
384
- let patterns = PATTERN_STRS
446
+ fn get_patterns ( ) -> Vec < Pattern < ' static > > {
447
+ PATTERN_STRS
385
448
. iter ( )
386
449
. map ( |s| {
387
450
s. parse :: < reference:: Pattern > ( )
388
451
. unwrap ( )
389
452
. to_runtime_pattern ( )
390
453
} )
391
- . collect :: < Vec < _ > > ( ) ;
454
+ . collect ( )
455
+ }
456
+
457
+ #[ test]
458
+ fn test_basic ( ) {
459
+ let patterns = get_patterns ( ) ;
392
460
let mut it = patterns. iter ( ) . cloned ( ) ;
393
461
let lms0 = LengthPluralElements {
394
462
long : PluralElements :: new ( it. next ( ) . unwrap ( ) ) ,
@@ -501,4 +569,45 @@ pub mod tests {
501
569
assert_eq ! ( builder, recovered_builder) ;
502
570
}
503
571
}
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
+ }
504
613
}
0 commit comments