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 #[expect(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 marker: PhantomData<fn() -> (K1, V)>,
176}
177
178impl<K1, V> TupleVecMapVisitor<K1, V> {
179 fn new() -> Self {
180 TupleVecMapVisitor {
181 marker: PhantomData,
182 }
183 }
184}
185
186impl<'de, K1, V> Visitor<'de> for TupleVecMapVisitor<K1, V>
187where
188 K1: Deserialize<'de>,
189 V: Deserialize<'de>,
190{
191 type Value = TupleVecMap<K1, V>;
192
193 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
194 formatter.write_str("an inner map produced by ZeroMap2d")
195 }
196
197 fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error>
198 where
199 M: MapAccess<'de>,
200 {
201 let mut result = Vec::with_capacity(access.size_hint().unwrap_or(0));
202 while let Some((key1, value)) = access.next_entry::<K1, V>()? {
203 result.push((key1, value));
204 }
205 Ok(TupleVecMap { entries: result })
206 }
207}
208
209impl<'de, K1, V> Deserialize<'de> for TupleVecMap<K1, V>
210where
211 K1: Deserialize<'de>,
212 V: Deserialize<'de>,
213{
214 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
215 where
216 D: Deserializer<'de>,
217 {
218 deserializer.deserialize_map(TupleVecMapVisitor::<K1, V>::new())
219 }
220}
221
222impl<'de, 'a, K0, K1, V> Deserialize<'de> for ZeroMap2d<'a, K0, K1, V>
224where
225 K0: ZeroMapKV<'a> + Ord + ?Sized,
226 K1: ZeroMapKV<'a> + Ord + ?Sized,
227 V: ZeroMapKV<'a> + ?Sized,
228 K0::Container: Deserialize<'de>,
229 K1::Container: Deserialize<'de>,
230 V::Container: Deserialize<'de>,
231 K0::OwnedType: Deserialize<'de>,
232 K1::OwnedType: Deserialize<'de>,
233 V::OwnedType: Deserialize<'de>,
234 'de: 'a,
235{
236 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
237 where
238 D: Deserializer<'de>,
239 {
240 if deserializer.is_human_readable() {
241 deserializer.deserialize_map(ZeroMap2dMapVisitor::<'a, K0, K1, V>::new())
242 } else {
243 let (keys0, joiner, keys1, values): (
244 K0::Container,
245 ZeroVec<u32>,
246 K1::Container,
247 V::Container,
248 ) = Deserialize::deserialize(deserializer)?;
249 if keys0.zvl_len() != joiner.len() {
251 return Err(de::Error::custom(
252 "Mismatched keys0 and joiner sizes in ZeroMap2d",
253 ));
254 }
255 if keys1.zvl_len() != values.zvl_len() {
257 return Err(de::Error::custom(
258 "Mismatched keys1 and value sizes in ZeroMap2d",
259 ));
260 }
261 if !joiner.zvl_is_ascending() {
263 return Err(de::Error::custom(
264 "ZeroMap2d deserializing joiner array out of order",
265 ));
266 }
267 if let Some(last_joiner0) = joiner.last() {
269 if keys1.zvl_len() != last_joiner0 as usize {
270 return Err(de::Error::custom(
271 "ZeroMap2d deserializing joiner array malformed",
272 ));
273 }
274 }
275 let result = Self {
276 keys0,
277 joiner,
278 keys1,
279 values,
280 };
281 #[cfg(debug_assertions)]
283 result.check_invariants();
284 Ok(result)
285 }
286 }
287}
288
289impl<'de, 'a, K0, K1, V> Deserialize<'de> for ZeroMap2dBorrowed<'a, K0, K1, V>
291where
292 K0: ZeroMapKV<'a> + Ord + ?Sized,
293 K1: ZeroMapKV<'a> + Ord + ?Sized,
294 V: ZeroMapKV<'a> + ?Sized,
295 K0::Container: Deserialize<'de>,
296 K1::Container: Deserialize<'de>,
297 V::Container: Deserialize<'de>,
298 K0::OwnedType: Deserialize<'de>,
299 K1::OwnedType: Deserialize<'de>,
300 V::OwnedType: Deserialize<'de>,
301 'de: 'a,
302{
303 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
304 where
305 D: Deserializer<'de>,
306 {
307 if deserializer.is_human_readable() {
308 Err(de::Error::custom(
309 "ZeroMap2dBorrowed cannot be deserialized from human-readable formats",
310 ))
311 } else {
312 let deserialized: ZeroMap2d<'a, K0, K1, V> = ZeroMap2d::deserialize(deserializer)?;
313 let keys0 = if let Some(keys0) = deserialized.keys0.zvl_as_borrowed_inner() {
314 keys0
315 } else {
316 return Err(de::Error::custom(
317 "ZeroMap2dBorrowed can only deserialize in zero-copy ways",
318 ));
319 };
320 let joiner = if let Some(joiner) = deserialized.joiner.zvl_as_borrowed_inner() {
321 joiner
322 } else {
323 return Err(de::Error::custom(
324 "ZeroMap2dBorrowed can only deserialize in zero-copy ways",
325 ));
326 };
327 let keys1 = if let Some(keys1) = deserialized.keys1.zvl_as_borrowed_inner() {
328 keys1
329 } else {
330 return Err(de::Error::custom(
331 "ZeroMap2dBorrowed can only deserialize in zero-copy ways",
332 ));
333 };
334 let values = if let Some(values) = deserialized.values.zvl_as_borrowed_inner() {
335 values
336 } else {
337 return Err(de::Error::custom(
338 "ZeroMap2dBorrowed can only deserialize in zero-copy ways",
339 ));
340 };
341 Ok(Self {
342 keys0,
343 joiner,
344 keys1,
345 values,
346 })
347 }
348 }
349}
350
351#[cfg(test)]
352#[allow(non_camel_case_types)]
353mod test {
354 use crate::map2d::{ZeroMap2d, ZeroMap2dBorrowed};
355
356 #[derive(serde::Serialize, serde::Deserialize)]
357 #[allow(
358 dead_code,
359 reason = "We are testing that these types can be deserialized, and Tests compatibility of custom impl with Serde derive."
360 )]
361 struct DeriveTest_ZeroMap2d<'data> {
362 #[serde(borrow)]
363 _data: ZeroMap2d<'data, u16, str, [u8]>,
364 }
365
366 #[derive(serde::Serialize, serde::Deserialize)]
367 #[allow(
368 dead_code,
369 reason = "We are testing that these types can be deserialized, and Tests compatibility of custom impl with Serde derive."
370 )]
371 struct DeriveTest_ZeroMap2dBorrowed<'data> {
372 #[serde(borrow)]
373 _data: ZeroMap2dBorrowed<'data, u16, str, [u8]>,
374 }
375
376 const JSON_STR: &str = "{\"1\":{\"1\":\"uno\"},\"2\":{\"2\":\"dos\",\"3\":\"tres\"}}";
377 const BINCODE_BYTES: &[u8] = &[
378 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,
379 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,
380 117, 110, 111, 100, 111, 115, 116, 114, 101, 115,
381 ];
382
383 fn make_map() -> ZeroMap2d<'static, u32, u16, str> {
384 let mut map = ZeroMap2d::new();
385 map.insert(&1, &1, "uno");
386 map.insert(&2, &2, "dos");
387 map.insert(&2, &3, "tres");
388 map
389 }
390
391 #[test]
392 fn test_serde_json() {
393 let map = make_map();
394 let json_str = serde_json::to_string(&map).expect("serialize");
395 assert_eq!(JSON_STR, json_str);
396 let new_map: ZeroMap2d<u32, u16, str> =
397 serde_json::from_str(&json_str).expect("deserialize");
398 assert_eq!(format!("{new_map:?}"), format!("{map:?}"));
399 }
400
401 #[test]
402 fn test_bincode() {
403 let map = make_map();
404 let bincode_bytes = bincode::serialize(&map).expect("serialize");
405 assert_eq!(BINCODE_BYTES, bincode_bytes);
406 let new_map: ZeroMap2d<u32, u16, str> =
407 bincode::deserialize(&bincode_bytes).expect("deserialize");
408 assert_eq!(
409 format!("{new_map:?}"),
410 format!("{map:?}").replace("Owned", "Borrowed"),
411 );
412
413 let new_map: ZeroMap2dBorrowed<u32, u16, str> =
414 bincode::deserialize(&bincode_bytes).expect("deserialize");
415 assert_eq!(
416 format!("{new_map:?}"),
417 format!("{map:?}")
418 .replace("Owned", "Borrowed")
419 .replace("ZeroMap2d", "ZeroMap2dBorrowed")
420 );
421 }
422
423 #[test]
424 fn test_serde_rmp() {
425 let map = make_map();
426 let rmp_buf = rmp_serde::to_vec(&map).expect("serialize");
427 let new_map: ZeroMap2d<u32, u16, str> = rmp_serde::from_slice(&rmp_buf).unwrap();
428 assert_eq!(map, new_map);
429 }
430
431 #[test]
432 fn test_sample_bincode() {
433 let mut map: ZeroMap2d<u16, u16, str> = ZeroMap2d::new();
435 map.insert(&1, &2, "three");
436 let bincode_bytes: Vec<u8> = bincode::serialize(&map).expect("serialize");
437 assert_eq!(
438 bincode_bytes.as_slice(),
439 &[
440 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,
441 0, 0, 2, 0, 7, 0, 0, 0, 0, 0, 0, 0, 1, 0, 116, 104, 114, 101, 101
442 ]
443 );
444 }
445}