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 ).
5 use super::{ZeroMap2d, ZeroMap2dBorrowed, ZeroMap2dCursor}
;
6 use crate::map
::{MutableZeroVecLike, ZeroMapKV, ZeroVecLike}
;
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}
;
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
>
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
,
26 fn serialize
<S
>(&self, serializer
: S
) -> Result
<S
::Ok
, S
::Error
>
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
)?
;
39 (&self.keys0
, &self.joiner
, &self.keys1
, &self.values
).serialize(serializer
)
44 /// Helper struct for human-serializing the inner map of a ZeroMap2d
45 #[cfg(feature = "serde")]
46 struct ZeroMap2dInnerMapSerialize
<'a
, 'l
, K0
, K1
, V
>
48 K0
: ZeroMapKV
<'a
> + ?Sized
+ Ord
,
49 K1
: ZeroMapKV
<'a
> + ?Sized
+ Ord
,
50 V
: ZeroMapKV
<'a
> + ?Sized
,
52 pub cursor
: ZeroMap2dCursor
<'l
, 'a
, K0
, K1
, V
>,
55 #[cfg(feature = "serde")]
56 impl<'a
, 'l
, K0
, K1
, V
> Serialize
for ZeroMap2dInnerMapSerialize
<'a
, 'l
, K0
, K1
, V
>
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
,
65 fn serialize
<S
>(&self, serializer
: S
) -> Result
<S
::Ok
, S
::Error
>
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
))?
;
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
>
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
,
89 fn serialize
<S
>(&self, serializer
: S
) -> Result
<S
::Ok
, S
::Error
>
93 ZeroMap2d
::<K0
, K1
, V
>::from(*self).serialize(serializer
)
97 /// Modified example from https://serde.rs/deserialize-map.html
98 struct ZeroMap2dMapVisitor
<'a
, K0
, K1
, V
>
100 K0
: ZeroMapKV
<'a
> + ?Sized
+ Ord
,
101 K1
: ZeroMapKV
<'a
> + ?Sized
+ Ord
,
102 V
: ZeroMapKV
<'a
> + ?Sized
,
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
)>,
108 impl<'a
, K0
, K1
, V
> ZeroMap2dMapVisitor
<'a
, K0
, K1
, V
>
110 K0
: ZeroMapKV
<'a
> + ?Sized
+ Ord
,
111 K1
: ZeroMapKV
<'a
> + ?Sized
+ Ord
,
112 V
: ZeroMapKV
<'a
> + ?Sized
,
115 ZeroMap2dMapVisitor
{
121 impl<'a
, 'de
, K0
, K1
, V
> Visitor
<'de
> for ZeroMap2dMapVisitor
<'a
, K0
, K1
, V
>
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
>,
132 type Value
= ZeroMap2d
<'a
, K0
, K1
, V
>;
134 fn expecting(&self, formatter
: &mut fmt
::Formatter
) -> fmt
::Result
{
135 formatter
.write_str("a map produced by ZeroMap2d")
138 fn visit_map
<M
>(self, mut access
: M
) -> Result
<Self::Value
, M
::Error
>
142 let mut map
= ZeroMap2d
::with_capacity(access
.size_hint().unwrap_or(0));
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
>>()?
149 for (key1
, value
) in inner_map
.entries
.iter() {
152 K0
::Container
::owned_as_t(&key0
),
153 K1
::Container
::owned_as_t(key1
),
154 V
::Container
::owned_as_t(value
),
158 return Err(de
::Error
::custom(
159 "ZeroMap2d's keys must be sorted while deserializing",
169 /// Helper struct for human-deserializing the inner map of a ZeroMap2d
170 struct TupleVecMap
<K1
, V
> {
171 pub entries
: Vec
<(K1
, V
)>,
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
)>,
179 impl<K1
, V
> TupleVecMapVisitor
<K1
, V
> {
187 impl<'de
, K1
, V
> Visitor
<'de
> for TupleVecMapVisitor
<K1
, V
>
189 K1
: Deserialize
<'de
>,
192 type Value
= TupleVecMap
<K1
, V
>;
194 fn expecting(&self, formatter
: &mut fmt
::Formatter
) -> fmt
::Result
{
195 formatter
.write_str("an inner map produced by ZeroMap2d")
198 fn visit_map
<M
>(self, mut access
: M
) -> Result
<Self::Value
, M
::Error
>
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
));
206 Ok(TupleVecMap { entries: result }
)
210 impl<'de
, K1
, V
> Deserialize
<'de
> for TupleVecMap
<K1
, V
>
212 K1
: Deserialize
<'de
>,
215 fn deserialize
<D
>(deserializer
: D
) -> Result
<Self, D
::Error
>
217 D
: Deserializer
<'de
>,
219 deserializer
.deserialize_map(TupleVecMapVisitor
::<K1
, V
>::new())
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
>
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
>,
237 fn deserialize
<D
>(deserializer
: D
) -> Result
<Self, D
::Error
>
239 D
: Deserializer
<'de
>,
241 if deserializer
.is_human_readable() {
242 deserializer
.deserialize_map(ZeroMap2dMapVisitor
::<'a
, K0
, K1
, V
>::new())
244 let (keys0
, joiner
, keys1
, values
): (
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",
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",
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",
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",
282 // In debug mode, check the optional invariants, too
283 #[cfg(debug_assertions)]
284 result
.check_invariants();
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
>
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
>,
304 fn deserialize
<D
>(deserializer
: D
) -> Result
<Self, D
::Error
>
306 D
: Deserializer
<'de
>,
308 if deserializer
.is_human_readable() {
309 Err(de
::Error
::custom(
310 "ZeroMap2dBorrowed cannot be deserialized from human-readable formats",
313 let deserialized
: ZeroMap2d
<'a
, K0
, K1
, V
> = ZeroMap2d
::deserialize(deserializer
)?
;
314 let keys0
= if let Some(keys0
) = deserialized
.keys0
.zvl_as_borrowed_inner() {
317 return Err(de
::Error
::custom(
318 "ZeroMap2dBorrowed can only deserialize in zero-copy ways",
321 let joiner
= if let Some(joiner
) = deserialized
.joiner
.zvl_as_borrowed_inner() {
324 return Err(de
::Error
::custom(
325 "ZeroMap2dBorrowed can only deserialize in zero-copy ways",
328 let keys1
= if let Some(keys1
) = deserialized
.keys1
.zvl_as_borrowed_inner() {
331 return Err(de
::Error
::custom(
332 "ZeroMap2dBorrowed can only deserialize in zero-copy ways",
335 let values
= if let Some(values
) = deserialized
.values
.zvl_as_borrowed_inner() {
338 return Err(de
::Error
::custom(
339 "ZeroMap2dBorrowed can only deserialize in zero-copy ways",
353 #[allow(non_camel_case_types)]
355 use crate::map2d
::{ZeroMap2d, ZeroMap2dBorrowed}
;
357 #[derive(serde::Serialize, serde::Deserialize)]
358 struct DeriveTest_ZeroMap2d
<'data
> {
360 _data
: ZeroMap2d
<'data
, u16, str, [u8]>,
363 #[derive(serde::Serialize, serde::Deserialize)]
364 struct DeriveTest_ZeroMap2dBorrowed
<'data
> {
366 _data
: ZeroMap2dBorrowed
<'data
, u16, str, [u8]>,
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, 20, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0,
373 3, 0, 6, 0, 117, 110, 111, 100, 111, 115, 116, 114, 101, 115,
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");
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:?}"));
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");
402 format
!("{new_map:?}"),
403 format
!("{map:?}").replace("Owned", "Borrowed"),
406 let new_map
: ZeroMap2dBorrowed
<u32, u16, str> =
407 bincode
::deserialize(&bincode_bytes
).expect("deserialize");
409 format
!("{new_map:?}"),
411 .replace("Owned", "Borrowed")
412 .replace("ZeroMap2d", "ZeroMap2dBorrowed")
417 fn test_sample_bincode() {
418 // This is the map from the main docs page for ZeroMap2d
419 let mut map
: ZeroMap2d
<u16, u16, str> = ZeroMap2d
::new();
420 map
.insert(&1, &2, "three");
421 let bincode_bytes
: Vec
<u8> = bincode
::serialize(&map
).expect("serialize");
423 bincode_bytes
.as_slice(),
425 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,
426 0, 0, 2, 0, 11, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 116, 104, 114, 101, 101