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::builder::bytestr::ByteStr; 6 use crate::options::ZeroTrieWithOptions; 7 use crate::zerotrie::ZeroTrieFlavor; 8 use crate::ZeroAsciiIgnoreCaseTrie; 9 use crate::ZeroTrie; 10 use crate::ZeroTrieExtendedCapacity; 11 use crate::ZeroTriePerfectHash; 12 use crate::ZeroTrieSimpleAscii; 13 use alloc::boxed::Box; 14 use alloc::vec::Vec; 15 use core::fmt; 16 use litemap::LiteMap; 17 use serde::de::Error; 18 use serde::de::Visitor; 19 use serde::Deserialize; 20 use serde::Deserializer; 21 use serde::Serialize; 22 use serde::Serializer; 23 24 struct ByteStrVisitor; 25 impl<'de> Visitor<'de> for ByteStrVisitor { 26 type Value = Box<[u8]>; expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result27 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 28 write!(formatter, "a slice of borrowed bytes or a string") 29 } visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>30 fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E> { 31 Ok(Box::from(v)) 32 } visit_str<E>(self, v: &str) -> Result<Self::Value, E>33 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E> { 34 Ok(Box::from(v.as_bytes())) 35 } visit_seq<A>(self, mut v: A) -> Result<Self::Value, A::Error> where A: serde::de::SeqAccess<'de>,36 fn visit_seq<A>(self, mut v: A) -> Result<Self::Value, A::Error> 37 where 38 A: serde::de::SeqAccess<'de>, 39 { 40 let mut result = Vec::with_capacity(v.size_hint().unwrap_or(0)); 41 while let Some(x) = v.next_element::<u8>()? { 42 result.push(x); 43 } 44 Ok(Box::from(result)) 45 } 46 } 47 48 impl<'data, 'de: 'data> Deserialize<'de> for &'data ByteStr { deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de>,49 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> 50 where 51 D: Deserializer<'de>, 52 { 53 let s = <&'data [u8]>::deserialize(deserializer)?; 54 Ok(ByteStr::from_bytes(s)) 55 } 56 } 57 58 impl<'de> Deserialize<'de> for Box<ByteStr> { deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de>,59 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> 60 where 61 D: Deserializer<'de>, 62 { 63 if deserializer.is_human_readable() { 64 let s = deserializer.deserialize_any(ByteStrVisitor)?; 65 Ok(ByteStr::from_boxed_bytes(s)) 66 } else { 67 let s = Vec::<u8>::deserialize(deserializer)?; 68 Ok(ByteStr::from_boxed_bytes(s.into_boxed_slice())) 69 } 70 } 71 } 72 73 impl Serialize for &ByteStr { serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer,74 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> 75 where 76 S: Serializer, 77 { 78 let bytes = self.as_bytes(); 79 if serializer.is_human_readable() { 80 match core::str::from_utf8(bytes) { 81 Ok(s) => serializer.serialize_str(s), 82 Err(_) => serializer.serialize_bytes(bytes), 83 } 84 } else { 85 serializer.serialize_bytes(bytes) 86 } 87 } 88 } 89 90 impl<'data, 'de: 'data, Store> Deserialize<'de> for ZeroTrieSimpleAscii<Store> 91 where 92 // DISCUSS: There are several possibilities for the bounds here that would 93 // get the job done. I could look for Deserialize, but this would require 94 // creating a custom Deserializer for the map case. I also considered 95 // introducing a new trait instead of relying on From. 96 Store: From<&'data [u8]> + From<Vec<u8>> + 'data, 97 { deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de>,98 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> 99 where 100 D: Deserializer<'de>, 101 { 102 if deserializer.is_human_readable() { 103 let lm = LiteMap::<Box<ByteStr>, usize>::deserialize(deserializer)?; 104 ZeroTrieSimpleAscii::try_from_serde_litemap(&lm) 105 .map_err(D::Error::custom) 106 .map(|trie| trie.convert_store()) 107 } else { 108 // Note: `impl Deserialize for &[u8]` uses visit_borrowed_bytes 109 let (flags, trie_bytes) = <(u8, &[u8])>::deserialize(deserializer)?; 110 if Self::OPTIONS.to_u8_flags() != flags { 111 return Err(D::Error::custom("invalid ZeroTrie tag")); 112 }; 113 Ok(ZeroTrieSimpleAscii::from_store(Store::from(trie_bytes))) 114 } 115 } 116 } 117 118 impl<Store> Serialize for ZeroTrieSimpleAscii<Store> 119 where 120 Store: AsRef<[u8]>, 121 { serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer,122 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> 123 where 124 S: Serializer, 125 { 126 if serializer.is_human_readable() { 127 let lm = self.to_litemap(); 128 lm.serialize(serializer) 129 } else { 130 // Note: `impl Serialize for ByteStr` uses `serialize_bytes` 131 (Self::FLAGS, ByteStr::from_bytes(self.as_bytes())).serialize(serializer) 132 } 133 } 134 } 135 136 impl<'de, 'data, Store> Deserialize<'de> for ZeroAsciiIgnoreCaseTrie<Store> 137 where 138 'de: 'data, 139 // DISCUSS: There are several possibilities for the bounds here that would 140 // get the job done. I could look for Deserialize, but this would require 141 // creating a custom Deserializer for the map case. I also considered 142 // introducing a new trait instead of relying on From. 143 Store: From<&'data [u8]> + From<Vec<u8>> + 'data, 144 { deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de>,145 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> 146 where 147 D: Deserializer<'de>, 148 { 149 if deserializer.is_human_readable() { 150 let lm = LiteMap::<Box<ByteStr>, usize>::deserialize(deserializer)?; 151 ZeroAsciiIgnoreCaseTrie::try_from_serde_litemap(&lm) 152 .map_err(D::Error::custom) 153 .map(|trie| trie.convert_store()) 154 } else { 155 // Note: `impl Deserialize for &[u8]` uses visit_borrowed_bytes 156 let (flags, trie_bytes) = <(u8, &[u8])>::deserialize(deserializer)?; 157 if Self::OPTIONS.to_u8_flags() != flags { 158 return Err(D::Error::custom("invalid ZeroTrie tag")); 159 } 160 Ok(ZeroAsciiIgnoreCaseTrie::from_store(Store::from(trie_bytes))) 161 } 162 } 163 } 164 165 impl<Store> Serialize for ZeroAsciiIgnoreCaseTrie<Store> 166 where 167 Store: AsRef<[u8]>, 168 { serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer,169 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> 170 where 171 S: Serializer, 172 { 173 if serializer.is_human_readable() { 174 let lm = self.to_litemap(); 175 lm.serialize(serializer) 176 } else { 177 // Note: `impl Serialize for ByteStr` uses `serialize_bytes` 178 ( 179 Self::OPTIONS.to_u8_flags(), 180 ByteStr::from_bytes(self.as_bytes()), 181 ) 182 .serialize(serializer) 183 } 184 } 185 } 186 187 impl<'de, 'data, Store> Deserialize<'de> for ZeroTriePerfectHash<Store> 188 where 189 'de: 'data, 190 Store: From<&'data [u8]> + From<Vec<u8>> + 'data, 191 { deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de>,192 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> 193 where 194 D: Deserializer<'de>, 195 { 196 if deserializer.is_human_readable() { 197 let lm = LiteMap::<Box<ByteStr>, usize>::deserialize(deserializer)?; 198 ZeroTriePerfectHash::try_from_serde_litemap(&lm) 199 .map_err(D::Error::custom) 200 .map(|trie| trie.convert_store()) 201 } else { 202 // Note: `impl Deserialize for &[u8]` uses visit_borrowed_bytes 203 let (flags, trie_bytes) = <(u8, &[u8])>::deserialize(deserializer)?; 204 if Self::OPTIONS.to_u8_flags() != flags { 205 return Err(D::Error::custom("invalid ZeroTrie tag")); 206 } 207 Ok(ZeroTriePerfectHash::from_store(Store::from(trie_bytes))) 208 } 209 } 210 } 211 212 impl<Store> Serialize for ZeroTriePerfectHash<Store> 213 where 214 Store: AsRef<[u8]>, 215 { serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer,216 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> 217 where 218 S: Serializer, 219 { 220 if serializer.is_human_readable() { 221 let lm = self.to_litemap(); 222 let lm = lm 223 .iter() 224 .map(|(k, v)| (ByteStr::from_bytes(k), v)) 225 .collect::<LiteMap<_, _>>(); 226 lm.serialize(serializer) 227 } else { 228 // Note: `impl Serialize for ByteStr` uses `serialize_bytes` 229 ( 230 Self::OPTIONS.to_u8_flags(), 231 ByteStr::from_bytes(self.as_bytes()), 232 ) 233 .serialize(serializer) 234 } 235 } 236 } 237 238 impl<'de, 'data, Store> Deserialize<'de> for ZeroTrieExtendedCapacity<Store> 239 where 240 'de: 'data, 241 Store: From<&'data [u8]> + From<Vec<u8>> + 'data, 242 { deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de>,243 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> 244 where 245 D: Deserializer<'de>, 246 { 247 if deserializer.is_human_readable() { 248 let lm = LiteMap::<Box<ByteStr>, usize>::deserialize(deserializer)?; 249 ZeroTrieExtendedCapacity::try_from_serde_litemap(&lm) 250 .map_err(D::Error::custom) 251 .map(|trie| trie.convert_store()) 252 } else { 253 // Note: `impl Deserialize for &[u8]` uses visit_borrowed_bytes 254 let (flags, trie_bytes) = <(u8, &[u8])>::deserialize(deserializer)?; 255 if Self::OPTIONS.to_u8_flags() != flags { 256 return Err(D::Error::custom("invalid ZeroTrie tag")); 257 } 258 Ok(ZeroTrieExtendedCapacity::from_store(Store::from( 259 trie_bytes, 260 ))) 261 } 262 } 263 } 264 265 impl<Store> Serialize for ZeroTrieExtendedCapacity<Store> 266 where 267 Store: AsRef<[u8]>, 268 { serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer,269 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> 270 where 271 S: Serializer, 272 { 273 if serializer.is_human_readable() { 274 let lm = self.to_litemap(); 275 let lm = lm 276 .iter() 277 .map(|(k, v)| (ByteStr::from_bytes(k), v)) 278 .collect::<LiteMap<_, _>>(); 279 lm.serialize(serializer) 280 } else { 281 // Note: `impl Serialize for ByteStr` uses `serialize_bytes` 282 ( 283 Self::OPTIONS.to_u8_flags(), 284 ByteStr::from_bytes(self.as_bytes()), 285 ) 286 .serialize(serializer) 287 } 288 } 289 } 290 291 impl<'de, 'data, Store> Deserialize<'de> for ZeroTrie<Store> 292 where 293 'de: 'data, 294 Store: From<&'data [u8]> + From<Vec<u8>> + 'data, 295 { deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'de>,296 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> 297 where 298 D: Deserializer<'de>, 299 { 300 if deserializer.is_human_readable() { 301 let lm = LiteMap::<Box<ByteStr>, usize>::deserialize(deserializer)?; 302 ZeroTrie::<Vec<u8>>::try_from(&lm) 303 .map_err(D::Error::custom) 304 .map(|trie| trie.convert_store()) 305 } else { 306 // Note: `impl Deserialize for &[u8]` uses visit_borrowed_bytes 307 let bytes = <&[u8]>::deserialize(deserializer)?; 308 let (tag, trie_bytes) = bytes 309 .split_first() 310 .ok_or(D::Error::custom("expected at least 1 byte for ZeroTrie"))?; 311 let store = Store::from(trie_bytes); 312 let zerotrie = if *tag == ZeroTrieSimpleAscii::<u8>::OPTIONS.to_u8_flags() { 313 ZeroTrieSimpleAscii::from_store(store).into_zerotrie() 314 } else if *tag == ZeroTriePerfectHash::<u8>::OPTIONS.to_u8_flags() { 315 ZeroTriePerfectHash::from_store(store).into_zerotrie() 316 } else if *tag == ZeroTrieExtendedCapacity::<u8>::OPTIONS.to_u8_flags() { 317 ZeroTrieExtendedCapacity::from_store(store).into_zerotrie() 318 } else { 319 return Err(D::Error::custom("invalid ZeroTrie tag")); 320 }; 321 Ok(zerotrie) 322 } 323 } 324 } 325 326 impl<Store> Serialize for ZeroTrie<Store> 327 where 328 Store: AsRef<[u8]>, 329 { serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer,330 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> 331 where 332 S: Serializer, 333 { 334 if serializer.is_human_readable() { 335 let lm = self.to_litemap(); 336 let lm = lm 337 .iter() 338 .map(|(k, v)| (ByteStr::from_bytes(k), v)) 339 .collect::<LiteMap<_, _>>(); 340 lm.serialize(serializer) 341 } else { 342 let (tag, bytes) = match &self.0 { 343 ZeroTrieFlavor::SimpleAscii(t) => ( 344 ZeroTrieSimpleAscii::<u8>::OPTIONS.to_u8_flags(), 345 t.as_bytes(), 346 ), 347 ZeroTrieFlavor::PerfectHash(t) => ( 348 ZeroTriePerfectHash::<u8>::OPTIONS.to_u8_flags(), 349 t.as_bytes(), 350 ), 351 ZeroTrieFlavor::ExtendedCapacity(t) => ( 352 ZeroTrieExtendedCapacity::<u8>::OPTIONS.to_u8_flags(), 353 t.as_bytes(), 354 ), 355 }; 356 let mut all_in_one_vec = Vec::with_capacity(bytes.len() + 1); 357 all_in_one_vec.push(tag); 358 all_in_one_vec.extend(bytes); 359 serializer.serialize_bytes(&all_in_one_vec) 360 } 361 } 362 } 363 364 #[cfg(test)] 365 mod testdata { 366 include!("../tests/data/data.rs"); 367 } 368 369 #[cfg(test)] 370 mod tests { 371 use super::*; 372 use alloc::borrow::Cow; 373 374 #[derive(Serialize, Deserialize)] 375 pub struct ZeroTrieSimpleAsciiCow<'a> { 376 #[serde(borrow)] 377 trie: ZeroTrieSimpleAscii<Cow<'a, [u8]>>, 378 } 379 380 #[test] test_serde_simpleascii_cow()381 pub fn test_serde_simpleascii_cow() { 382 let trie = ZeroTrieSimpleAscii::from_store(Cow::from(testdata::basic::TRIE_ASCII)); 383 let original = ZeroTrieSimpleAsciiCow { trie }; 384 let json_str = serde_json::to_string(&original).unwrap(); 385 let bincode_bytes = bincode::serialize(&original).unwrap(); 386 let rmp_bytes = rmp_serde::to_vec(&original).unwrap(); 387 388 assert_eq!(json_str, testdata::basic::JSON_STR_ASCII); 389 assert_eq!(&bincode_bytes[0..9], &[0, 26, 0, 0, 0, 0, 0, 0, 0]); 390 assert_eq!(&bincode_bytes[9..], testdata::basic::BINCODE_BYTES_ASCII); 391 assert_eq!(&rmp_bytes[0..5], &[145, 146, 0, 196, 26]); 392 assert_eq!(&rmp_bytes[5..], testdata::basic::BINCODE_BYTES_ASCII); 393 394 let json_recovered: ZeroTrieSimpleAsciiCow = serde_json::from_str(&json_str).unwrap(); 395 let bincode_recovered: ZeroTrieSimpleAsciiCow = 396 bincode::deserialize(&bincode_bytes).unwrap(); 397 let rmp_recovered: ZeroTrieSimpleAsciiCow = rmp_serde::from_slice(&rmp_bytes).unwrap(); 398 399 assert_eq!(original.trie, json_recovered.trie); 400 assert_eq!(original.trie, bincode_recovered.trie); 401 assert_eq!(original.trie, rmp_recovered.trie); 402 403 assert!(matches!(json_recovered.trie.into_store(), Cow::Owned(_))); 404 assert!(matches!( 405 bincode_recovered.trie.into_store(), 406 Cow::Borrowed(_) 407 )); 408 } 409 410 #[derive(Serialize, Deserialize)] 411 pub struct ZeroAsciiIgnoreCaseTrieCow<'a> { 412 #[serde(borrow)] 413 trie: ZeroAsciiIgnoreCaseTrie<Cow<'a, [u8]>>, 414 } 415 416 #[test] test_serde_asciiignorecase_cow()417 pub fn test_serde_asciiignorecase_cow() { 418 let trie = ZeroAsciiIgnoreCaseTrie::from_store(Cow::from(testdata::basic::TRIE_ASCII)); 419 let original = ZeroAsciiIgnoreCaseTrieCow { trie }; 420 let json_str = serde_json::to_string(&original).unwrap(); 421 let bincode_bytes = bincode::serialize(&original).unwrap(); 422 423 assert_eq!(json_str, testdata::basic::JSON_STR_ASCII); 424 assert_eq!(&bincode_bytes[0..9], &[8, 26, 0, 0, 0, 0, 0, 0, 0]); 425 assert_eq!(&bincode_bytes[9..], testdata::basic::BINCODE_BYTES_ASCII); 426 427 let json_recovered: ZeroAsciiIgnoreCaseTrieCow = serde_json::from_str(&json_str).unwrap(); 428 let bincode_recovered: ZeroAsciiIgnoreCaseTrieCow = 429 bincode::deserialize(&bincode_bytes).unwrap(); 430 431 assert_eq!(original.trie, json_recovered.trie); 432 assert_eq!(original.trie, bincode_recovered.trie); 433 434 assert!(matches!(json_recovered.trie.into_store(), Cow::Owned(_))); 435 assert!(matches!( 436 bincode_recovered.trie.into_store(), 437 Cow::Borrowed(_) 438 )); 439 } 440 441 #[derive(Serialize, Deserialize)] 442 pub struct ZeroTriePerfectHashCow<'a> { 443 #[serde(borrow)] 444 trie: ZeroTriePerfectHash<Cow<'a, [u8]>>, 445 } 446 447 #[test] test_serde_perfecthash_cow()448 pub fn test_serde_perfecthash_cow() { 449 let trie = ZeroTriePerfectHash::from_store(Cow::from(testdata::basic::TRIE_ASCII)); 450 let original = ZeroTriePerfectHashCow { trie }; 451 let json_str = serde_json::to_string(&original).unwrap(); 452 let bincode_bytes = bincode::serialize(&original).unwrap(); 453 454 assert_eq!(json_str, testdata::basic::JSON_STR_ASCII); 455 assert_eq!(&bincode_bytes[0..9], &[3, 26, 0, 0, 0, 0, 0, 0, 0]); 456 assert_eq!(&bincode_bytes[9..], testdata::basic::BINCODE_BYTES_ASCII); 457 458 let json_recovered: ZeroTriePerfectHashCow = serde_json::from_str(&json_str).unwrap(); 459 let bincode_recovered: ZeroTriePerfectHashCow = 460 bincode::deserialize(&bincode_bytes).unwrap(); 461 462 assert_eq!(original.trie, json_recovered.trie); 463 assert_eq!(original.trie, bincode_recovered.trie); 464 465 assert!(matches!(json_recovered.trie.into_store(), Cow::Owned(_))); 466 assert!(matches!( 467 bincode_recovered.trie.into_store(), 468 Cow::Borrowed(_) 469 )); 470 } 471 472 #[test] test_serde_perfecthash_cow_u()473 pub fn test_serde_perfecthash_cow_u() { 474 let trie = ZeroTriePerfectHash::from_store(Cow::from(testdata::basic::TRIE_UNICODE)); 475 let original = ZeroTriePerfectHashCow { trie }; 476 let json_str = serde_json::to_string(&original).unwrap(); 477 let bincode_bytes = bincode::serialize(&original).unwrap(); 478 479 assert_eq!(json_str, testdata::basic::JSON_STR_UNICODE); 480 assert_eq!(&bincode_bytes[0..9], &[3, 39, 0, 0, 0, 0, 0, 0, 0]); 481 assert_eq!(&bincode_bytes[9..], testdata::basic::BINCODE_BYTES_UNICODE); 482 483 let json_recovered: ZeroTriePerfectHashCow = serde_json::from_str(&json_str).unwrap(); 484 let bincode_recovered: ZeroTriePerfectHashCow = 485 bincode::deserialize(&bincode_bytes).unwrap(); 486 487 assert_eq!(original.trie, json_recovered.trie); 488 assert_eq!(original.trie, bincode_recovered.trie); 489 490 assert!(matches!(json_recovered.trie.into_store(), Cow::Owned(_))); 491 assert!(matches!( 492 bincode_recovered.trie.into_store(), 493 Cow::Borrowed(_) 494 )); 495 } 496 497 #[test] test_serde_perfecthash_cow_bin()498 pub fn test_serde_perfecthash_cow_bin() { 499 let trie = ZeroTriePerfectHash::from_store(Cow::from(testdata::basic::TRIE_BINARY)); 500 let original = ZeroTriePerfectHashCow { trie }; 501 let json_str = serde_json::to_string(&original).unwrap(); 502 let bincode_bytes = bincode::serialize(&original).unwrap(); 503 504 assert_eq!(json_str, testdata::basic::JSON_STR_BINARY); 505 assert_eq!(&bincode_bytes[0..9], &[3, 26, 0, 0, 0, 0, 0, 0, 0]); 506 assert_eq!(&bincode_bytes[9..], testdata::basic::BINCODE_BYTES_BINARY); 507 508 let json_recovered: ZeroTriePerfectHashCow = serde_json::from_str(&json_str).unwrap(); 509 let bincode_recovered: ZeroTriePerfectHashCow = 510 bincode::deserialize(&bincode_bytes).unwrap(); 511 512 assert_eq!(original.trie, json_recovered.trie); 513 assert_eq!(original.trie, bincode_recovered.trie); 514 515 assert!(matches!(json_recovered.trie.into_store(), Cow::Owned(_))); 516 assert!(matches!( 517 bincode_recovered.trie.into_store(), 518 Cow::Borrowed(_) 519 )); 520 } 521 522 #[derive(Serialize, Deserialize)] 523 pub struct ZeroTrieAnyCow<'a> { 524 #[serde(borrow)] 525 trie: ZeroTrie<Cow<'a, [u8]>>, 526 } 527 528 #[test] test_serde_any_cow()529 pub fn test_serde_any_cow() { 530 let trie = 531 ZeroTrieSimpleAscii::from_store(Cow::from(testdata::basic::TRIE_ASCII)).into_zerotrie(); 532 let original = ZeroTrieAnyCow { trie }; 533 let json_str = serde_json::to_string(&original).unwrap(); 534 let bincode_bytes = bincode::serialize(&original).unwrap(); 535 536 assert_eq!(json_str, testdata::basic::JSON_STR_ASCII); 537 assert_eq!(&bincode_bytes[0..9], &[27, 0, 0, 0, 0, 0, 0, 0, 0]); 538 assert_eq!(&bincode_bytes[9..], testdata::basic::BINCODE_BYTES_ASCII); 539 540 let json_recovered: ZeroTrieAnyCow = serde_json::from_str(&json_str).unwrap(); 541 let bincode_recovered: ZeroTrieAnyCow = bincode::deserialize(&bincode_bytes).unwrap(); 542 543 assert_eq!(original.trie, json_recovered.trie); 544 assert_eq!(original.trie, bincode_recovered.trie); 545 546 assert!(matches!(json_recovered.trie.into_store(), Cow::Owned(_))); 547 assert!(matches!( 548 bincode_recovered.trie.into_store(), 549 Cow::Borrowed(_) 550 )); 551 } 552 553 #[test] test_serde_any_cow_u()554 pub fn test_serde_any_cow_u() { 555 let trie = ZeroTriePerfectHash::from_store(Cow::from(testdata::basic::TRIE_UNICODE)) 556 .into_zerotrie(); 557 let original = ZeroTrieAnyCow { trie }; 558 let json_str = serde_json::to_string(&original).unwrap(); 559 let bincode_bytes = bincode::serialize(&original).unwrap(); 560 561 assert_eq!(json_str, testdata::basic::JSON_STR_UNICODE); 562 assert_eq!(&bincode_bytes[0..9], &[40, 0, 0, 0, 0, 0, 0, 0, 3]); 563 assert_eq!(&bincode_bytes[9..], testdata::basic::BINCODE_BYTES_UNICODE); 564 565 let json_recovered: ZeroTrieAnyCow = serde_json::from_str(&json_str).unwrap(); 566 let bincode_recovered: ZeroTrieAnyCow = bincode::deserialize(&bincode_bytes).unwrap(); 567 568 assert_eq!(original.trie, json_recovered.trie); 569 assert_eq!(original.trie, bincode_recovered.trie); 570 571 assert!(matches!(json_recovered.trie.into_store(), Cow::Owned(_))); 572 assert!(matches!( 573 bincode_recovered.trie.into_store(), 574 Cow::Borrowed(_) 575 )); 576 } 577 } 578 579 #[cfg(test)] 580 #[cfg(feature = "zerovec")] 581 mod tests_zerovec { 582 use super::*; 583 use zerovec::ZeroVec; 584 585 #[derive(Serialize, Deserialize)] 586 pub struct ZeroTrieSimpleAsciiZeroVec<'a> { 587 #[serde(borrow)] 588 trie: ZeroTrieSimpleAscii<ZeroVec<'a, u8>>, 589 } 590 591 #[test] test_serde_simpleascii_zerovec()592 pub fn test_serde_simpleascii_zerovec() { 593 let trie = 594 ZeroTrieSimpleAscii::from_store(ZeroVec::new_borrowed(testdata::basic::TRIE_ASCII)); 595 let original = ZeroTrieSimpleAsciiZeroVec { trie }; 596 let json_str = serde_json::to_string(&original).unwrap(); 597 let bincode_bytes = bincode::serialize(&original).unwrap(); 598 599 assert_eq!(json_str, testdata::basic::JSON_STR_ASCII); 600 assert_eq!(&bincode_bytes[0..9], &[0, 26, 0, 0, 0, 0, 0, 0, 0]); 601 assert_eq!(&bincode_bytes[9..], testdata::basic::BINCODE_BYTES_ASCII); 602 603 let json_recovered: ZeroTrieSimpleAsciiZeroVec = serde_json::from_str(&json_str).unwrap(); 604 let bincode_recovered: ZeroTrieSimpleAsciiZeroVec = 605 bincode::deserialize(&bincode_bytes).unwrap(); 606 607 assert_eq!(original.trie, json_recovered.trie); 608 assert_eq!(original.trie, bincode_recovered.trie); 609 610 assert!(json_recovered.trie.into_store().is_owned()); 611 assert!(!bincode_recovered.trie.into_store().is_owned()); 612 } 613 614 #[derive(Serialize, Deserialize)] 615 pub struct ZeroTriePerfectHashZeroVec<'a> { 616 #[serde(borrow)] 617 trie: ZeroTriePerfectHash<ZeroVec<'a, u8>>, 618 } 619 620 #[test] test_serde_perfecthash_zerovec()621 pub fn test_serde_perfecthash_zerovec() { 622 let trie = 623 ZeroTriePerfectHash::from_store(ZeroVec::new_borrowed(testdata::basic::TRIE_ASCII)); 624 let original = ZeroTriePerfectHashZeroVec { trie }; 625 let json_str = serde_json::to_string(&original).unwrap(); 626 let bincode_bytes = bincode::serialize(&original).unwrap(); 627 628 assert_eq!(json_str, testdata::basic::JSON_STR_ASCII); 629 assert_eq!(&bincode_bytes[0..9], &[3, 26, 0, 0, 0, 0, 0, 0, 0]); 630 assert_eq!(&bincode_bytes[9..], testdata::basic::BINCODE_BYTES_ASCII); 631 632 let json_recovered: ZeroTriePerfectHashZeroVec = serde_json::from_str(&json_str).unwrap(); 633 let bincode_recovered: ZeroTriePerfectHashZeroVec = 634 bincode::deserialize(&bincode_bytes).unwrap(); 635 636 assert_eq!(original.trie, json_recovered.trie); 637 assert_eq!(original.trie, bincode_recovered.trie); 638 639 assert!(json_recovered.trie.into_store().is_owned()); 640 assert!(!bincode_recovered.trie.into_store().is_owned()); 641 } 642 } 643