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 struct DeriveTest_ZeroMap2d<'data> {
358 #[serde(borrow)]
359 _data: ZeroMap2d<'data, u16, str, [u8]>,
360 }
361
362 #[derive(serde::Serialize, serde::Deserialize)]
363 struct DeriveTest_ZeroMap2dBorrowed<'data> {
364 #[serde(borrow)]
365 _data: ZeroMap2dBorrowed<'data, u16, str, [u8]>,
366 }
367
368 const JSON_STR: &str = "{\"1\":{\"1\":\"uno\"},\"2\":{\"2\":\"dos\",\"3\":\"tres\"}}";
369 const BINCODE_BYTES: &[u8] = &[
370 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,
371 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,
372 117, 110, 111, 100, 111, 115, 116, 114, 101, 115,
373 ];
374
375 fn make_map() -> ZeroMap2d<'static, u32, u16, str> {
376 let mut map = ZeroMap2d::new();
377 map.insert(&1, &1, "uno");
378 map.insert(&2, &2, "dos");
379 map.insert(&2, &3, "tres");
380 map
381 }
382
383 #[test]
384 fn test_serde_json() {
385 let map = make_map();
386 let json_str = serde_json::to_string(&map).expect("serialize");
387 assert_eq!(JSON_STR, json_str);
388 let new_map: ZeroMap2d<u32, u16, str> =
389 serde_json::from_str(&json_str).expect("deserialize");
390 assert_eq!(format!("{new_map:?}"), format!("{map:?}"));
391 }
392
393 #[test]
394 fn test_bincode() {
395 let map = make_map();
396 let bincode_bytes = bincode::serialize(&map).expect("serialize");
397 assert_eq!(BINCODE_BYTES, bincode_bytes);
398 let new_map: ZeroMap2d<u32, u16, str> =
399 bincode::deserialize(&bincode_bytes).expect("deserialize");
400 assert_eq!(
401 format!("{new_map:?}"),
402 format!("{map:?}").replace("Owned", "Borrowed"),
403 );
404
405 let new_map: ZeroMap2dBorrowed<u32, u16, str> =
406 bincode::deserialize(&bincode_bytes).expect("deserialize");
407 assert_eq!(
408 format!("{new_map:?}"),
409 format!("{map:?}")
410 .replace("Owned", "Borrowed")
411 .replace("ZeroMap2d", "ZeroMap2dBorrowed")
412 );
413 }
414
415 #[test]
416 fn test_serde_rmp() {
417 let map = make_map();
418 let rmp_buf = rmp_serde::to_vec(&map).expect("serialize");
419 let new_map: ZeroMap2d<u32, u16, str> = rmp_serde::from_slice(&rmp_buf).unwrap();
420 assert_eq!(map, new_map);
421 }
422
423 #[test]
424 fn test_sample_bincode() {
425 let mut map: ZeroMap2d<u16, u16, str> = ZeroMap2d::new();
427 map.insert(&1, &2, "three");
428 let bincode_bytes: Vec<u8> = bincode::serialize(&map).expect("serialize");
429 assert_eq!(
430 bincode_bytes.as_slice(),
431 &[
432 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,
433 0, 0, 2, 0, 7, 0, 0, 0, 0, 0, 0, 0, 1, 0, 116, 104, 114, 101, 101
434 ]
435 );
436 }
437}