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::{ZeroMap2d, ZeroMap2dBorrowed, ZeroMap2dCursor}; 6 use crate::map::{MutableZeroVecLike, ZeroMapKV, ZeroVecLike}; 7 use crate::ZeroVec; 8 use alloc::vec::Vec; 9 use core::fmt; 10 use core::marker::PhantomData; 11 use serde::de::{self, Deserialize, Deserializer, MapAccess, Visitor}; 12 #[cfg(feature = "serde")] 13 use serde::ser::{Serialize, SerializeMap, Serializer}; 14 15 /// This impl requires enabling the optional `serde` Cargo feature of the `zerovec` crate 16 #[cfg(feature = "serde")] 17 impl<'a, K0, K1, V> Serialize for ZeroMap2d<'a, K0, K1, V> 18 where 19 K0: ZeroMapKV<'a> + Serialize + ?Sized + Ord, 20 K1: ZeroMapKV<'a> + Serialize + ?Sized + Ord, 21 V: ZeroMapKV<'a> + Serialize + ?Sized, 22 K0::Container: Serialize, 23 K1::Container: Serialize, 24 V::Container: Serialize, 25 { serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer,26 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> 27 where 28 S: Serializer, 29 { 30 if serializer.is_human_readable() { 31 let mut serde_map = serializer.serialize_map(None)?; 32 for cursor in self.iter0() { 33 K0::Container::zvl_get_as_t(cursor.key0(), |k| serde_map.serialize_key(k))?; 34 let inner_map = ZeroMap2dInnerMapSerialize { cursor }; 35 serde_map.serialize_value(&inner_map)?; 36 } 37 serde_map.end() 38 } else { 39 (&self.keys0, &self.joiner, &self.keys1, &self.values).serialize(serializer) 40 } 41 } 42 } 43 44 /// Helper struct for human-serializing the inner map of a ZeroMap2d 45 #[cfg(feature = "serde")] 46 struct ZeroMap2dInnerMapSerialize<'a, 'l, K0, K1, V> 47 where 48 K0: ZeroMapKV<'a> + ?Sized + Ord, 49 K1: ZeroMapKV<'a> + ?Sized + Ord, 50 V: ZeroMapKV<'a> + ?Sized, 51 { 52 pub cursor: ZeroMap2dCursor<'l, 'a, K0, K1, V>, 53 } 54 55 #[cfg(feature = "serde")] 56 impl<'a, 'l, K0, K1, V> Serialize for ZeroMap2dInnerMapSerialize<'a, 'l, K0, K1, V> 57 where 58 K0: ZeroMapKV<'a> + Serialize + ?Sized + Ord, 59 K1: ZeroMapKV<'a> + Serialize + ?Sized + Ord, 60 V: ZeroMapKV<'a> + Serialize + ?Sized, 61 K0::Container: Serialize, 62 K1::Container: Serialize, 63 V::Container: Serialize, 64 { serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer,65 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> 66 where 67 S: Serializer, 68 { 69 let mut serde_map = serializer.serialize_map(None)?; 70 for (key1, v) in self.cursor.iter1() { 71 K1::Container::zvl_get_as_t(key1, |k| serde_map.serialize_key(k))?; 72 V::Container::zvl_get_as_t(v, |v| serde_map.serialize_value(v))?; 73 } 74 serde_map.end() 75 } 76 } 77 78 /// This impl requires enabling the optional `serde` Cargo feature of the `zerovec` crate 79 #[cfg(feature = "serde")] 80 impl<'a, K0, K1, V> Serialize for ZeroMap2dBorrowed<'a, K0, K1, V> 81 where 82 K0: ZeroMapKV<'a> + Serialize + ?Sized + Ord, 83 K1: ZeroMapKV<'a> + Serialize + ?Sized + Ord, 84 V: ZeroMapKV<'a> + Serialize + ?Sized, 85 K0::Container: Serialize, 86 K1::Container: Serialize, 87 V::Container: Serialize, 88 { serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer,89 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> 90 where 91 S: Serializer, 92 { 93 ZeroMap2d::<K0, K1, V>::from(*self).serialize(serializer) 94 } 95 } 96 97 /// Modified example from https://serde.rs/deserialize-map.html 98 struct ZeroMap2dMapVisitor<'a, K0, K1, V> 99 where 100 K0: ZeroMapKV<'a> + ?Sized + Ord, 101 K1: ZeroMapKV<'a> + ?Sized + Ord, 102 V: ZeroMapKV<'a> + ?Sized, 103 { 104 #[allow(clippy::type_complexity)] // it's a marker type, complexity doesn't matter 105 marker: PhantomData<fn() -> (&'a K0::OwnedType, &'a K1::OwnedType, &'a V::OwnedType)>, 106 } 107 108 impl<'a, K0, K1, V> ZeroMap2dMapVisitor<'a, K0, K1, V> 109 where 110 K0: ZeroMapKV<'a> + ?Sized + Ord, 111 K1: ZeroMapKV<'a> + ?Sized + Ord, 112 V: ZeroMapKV<'a> + ?Sized, 113 { new() -> Self114 fn new() -> Self { 115 ZeroMap2dMapVisitor { 116 marker: PhantomData, 117 } 118 } 119 } 120 121 impl<'a, 'de, K0, K1, V> Visitor<'de> for ZeroMap2dMapVisitor<'a, K0, K1, V> 122 where 123 K0: ZeroMapKV<'a> + Ord + ?Sized + Ord, 124 K1: ZeroMapKV<'a> + Ord + ?Sized + Ord, 125 V: ZeroMapKV<'a> + ?Sized, 126 K1::Container: Deserialize<'de>, 127 V::Container: Deserialize<'de>, 128 K0::OwnedType: Deserialize<'de>, 129 K1::OwnedType: Deserialize<'de>, 130 V::OwnedType: Deserialize<'de>, 131 { 132 type Value = ZeroMap2d<'a, K0, K1, V>; 133 expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result134 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 135 formatter.write_str("a map produced by ZeroMap2d") 136 } 137 visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error> where M: MapAccess<'de>,138 fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error> 139 where 140 M: MapAccess<'de>, 141 { 142 let mut map = ZeroMap2d::with_capacity(access.size_hint().unwrap_or(0)); 143 144 // On the first level, pull out the K0s and a TupleVecMap of the 145 // K1s and Vs, and then collect them into a ZeroMap2d 146 while let Some((key0, inner_map)) = 147 access.next_entry::<K0::OwnedType, TupleVecMap<K1::OwnedType, V::OwnedType>>()? 148 { 149 for (key1, value) in inner_map.entries.iter() { 150 if map 151 .try_append( 152 K0::Container::owned_as_t(&key0), 153 K1::Container::owned_as_t(key1), 154 V::Container::owned_as_t(value), 155 ) 156 .is_some() 157 { 158 return Err(de::Error::custom( 159 "ZeroMap2d's keys must be sorted while deserializing", 160 )); 161 } 162 } 163 } 164 165 Ok(map) 166 } 167 } 168 169 /// Helper struct for human-deserializing the inner map of a ZeroMap2d 170 struct TupleVecMap<K1, V> { 171 pub entries: Vec<(K1, V)>, 172 } 173 174 struct TupleVecMapVisitor<K1, V> { 175 #[allow(clippy::type_complexity)] // it's a marker type, complexity doesn't matter 176 marker: PhantomData<fn() -> (K1, V)>, 177 } 178 179 impl<K1, V> TupleVecMapVisitor<K1, V> { new() -> Self180 fn new() -> Self { 181 TupleVecMapVisitor { 182 marker: PhantomData, 183 } 184 } 185 } 186 187 impl<'de, K1, V> Visitor<'de> for TupleVecMapVisitor<K1, V> 188 where 189 K1: Deserialize<'de>, 190 V: Deserialize<'de>, 191 { 192 type Value = TupleVecMap<K1, V>; 193 expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result194 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 195 formatter.write_str("an inner map produced by ZeroMap2d") 196 } 197 visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error> where M: MapAccess<'de>,198 fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error> 199 where 200 M: MapAccess<'de>, 201 { 202 let mut result = Vec::with_capacity(access.size_hint().unwrap_or(0)); 203 while let Some((key1, value)) = access.next_entry::<K1, V>()? { 204 result.push((key1, value)); 205 } 206 Ok(TupleVecMap { entries: result }) 207 } 208 } 209 210 impl<'de, K1, V> Deserialize<'de> for TupleVecMap<K1, V> 211 where 212 K1: Deserialize<'de>, 213 V: Deserialize<'de>, 214 { deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de>,215 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> 216 where 217 D: Deserializer<'de>, 218 { 219 deserializer.deserialize_map(TupleVecMapVisitor::<K1, V>::new()) 220 } 221 } 222 223 /// This impl requires enabling the optional `serde` Cargo feature of the `zerovec` crate 224 impl<'de, 'a, K0, K1, V> Deserialize<'de> for ZeroMap2d<'a, K0, K1, V> 225 where 226 K0: ZeroMapKV<'a> + Ord + ?Sized, 227 K1: ZeroMapKV<'a> + Ord + ?Sized, 228 V: ZeroMapKV<'a> + ?Sized, 229 K0::Container: Deserialize<'de>, 230 K1::Container: Deserialize<'de>, 231 V::Container: Deserialize<'de>, 232 K0::OwnedType: Deserialize<'de>, 233 K1::OwnedType: Deserialize<'de>, 234 V::OwnedType: Deserialize<'de>, 235 'de: 'a, 236 { deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de>,237 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> 238 where 239 D: Deserializer<'de>, 240 { 241 if deserializer.is_human_readable() { 242 deserializer.deserialize_map(ZeroMap2dMapVisitor::<'a, K0, K1, V>::new()) 243 } else { 244 let (keys0, joiner, keys1, values): ( 245 K0::Container, 246 ZeroVec<u32>, 247 K1::Container, 248 V::Container, 249 ) = Deserialize::deserialize(deserializer)?; 250 // Invariant 1: len(keys0) == len(joiner) 251 if keys0.zvl_len() != joiner.len() { 252 return Err(de::Error::custom( 253 "Mismatched keys0 and joiner sizes in ZeroMap2d", 254 )); 255 } 256 // Invariant 2: len(keys1) == len(values) 257 if keys1.zvl_len() != values.zvl_len() { 258 return Err(de::Error::custom( 259 "Mismatched keys1 and value sizes in ZeroMap2d", 260 )); 261 } 262 // Invariant 3: joiner is sorted 263 if !joiner.zvl_is_ascending() { 264 return Err(de::Error::custom( 265 "ZeroMap2d deserializing joiner array out of order", 266 )); 267 } 268 // Invariant 4: the last element of joiner is the length of keys1 269 if let Some(last_joiner0) = joiner.last() { 270 if keys1.zvl_len() != last_joiner0 as usize { 271 return Err(de::Error::custom( 272 "ZeroMap2d deserializing joiner array malformed", 273 )); 274 } 275 } 276 let result = Self { 277 keys0, 278 joiner, 279 keys1, 280 values, 281 }; 282 // In debug mode, check the optional invariants, too 283 #[cfg(debug_assertions)] 284 result.check_invariants(); 285 Ok(result) 286 } 287 } 288 } 289 290 /// This impl requires enabling the optional `serde` Cargo feature of the `zerovec` crate 291 impl<'de, 'a, K0, K1, V> Deserialize<'de> for ZeroMap2dBorrowed<'a, K0, K1, V> 292 where 293 K0: ZeroMapKV<'a> + Ord + ?Sized, 294 K1: ZeroMapKV<'a> + Ord + ?Sized, 295 V: ZeroMapKV<'a> + ?Sized, 296 K0::Container: Deserialize<'de>, 297 K1::Container: Deserialize<'de>, 298 V::Container: Deserialize<'de>, 299 K0::OwnedType: Deserialize<'de>, 300 K1::OwnedType: Deserialize<'de>, 301 V::OwnedType: Deserialize<'de>, 302 'de: 'a, 303 { deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de>,304 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> 305 where 306 D: Deserializer<'de>, 307 { 308 if deserializer.is_human_readable() { 309 Err(de::Error::custom( 310 "ZeroMap2dBorrowed cannot be deserialized from human-readable formats", 311 )) 312 } else { 313 let deserialized: ZeroMap2d<'a, K0, K1, V> = ZeroMap2d::deserialize(deserializer)?; 314 let keys0 = if let Some(keys0) = deserialized.keys0.zvl_as_borrowed_inner() { 315 keys0 316 } else { 317 return Err(de::Error::custom( 318 "ZeroMap2dBorrowed can only deserialize in zero-copy ways", 319 )); 320 }; 321 let joiner = if let Some(joiner) = deserialized.joiner.zvl_as_borrowed_inner() { 322 joiner 323 } else { 324 return Err(de::Error::custom( 325 "ZeroMap2dBorrowed can only deserialize in zero-copy ways", 326 )); 327 }; 328 let keys1 = if let Some(keys1) = deserialized.keys1.zvl_as_borrowed_inner() { 329 keys1 330 } else { 331 return Err(de::Error::custom( 332 "ZeroMap2dBorrowed can only deserialize in zero-copy ways", 333 )); 334 }; 335 let values = if let Some(values) = deserialized.values.zvl_as_borrowed_inner() { 336 values 337 } else { 338 return Err(de::Error::custom( 339 "ZeroMap2dBorrowed can only deserialize in zero-copy ways", 340 )); 341 }; 342 Ok(Self { 343 keys0, 344 joiner, 345 keys1, 346 values, 347 }) 348 } 349 } 350 } 351 352 #[cfg(test)] 353 #[allow(non_camel_case_types)] 354 mod test { 355 use crate::map2d::{ZeroMap2d, ZeroMap2dBorrowed}; 356 357 #[derive(serde::Serialize, serde::Deserialize)] 358 struct DeriveTest_ZeroMap2d<'data> { 359 #[serde(borrow)] 360 _data: ZeroMap2d<'data, u16, str, [u8]>, 361 } 362 363 #[derive(serde::Serialize, serde::Deserialize)] 364 struct DeriveTest_ZeroMap2dBorrowed<'data> { 365 #[serde(borrow)] 366 _data: ZeroMap2dBorrowed<'data, u16, str, [u8]>, 367 } 368 369 const JSON_STR: &str = "{\"1\":{\"1\":\"uno\"},\"2\":{\"2\":\"dos\",\"3\":\"tres\"}}"; 370 const BINCODE_BYTES: &[u8] = &[ 371 8, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 3, 0, 372 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 3, 0, 16, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3, 0, 6, 0, 373 117, 110, 111, 100, 111, 115, 116, 114, 101, 115, 374 ]; 375 make_map() -> ZeroMap2d<'static, u32, u16, str>376 fn make_map() -> ZeroMap2d<'static, u32, u16, str> { 377 let mut map = ZeroMap2d::new(); 378 map.insert(&1, &1, "uno"); 379 map.insert(&2, &2, "dos"); 380 map.insert(&2, &3, "tres"); 381 map 382 } 383 384 #[test] test_serde_json()385 fn test_serde_json() { 386 let map = make_map(); 387 let json_str = serde_json::to_string(&map).expect("serialize"); 388 assert_eq!(JSON_STR, json_str); 389 let new_map: ZeroMap2d<u32, u16, str> = 390 serde_json::from_str(&json_str).expect("deserialize"); 391 assert_eq!(format!("{new_map:?}"), format!("{map:?}")); 392 } 393 394 #[test] test_bincode()395 fn test_bincode() { 396 let map = make_map(); 397 let bincode_bytes = bincode::serialize(&map).expect("serialize"); 398 assert_eq!(BINCODE_BYTES, bincode_bytes); 399 let new_map: ZeroMap2d<u32, u16, str> = 400 bincode::deserialize(&bincode_bytes).expect("deserialize"); 401 assert_eq!( 402 format!("{new_map:?}"), 403 format!("{map:?}").replace("Owned", "Borrowed"), 404 ); 405 406 let new_map: ZeroMap2dBorrowed<u32, u16, str> = 407 bincode::deserialize(&bincode_bytes).expect("deserialize"); 408 assert_eq!( 409 format!("{new_map:?}"), 410 format!("{map:?}") 411 .replace("Owned", "Borrowed") 412 .replace("ZeroMap2d", "ZeroMap2dBorrowed") 413 ); 414 } 415 416 #[test] test_serde_rmp()417 fn test_serde_rmp() { 418 let map = make_map(); 419 let rmp_buf = rmp_serde::to_vec(&map).expect("serialize"); 420 let new_map: ZeroMap2d<u32, u16, str> = rmp_serde::from_slice(&rmp_buf).unwrap(); 421 assert_eq!(map, new_map); 422 } 423 424 #[test] test_sample_bincode()425 fn test_sample_bincode() { 426 // This is the map from the main docs page for ZeroMap2d 427 let mut map: ZeroMap2d<u16, u16, str> = ZeroMap2d::new(); 428 map.insert(&1, &2, "three"); 429 let bincode_bytes: Vec<u8> = bincode::serialize(&map).expect("serialize"); 430 assert_eq!( 431 bincode_bytes.as_slice(), 432 &[ 433 2, 0, 0, 0, 0, 0, 0, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 434 0, 0, 2, 0, 7, 0, 0, 0, 0, 0, 0, 0, 1, 0, 116, 104, 114, 101, 101 435 ] 436 ); 437 } 438 } 439