• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

zbraniecki / icu4x / 6815798908

09 Nov 2023 05:17PM UTC coverage: 72.607% (-2.4%) from 75.01%
6815798908

push

github

web-flow
Implement `Any/BufferProvider` for some smart pointers (#4255)

Allows storing them as a `Box<dyn Any/BufferProvider>` without using a
wrapper type that implements the trait.

44281 of 60987 relevant lines covered (72.61%)

201375.86 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

84.26
/components/datetime/src/pattern/common/serde.rs
1
// This file is part of ICU4X. For terms of use, please see the file
×
2
// called LICENSE at the top level of the ICU4X source tree
3
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
4

5
use crate::pattern::{PatternItem, TimeGranularity};
6
use ::serde::{de, Deserialize, Deserializer};
7
use alloc::{fmt, format, vec::Vec};
8

9
#[cfg(feature = "datagen")]
10
use ::serde::{ser, Serialize};
11

12
mod reference {
13
    use super::*;
14
    use crate::pattern::reference::Pattern;
15

16
    /// A helper struct that is shaped exactly like `runtime::Pattern`
17
    /// and is used to aid in quick deserialization.
18
    #[derive(Debug, Clone, PartialEq, Deserialize)]
2✔
19
    #[cfg_attr(feature = "datagen", derive(Serialize))]
2✔
20
    struct PatternForSerde {
21
        items: Vec<PatternItem>,
×
22
        time_granularity: TimeGranularity,
×
23
    }
24

25
    impl From<PatternForSerde> for Pattern {
26
        fn from(pfs: PatternForSerde) -> Self {
1✔
27
            Self {
1✔
28
                items: pfs.items,
1✔
29
                time_granularity: pfs.time_granularity,
1✔
30
            }
31
        }
1✔
32
    }
33

34
    impl From<&Pattern> for PatternForSerde {
35
        fn from(pfs: &Pattern) -> Self {
48✔
36
            Self {
48✔
37
                items: pfs.items.clone(),
48✔
38
                time_granularity: pfs.time_granularity,
48✔
39
            }
40
        }
48✔
41
    }
42

43
    #[allow(clippy::upper_case_acronyms)]
44
    pub(crate) struct DeserializePatternUTS35String;
45

46
    impl<'de> de::Visitor<'de> for DeserializePatternUTS35String {
47
        type Value = Pattern;
48

49
        fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
×
50
            write!(formatter, "a valid pattern.")
×
51
        }
×
52

53
        fn visit_str<E>(self, pattern_string: &str) -> Result<Self::Value, E>
4✔
54
        where
55
            E: de::Error,
56
        {
57
            // Parse a string into a list of fields.
58
            pattern_string.parse().map_err(|err| {
4✔
59
                de::Error::invalid_value(
×
60
                    de::Unexpected::Other(&format!("{err}")),
×
61
                    &"a valid UTS 35 pattern string",
62
                )
63
            })
×
64
        }
4✔
65
    }
66

67
    impl<'de> Deserialize<'de> for Pattern {
68
        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
2✔
69
        where
70
            D: Deserializer<'de>,
71
        {
72
            if deserializer.is_human_readable() {
3✔
73
                deserializer.deserialize_str(DeserializePatternUTS35String)
1✔
74
            } else {
75
                let pattern = PatternForSerde::deserialize(deserializer)?;
1✔
76
                Ok(Pattern::from(pattern))
1✔
77
            }
1✔
78
        }
2✔
79
    }
80

81
    #[cfg(feature = "datagen")]
82
    impl Serialize for Pattern {
83
        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
3✔
84
        where
85
            S: ser::Serializer,
86
        {
87
            if serializer.is_human_readable() {
3✔
88
                serializer.serialize_str(&self.to_string())
1✔
89
            } else {
1✔
90
                let pfs = PatternForSerde::from(self);
2✔
91
                pfs.serialize(serializer)
2✔
92
            }
2✔
93
        }
3✔
94
    }
95

96
    #[cfg(all(test, feature = "datagen"))]
97
    mod test {
98
        use super::*;
99

100
        #[test]
101
        fn reference_pattern_serde_human_readable_test() {
2✔
102
            let pattern: Pattern = "Y-m-d HH:mm".parse().expect("Failed to parse pattern");
1✔
103
            let json = serde_json::to_string(&pattern).expect("Failed to serialize pattern");
1✔
104
            let result: Pattern =
105
                serde_json::from_str(&json).expect("Failed to deserialize pattern");
1✔
106
            assert_eq!(pattern, result);
1✔
107
        }
2✔
108

109
        #[test]
110
        fn reference_pattern_serde_bincode_test() {
2✔
111
            let pattern: Pattern = "Y-m-d HH:mm".parse().expect("Failed to parse pattern");
1✔
112
            let bytes = bincode::serialize(&pattern).expect("Failed to serialize pattern");
1✔
113
            let result: Pattern =
114
                bincode::deserialize(&bytes).expect("Failed to deserialize pattern");
1✔
115
            assert_eq!(pattern, result);
1✔
116
        }
2✔
117
    }
118
}
119

120
mod runtime {
121
    use super::*;
122
    use crate::pattern::{runtime::Pattern, PatternItem};
123
    use zerovec::ZeroVec;
124

125
    /// A helper struct that is shaped exactly like `runtime::Pattern`
126
    /// and is used to aid in quick deserialization.
127
    #[derive(Debug, Clone, PartialEq, Deserialize)]
62✔
128
    #[cfg_attr(feature = "datagen", derive(Serialize))]
6✔
129
    struct PatternForSerde<'data> {
130
        #[serde(borrow)]
131
        pub items: ZeroVec<'data, PatternItem>,
×
132
        pub time_granularity: TimeGranularity,
×
133
    }
134

135
    impl<'data> From<PatternForSerde<'data>> for Pattern<'data> {
136
        fn from(pfs: PatternForSerde<'data>) -> Self {
30✔
137
            Self {
30✔
138
                items: pfs.items,
30✔
139
                time_granularity: pfs.time_granularity,
30✔
140
            }
141
        }
30✔
142
    }
143

144
    #[allow(clippy::upper_case_acronyms)]
145
    struct DeserializePatternUTS35String;
146

147
    impl<'de> de::Visitor<'de> for DeserializePatternUTS35String {
148
        type Value = Pattern<'de>;
149

150
        fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
×
151
            write!(formatter, "a valid pattern.")
×
152
        }
×
153

154
        fn visit_str<E>(self, pattern_string: &str) -> Result<Self::Value, E>
3✔
155
        where
156
            E: de::Error,
157
        {
158
            // Parse a string into a list of fields.
159
            let reference_deserializer = super::reference::DeserializePatternUTS35String;
160
            let pattern = reference_deserializer.visit_str(pattern_string)?;
3✔
161

162
            Ok(Self::Value::from(&pattern))
3✔
163
        }
3✔
164
    }
165

166
    impl<'de: 'data, 'data> Deserialize<'de> for Pattern<'data> {
167
        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
35✔
168
        where
169
            D: Deserializer<'de>,
170
        {
171
            if deserializer.is_human_readable() {
65✔
172
                deserializer.deserialize_str(DeserializePatternUTS35String)
3✔
173
            } else {
174
                let pattern = PatternForSerde::deserialize(deserializer)?;
31✔
175
                Ok(Pattern::from(pattern))
30✔
176
            }
30✔
177
        }
33✔
178
    }
179

180
    #[cfg(feature = "datagen")]
181
    impl Serialize for Pattern<'_> {
182
        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
9✔
183
        where
184
            S: ser::Serializer,
185
        {
186
            if serializer.is_human_readable() {
9✔
187
                serializer.serialize_str(&self.to_string())
3✔
188
            } else {
3✔
189
                let pfs = PatternForSerde {
6✔
190
                    items: self.items.clone(),
6✔
191
                    time_granularity: self.time_granularity,
6✔
192
                };
193
                pfs.serialize(serializer)
6✔
194
            }
6✔
195
        }
9✔
196
    }
197

198
    #[cfg(all(test, feature = "datagen"))]
199
    mod test {
200
        use super::*;
201

202
        #[test]
203
        fn runtime_pattern_serde_human_readable_test() {
2✔
204
            let pattern: Pattern = "Y-m-d HH:mm".parse().expect("Failed to parse pattern");
1✔
205
            let json = serde_json::to_string(&pattern).expect("Failed to serialize pattern");
1✔
206
            let result: Pattern =
207
                serde_json::from_str(&json).expect("Failed to deserialize pattern");
1✔
208
            assert_eq!(pattern, result);
1✔
209
        }
2✔
210

211
        #[test]
212
        fn runtime_pattern_serde_bincode_test() {
2✔
213
            let pattern: Pattern = "Y-m-d HH:mm".parse().expect("Failed to parse pattern");
1✔
214
            let bytes = bincode::serialize(&pattern).expect("Failed to serialize pattern");
1✔
215
            let result: Pattern =
216
                bincode::deserialize(&bytes).expect("Failed to deserialize pattern");
1✔
217
            assert_eq!(pattern, result);
1✔
218
        }
2✔
219
    }
220

221
    mod plural {
222
        // Can't use `serde(untagged)` on `PatternPlurals` because
223
        // Postcard can't handle enums not discriminated at compilation time.
224
        use super::*;
225
        use crate::pattern::runtime::{PatternPlurals, PluralPattern};
226
        use core::fmt;
227

228
        /// A helper struct that is shaped exactly like `runtime::PatternPlurals`
229
        /// and is used to aid in quick deserialization.
230
        #[derive(Debug, Clone, PartialEq, Deserialize)]
4✔
231
        #[cfg_attr(feature = "datagen", derive(Serialize))]
2✔
232
        #[allow(clippy::large_enum_variant)]
233
        enum PatternPluralsForSerde<'data> {
234
            #[serde(borrow)]
235
            MultipleVariants(PluralPattern<'data>),
3✔
236
            #[serde(borrow)]
237
            SinglePattern(Pattern<'data>),
×
238
        }
239

240
        impl<'data> From<PatternPluralsForSerde<'data>> for PatternPlurals<'data> {
241
            fn from(pfs: PatternPluralsForSerde<'data>) -> Self {
1✔
242
                match pfs {
1✔
243
                    PatternPluralsForSerde::MultipleVariants(variants) => {
1✔
244
                        Self::MultipleVariants(variants)
1✔
245
                    }
246
                    PatternPluralsForSerde::SinglePattern(pattern) => Self::SinglePattern(pattern),
×
247
                }
248
            }
1✔
249
        }
250

251
        impl<'data> From<&PatternPlurals<'data>> for PatternPluralsForSerde<'data> {
252
            fn from(pfs: &PatternPlurals<'data>) -> Self {
2✔
253
                match pfs.clone() {
2✔
254
                    PatternPlurals::MultipleVariants(variants) => Self::MultipleVariants(variants),
2✔
255
                    PatternPlurals::SinglePattern(pattern) => Self::SinglePattern(pattern),
×
256
                }
257
            }
2✔
258
        }
259

260
        struct DeserializePatternPlurals;
261

262
        impl<'de> de::Visitor<'de> for DeserializePatternPlurals {
263
            type Value = PatternPlurals<'de>;
264

265
            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
×
266
                write!(formatter, "a valid pattern.")
×
267
            }
×
268

269
            fn visit_str<E>(self, pattern_string: &str) -> Result<Self::Value, E>
×
270
            where
271
                E: de::Error,
272
            {
273
                let reference_deserializer = super::super::reference::DeserializePatternUTS35String;
274
                let pattern = reference_deserializer.visit_str(pattern_string)?;
×
275

276
                Ok(PatternPlurals::SinglePattern(Pattern::from(&pattern)))
×
277
            }
×
278

279
            fn visit_map<V>(self, map: V) -> Result<Self::Value, V::Error>
1✔
280
            where
281
                V: de::MapAccess<'de>,
282
            {
283
                Ok(PatternPlurals::MultipleVariants(
1✔
284
                    PluralPattern::deserialize(de::value::MapAccessDeserializer::new(map))?,
1✔
285
                ))
286
            }
1✔
287
        }
288

289
        impl<'de: 'data, 'data> Deserialize<'de> for PatternPlurals<'data> {
290
            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
2✔
291
            where
292
                D: Deserializer<'de>,
293
            {
294
                if deserializer.is_human_readable() {
3✔
295
                    // deserializer.deserialize_enum("PatternPlurals", &["Single", "Multiple"], DeserializePatternPlurals)
296
                    deserializer.deserialize_any(DeserializePatternPlurals)
1✔
297
                } else {
298
                    let pattern = PatternPluralsForSerde::deserialize(deserializer)?;
1✔
299
                    Ok(Self::from(pattern))
1✔
300
                }
1✔
301
            }
2✔
302
        }
303

304
        #[cfg(feature = "datagen")]
305
        impl Serialize for PatternPlurals<'_> {
306
            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
3✔
307
            where
308
                S: ser::Serializer,
309
            {
310
                if serializer.is_human_readable() {
3✔
311
                    // match self {
312
                    //     Self::SinglePattern(pattern) => serializer.serialize_newtype_variant("PatternPlurals", 0, "Single", pattern),
313
                    //     Self::MultipleVariants(variants) => serializer.serialize_newtype_variant("PatternPlurals", 1, "Multiple", variants),
314
                    // }
315
                    match self {
1✔
316
                        Self::SinglePattern(pattern) => {
×
317
                            serializer.serialize_str(&pattern.to_string())
×
318
                        }
×
319
                        Self::MultipleVariants(variants) => variants.serialize(serializer),
1✔
320
                    }
321
                } else {
322
                    let pfs: PatternPluralsForSerde = self.into();
2✔
323
                    pfs.serialize(serializer)
2✔
324
                }
2✔
325
            }
3✔
326
        }
327

328
        #[cfg(all(test, feature = "datagen"))]
329
        mod test {
330
            use super::*;
331
            use icu_plurals::PluralCategory;
332

333
            #[test]
334
            fn runtime_pattern_plurals_serde_human_readable_test() {
2✔
335
                let pattern_other: Pattern = "Y-m-d w 'other' HH:mm"
1✔
336
                    .parse()
337
                    .expect("Failed to parse pattern");
1✔
338
                let pattern_two: Pattern = "Y-m-d w 'two' HH:mm"
1✔
339
                    .parse()
340
                    .expect("Failed to parse pattern");
1✔
341

342
                let mut plural_pattern =
343
                    PluralPattern::new(pattern_other).expect("Failed to create PluralPattern");
1✔
344

345
                plural_pattern.maybe_set_variant(PluralCategory::Two, pattern_two);
1✔
346

347
                let pattern_plurals = PatternPlurals::from(plural_pattern);
1✔
348

349
                let json = serde_json::to_string(&pattern_plurals)
1✔
350
                    .expect("Failed to serialize pattern plurals");
351
                let result: PatternPlurals =
352
                    serde_json::from_str(&json).expect("Failed to deserialize pattern plurals");
1✔
353
                assert_eq!(pattern_plurals, result);
1✔
354
            }
2✔
355

356
            #[test]
357
            fn runtime_pattern_plurals_serde_bincode_test() {
2✔
358
                let pattern_other: Pattern = "Y-m-d w 'other' HH:mm"
1✔
359
                    .parse()
360
                    .expect("Failed to parse pattern");
1✔
361
                let pattern_two: Pattern = "Y-m-d w 'two' HH:mm"
1✔
362
                    .parse()
363
                    .expect("Failed to parse pattern");
1✔
364

365
                let mut plural_pattern =
366
                    PluralPattern::new(pattern_other).expect("Failed to create PluralPattern");
1✔
367

368
                plural_pattern.maybe_set_variant(PluralCategory::Two, pattern_two);
1✔
369

370
                let pattern_plurals = PatternPlurals::from(plural_pattern);
1✔
371

372
                let bytes = bincode::serialize(&pattern_plurals)
1✔
373
                    .expect("Failed to serialize pattern plurals");
374
                let result: PatternPlurals =
375
                    bincode::deserialize(&bytes).expect("Failed to deserialize pattern plurals");
1✔
376
                assert_eq!(pattern_plurals, result);
1✔
377
            }
2✔
378
        }
379
    }
380

381
    mod generic {
382
        use super::*;
383
        use crate::pattern::runtime::GenericPattern;
384

385
        #[allow(clippy::upper_case_acronyms)]
386
        struct DeserializeGenericPatternUTS35String;
387

388
        impl<'de> de::Visitor<'de> for DeserializeGenericPatternUTS35String {
389
            type Value = GenericPattern<'de>;
390

391
            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
×
392
                write!(formatter, "a valid pattern.")
×
393
            }
×
394

395
            fn visit_str<E>(self, pattern_string: &str) -> Result<Self::Value, E>
1✔
396
            where
397
                E: de::Error,
398
            {
399
                // Parse a string into a list of fields.
400
                let pattern = pattern_string
1✔
401
                    .parse()
402
                    .map_err(|_| E::custom("Failed to parse pattern"))?;
×
403
                Ok(GenericPattern::from(&pattern))
1✔
404
            }
1✔
405
        }
406

407
        impl<'de: 'data, 'data> Deserialize<'de> for GenericPattern<'data> {
408
            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
14✔
409
            where
410
                D: Deserializer<'de>,
411
            {
412
                if deserializer.is_human_readable() {
27✔
413
                    deserializer.deserialize_str(DeserializeGenericPatternUTS35String)
1✔
414
                } else {
415
                    let items = ZeroVec::deserialize(deserializer)?;
13✔
416
                    Ok(Self { items })
13✔
417
                }
418
            }
14✔
419
        }
420

421
        #[cfg(feature = "datagen")]
422
        impl Serialize for GenericPattern<'_> {
423
            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
3✔
424
            where
425
                S: ser::Serializer,
426
            {
427
                if serializer.is_human_readable() {
3✔
428
                    // Serialize into the UTS 35 string representation.
429
                    let string = self.to_string();
1✔
430
                    serializer.serialize_str(&string)
1✔
431
                } else {
1✔
432
                    self.items.serialize(serializer)
2✔
433
                }
434
            }
3✔
435
        }
436

437
        #[cfg(all(test, feature = "datagen"))]
438
        mod test {
439
            use super::*;
440

441
            #[test]
442
            fn runtime_generic_pattern_serde_human_readable_test() {
2✔
443
                let pattern: GenericPattern =
444
                    "{0} 'and' {1}".parse().expect("Failed to parse pattern");
1✔
445
                let json = serde_json::to_string(&pattern).expect("Failed to serialize pattern");
1✔
446
                let result: GenericPattern =
447
                    serde_json::from_str(&json).expect("Failed to deserialize pattern");
1✔
448
                assert_eq!(pattern, result);
1✔
449
            }
2✔
450

451
            #[test]
452
            fn runtime_generic_pattern_serde_bincode_test() {
2✔
453
                let pattern: GenericPattern =
454
                    "{0} 'and' {1}".parse().expect("Failed to parse pattern");
1✔
455
                let bytes = bincode::serialize(&pattern).expect("Failed to serialize pattern");
1✔
456
                let result: GenericPattern =
457
                    bincode::deserialize(&bytes).expect("Failed to deserialize pattern");
1✔
458
                assert_eq!(pattern, result);
1✔
459
            }
2✔
460
        }
461
    }
462
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc