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