• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 super::ZeroHashMap;
6 use crate::{
7     map::{ZeroMapKV, ZeroVecLike},
8     ZeroVec,
9 };
10 
11 use serde::{de, Deserialize, Serialize};
12 
13 impl<'a, K, V> Serialize for ZeroHashMap<'a, K, V>
14 where
15     K: ZeroMapKV<'a> + Serialize + ?Sized,
16     V: ZeroMapKV<'a> + Serialize + ?Sized,
17     K::Container: Serialize,
18     V::Container: Serialize,
19 {
serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: serde::Serializer,20     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
21     where
22         S: serde::Serializer,
23     {
24         (&self.displacements, &self.keys, &self.values).serialize(serializer)
25     }
26 }
27 
28 impl<'de, 'a, K, V> Deserialize<'de> for ZeroHashMap<'a, K, V>
29 where
30     K: ZeroMapKV<'a> + ?Sized,
31     V: ZeroMapKV<'a> + ?Sized,
32     K::Container: Deserialize<'de>,
33     V::Container: Deserialize<'de>,
34     'de: 'a,
35 {
deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: serde::Deserializer<'de>,36     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
37     where
38         D: serde::Deserializer<'de>,
39     {
40         let (displacements, keys, values): (ZeroVec<(u32, u32)>, K::Container, V::Container) =
41             Deserialize::deserialize(deserializer)?;
42         if keys.zvl_len() != values.zvl_len() {
43             return Err(de::Error::custom(
44                 "Mismatched key and value sizes in ZeroHashMap",
45             ));
46         }
47         if displacements.zvl_len() != keys.zvl_len() {
48             return Err(de::Error::custom(
49                 "Mismatched displacements and key, value sizes in ZeroHashMap",
50             ));
51         }
52         Ok(Self {
53             displacements,
54             keys,
55             values,
56         })
57     }
58 }
59 
60 #[cfg(test)]
61 mod test {
62     use crate::{VarZeroVec, ZeroHashMap, ZeroVec};
63     use serde::{Deserialize, Serialize};
64 
65     const JSON_STR: &str = "[[[0,0],[0,1],[0,1]],[1,2,0],[\"b\",\"c\",\"a\"]]";
66 
67     const BINCODE_BYTES: &[u8] = &[
68         24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0,
69         0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0,
70         3, 0, 1, 0, 2, 0, 98, 99, 97,
71     ];
72 
73     #[derive(Serialize, Deserialize)]
74     struct DeriveTestZeroHashMap<'data> {
75         #[serde(borrow)]
76         _data: ZeroHashMap<'data, str, [u8]>,
77     }
78 
make_zerohashmap() -> ZeroHashMap<'static, u32, str>79     fn make_zerohashmap() -> ZeroHashMap<'static, u32, str> {
80         ZeroHashMap::from_iter([(0, "a"), (1, "b"), (2, "c")])
81     }
82 
build_invalid_hashmap_str( displacements: Vec<(u32, u32)>, keys: Vec<u32>, values: Vec<&str>, ) -> String83     fn build_invalid_hashmap_str(
84         displacements: Vec<(u32, u32)>,
85         keys: Vec<u32>,
86         values: Vec<&str>,
87     ) -> String {
88         let invalid_hm: ZeroHashMap<u32, str> = ZeroHashMap {
89             displacements: ZeroVec::alloc_from_slice(&displacements),
90             keys: ZeroVec::alloc_from_slice(&keys),
91             values: VarZeroVec::<str>::from(&values),
92         };
93         serde_json::to_string(&invalid_hm).expect("serialize")
94     }
95 
96     #[test]
test_invalid_deser_zhm()97     fn test_invalid_deser_zhm() {
98         // Invalid hashmap |keys| != |values|
99         let mut invalid_hm_str =
100             build_invalid_hashmap_str(vec![(0, 1), (0, 0)], vec![1, 2], vec!["a", "b", "c"]);
101 
102         assert_eq!(
103             serde_json::from_str::<ZeroHashMap<u32, str>>(&invalid_hm_str)
104                 .unwrap_err()
105                 .to_string(),
106             "Mismatched key and value sizes in ZeroHashMap"
107         );
108 
109         // Invalid hashmap |displacements| != |keys| == |values|
110         // |displacements| = 2, |keys| = 3, |values| = 3
111         invalid_hm_str =
112             build_invalid_hashmap_str(vec![(0, 1), (0, 0)], vec![2, 1, 0], vec!["a", "b", "c"]);
113 
114         assert_eq!(
115             serde_json::from_str::<ZeroHashMap<u32, str>>(&invalid_hm_str)
116                 .unwrap_err()
117                 .to_string(),
118             "Mismatched displacements and key, value sizes in ZeroHashMap"
119         );
120     }
121 
122     #[test]
test_serde_valid_deser_zhm()123     fn test_serde_valid_deser_zhm() {
124         let hm = make_zerohashmap();
125         let json_str = serde_json::to_string(&hm).expect("serialize");
126         assert_eq!(json_str, JSON_STR);
127         let deserialized_hm: ZeroHashMap<u32, str> =
128             serde_json::from_str(JSON_STR).expect("deserialize");
129         assert_eq!(
130             hm.iter().collect::<Vec<_>>(),
131             deserialized_hm.iter().collect::<Vec<_>>()
132         );
133     }
134 
135     #[test]
test_bincode_zhm()136     fn test_bincode_zhm() {
137         let hm = make_zerohashmap();
138         let bincode_bytes = bincode::serialize(&hm).expect("serialize");
139         assert_eq!(bincode_bytes, BINCODE_BYTES);
140         let deserialized_hm: ZeroHashMap<u32, str> =
141             bincode::deserialize(BINCODE_BYTES).expect("deserialize");
142         assert_eq!(
143             hm.iter().collect::<Vec<_>>(),
144             deserialized_hm.iter().collect::<Vec<_>>()
145         );
146     }
147 }
148