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 alloc::borrow::Cow;
6 use serde::de::Deserializer;
7 use serde::Deserialize;
8
9 #[derive(Deserialize)]
10 #[serde(transparent)]
11 // Cows fail to borrow in some situations (array, option), but structs of Cows don't.
12 #[allow(clippy::exhaustive_structs)] // newtype
13 #[derive(Debug)]
14 pub struct CowWrap<'data>(#[serde(borrow)] pub Cow<'data, str>);
15
16 #[derive(Deserialize)]
17 #[serde(transparent)]
18 // Cows fail to borrow in some situations (array, option), but structs of Cows don't.
19 #[allow(clippy::exhaustive_structs)] // newtype
20 #[derive(Debug)]
21 pub struct CowBytesWrap<'data>(#[serde(borrow)] pub Cow<'data, [u8]>);
22
array_of_cow<'de, D, const N: usize>(deserializer: D) -> Result<[Cow<'de, str>; N], D::Error> where D: Deserializer<'de>, [CowWrap<'de>; N]: Deserialize<'de>,23 pub fn array_of_cow<'de, D, const N: usize>(deserializer: D) -> Result<[Cow<'de, str>; N], D::Error>
24 where
25 D: Deserializer<'de>,
26 [CowWrap<'de>; N]: Deserialize<'de>,
27 {
28 <[CowWrap<'de>; N]>::deserialize(deserializer).map(|array| array.map(|wrap| wrap.0))
29 }
30
option_of_cow<'de, D>(deserializer: D) -> Result<Option<Cow<'de, str>>, D::Error> where D: Deserializer<'de>,31 pub fn option_of_cow<'de, D>(deserializer: D) -> Result<Option<Cow<'de, str>>, D::Error>
32 where
33 D: Deserializer<'de>,
34 {
35 <Option<CowWrap<'de>>>::deserialize(deserializer).map(|opt| opt.map(|wrap| wrap.0))
36 }
37
tuple_of_cow<'de, D>(deserializer: D) -> Result<(Cow<'de, str>, Cow<'de, str>), D::Error> where D: Deserializer<'de>, (CowWrap<'de>, CowWrap<'de>): Deserialize<'de>,38 pub fn tuple_of_cow<'de, D>(deserializer: D) -> Result<(Cow<'de, str>, Cow<'de, str>), D::Error>
39 where
40 D: Deserializer<'de>,
41 (CowWrap<'de>, CowWrap<'de>): Deserialize<'de>,
42 {
43 <(CowWrap<'de>, CowWrap<'de>)>::deserialize(deserializer).map(|x| (x.0 .0, x.1 .0))
44 }
45
46 #[test]
test_option()47 fn test_option() {
48 #[derive(Debug, PartialEq, serde::Serialize, serde::Deserialize)]
49 struct Demo<'s>(#[serde(borrow, deserialize_with = "option_of_cow")] Option<Cow<'s, str>>);
50
51 let data_orig = Demo(Some("Hello world".into()));
52 let json = serde_json::to_string(&data_orig).expect("serialize");
53 let data_new = serde_json::from_str::<Demo>(&json).expect("deserialize");
54 assert_eq!(data_orig, data_new);
55 assert!(matches!(data_new.0, Some(Cow::Borrowed(_))));
56 }
57
58 #[test]
test_tuple()59 fn test_tuple() {
60 #[derive(Debug, PartialEq, serde::Serialize, serde::Deserialize)]
61 struct Demo<'s>(
62 #[serde(borrow, deserialize_with = "tuple_of_cow")] (Cow<'s, str>, Cow<'s, str>),
63 );
64
65 let data_orig = Demo(("Hello world".into(), "Hello earth".into()));
66 let json = serde_json::to_string(&data_orig).expect("serialize");
67 let data_new = serde_json::from_str::<Demo>(&json).expect("deserialize");
68 assert_eq!(data_orig, data_new);
69 assert!(matches!(data_new.0, (Cow::Borrowed(_), Cow::Borrowed(_))));
70 }
71
72 #[test]
test_array()73 fn test_array() {
74 #[derive(Debug, PartialEq, serde::Serialize, serde::Deserialize)]
75 struct Demo<'s>(#[serde(borrow, deserialize_with = "array_of_cow")] [Cow<'s, str>; 1]);
76
77 let data_orig = Demo(["Hello world".into()]);
78 let json = serde_json::to_string(&data_orig).expect("serialize");
79 let data_new = serde_json::from_str::<Demo>(&json).expect("deserialize");
80 assert_eq!(data_orig, data_new);
81 assert!(matches!(data_new.0, [Cow::Borrowed(_)]));
82 }
83