1use super::{ZeroMap2d, ZeroMap2dBorrowed, ZeroMap2dCursor};
6use crate::map::{MutableZeroVecLike, ZeroMapKV, ZeroVecLike};
7use crate::ZeroVec;
8use alloc::vec::Vec;
9use core::fmt;
10use core::marker::PhantomData;
11use serde::de::{self, Deserialize, Deserializer, MapAccess, Visitor};
12#[cfg(feature = "serde")]
13use serde::ser::{Serialize, SerializeMap, Serializer};
14
15#[cfg(feature = "serde")]
17impl<'a, K0, K1, V> Serialize for ZeroMap2d<'a, K0, K1, V>
18where
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{
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#[cfg(feature = "serde")]
46struct ZeroMap2dInnerMapSerialize<'a, 'l, K0, K1, V>
47where
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")]
56impl<'a, 'l, K0, K1, V> Serialize for ZeroMap2dInnerMapSerialize<'a, 'l, K0, K1, V>
57where
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{
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#[cfg(feature = "serde")]
80impl<'a, K0, K1, V> Serialize for ZeroMap2dBorrowed<'a, K0, K1, V>
81where
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{
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
97struct ZeroMap2dMapVisitor<'a, K0, K1, V>
99where
100 K0: ZeroMapKV<'a> + ?Sized + Ord,
101 K1: ZeroMapKV<'a> + ?Sized + Ord,
102 V: ZeroMapKV<'a> + ?Sized,
103{
104 #[allow(clippy::type_complexity)] marker: PhantomData<fn() -> (&'a K0::OwnedType, &'a K1::OwnedType, &'a V::OwnedType)>,
106}
107
108impl<'a, K0, K1, V> ZeroMap2dMapVisitor<'a, K0, K1, V>
109where
110 K0: ZeroMapKV<'a> + ?Sized + Ord,
111 K1: ZeroMapKV<'a> + ?Sized + Ord,
112 V: ZeroMapKV<'a> + ?Sized,
113{
114 fn new() -> Self {
115 ZeroMap2dMapVisitor {
116 marker: PhantomData,
117 }
118 }
119}
120
121impl<'a, 'de, K0, K1, V> Visitor<'de> for ZeroMap2dMapVisitor<'a, K0, K1, V>
122where
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
134 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
135 formatter.write_str("a map produced by ZeroMap2d")
136 }
137
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 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
169struct TupleVecMap<K1, V> {
171 pub entries: Vec<(K1, V)>,
172}
173
174struct TupleVecMapVisitor<K1, V> {
175 #[allow(clippy::type_complexity)] marker: PhantomData<fn() -> (K1, V)>,
177}
178
179impl<K1, V> TupleVecMapVisitor<K1, V> {
180 fn new() -> Self {
181 TupleVecMapVisitor {
182 marker: PhantomData,
183 }
184 }
185}
186
187impl<'de, K1, V> Visitor<'de> for TupleVecMapVisitor<K1, V>
188where
189 K1: Deserialize<'de>,
190 V: Deserialize<'de>,
191{
192 type Value = TupleVecMap<K1, V>;
193
194 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
195 formatter.write_str("an inner map produced by ZeroMap2d")
196 }
197
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
210impl<'de, K1, V> Deserialize<'de> for TupleVecMap<K1, V>
211where
212 K1: Deserialize<'de>,
213 V: Deserialize<'de>,
214{
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
223impl<'de, 'a, K0, K1, V> Deserialize<'de> for ZeroMap2d<'a, K0, K1, V>
225where
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{
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 if keys0.zvl_len() != joiner.len() {
252 return Err(de::Error::custom(
253 "Mismatched keys0 and joiner sizes in ZeroMap2d",
254 ));
255 }
256 if keys1.zvl_len() != values.zvl_len() {
258 return Err(de::Error::custom(
259 "Mismatched keys1 and value sizes in ZeroMap2d",
260 ));
261 }
262 if !joiner.zvl_is_ascending() {
264 return Err(de::Error::custom(
265 "ZeroMap2d deserializing joiner array out of order",
266 ));
267 }
268 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 #[cfg(debug_assertions)]
284 result.check_invariants();
285 Ok(result)
286 }
287 }
288}
289
290impl<'de, 'a, K0, K1, V> Deserialize<'de> for ZeroMap2dBorrowed<'a, K0, K1, V>
292where
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{
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)]
354mod 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
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]
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]
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]
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]
425 fn test_sample_bincode() {
426 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}