co_primitives/library/
serde_map_as_list.rs1use serde::{
5 de::{SeqAccess, Visitor},
6 ser::SerializeSeq,
7 Deserialize, Deserializer, Serialize, Serializer,
8};
9use std::{iter::FromIterator, marker::PhantomData};
10
11pub fn serialize<S, K, V, M>(map: &M, serializer: S) -> Result<S::Ok, S::Error>
12where
13 S: Serializer,
14 K: Serialize,
15 V: Serialize,
16 for<'a> &'a M: IntoIterator<Item = (&'a K, &'a V)>,
17{
18 let iter = map.into_iter();
19 let (len, _) = iter.size_hint();
20 let mut seq = serializer.serialize_seq(Some(len))?;
21 for (k, v) in iter {
22 seq.serialize_element(&(&k, v))?;
23 }
24 seq.end()
25}
26
27pub fn deserialize<'de, D, K, V, M>(deserializer: D) -> Result<M, D::Error>
28where
29 D: Deserializer<'de>,
30 K: Deserialize<'de>,
31 V: Deserialize<'de>,
32 M: FromIterator<(K, V)> + Default + Extend<(K, V)>,
33{
34 struct MapAsListVisitor<K, V, M> {
35 marker: PhantomData<(K, V, M)>,
36 }
37
38 impl<'de, K, V, M> Visitor<'de> for MapAsListVisitor<K, V, M>
39 where
40 K: Deserialize<'de>,
41 V: Deserialize<'de>,
42 M: Default + Extend<(K, V)>,
43 {
44 type Value = M;
45
46 fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
47 f.write_str("a sequence of [key, value] pairs")
48 }
49
50 fn visit_seq<A>(self, mut seq: A) -> Result<M, A::Error>
51 where
52 A: SeqAccess<'de>,
53 {
54 let mut map = M::default();
55
56 while let Some((k, v)) = seq.next_element::<(K, V)>()? {
57 map.extend(std::iter::once((k, v)));
59 }
60
61 Ok(map)
62 }
63 }
64
65 deserializer.deserialize_seq(MapAsListVisitor { marker: PhantomData::<(K, V, M)> })
66}
67
68#[cfg(test)]
69mod tests {
70 use crate::{from_cbor, serde_map_as_list, to_cbor};
71 use serde::{Deserialize, Serialize};
72 use std::collections::BTreeMap;
73
74 #[derive(Debug, Serialize, Deserialize)]
75 #[serde(transparent)]
76 struct Wrapper(#[serde(with = "serde_map_as_list")] BTreeMap<u32, String>);
77
78 #[test]
79 fn test_list_btreemap() {
80 let mut map = BTreeMap::new();
81 map.insert(1, "one".to_owned());
82 map.insert(2, "two".to_owned());
83
84 let wrapper = Wrapper(map);
85
86 let json = serde_json::to_string(&wrapper).unwrap();
87 assert_eq!(json, r#"[[1,"one"],[2,"two"]]"#);
89 }
90
91 #[test]
92 fn test_roundtrip_btreemap_dagcbor() {
93 let mut map = BTreeMap::new();
94 map.insert(42, "forty-two".to_owned());
95 map.insert(7, "seven".to_owned());
96
97 let wrapper = Wrapper(map.clone());
98
99 let bytes = to_cbor(&wrapper).unwrap();
100 let decoded: Wrapper = from_cbor(&bytes).unwrap();
101
102 assert_eq!(decoded.0, map);
103 }
104
105 #[test]
106 fn test_roundtrip_btreemap_empty() {
107 let map: BTreeMap<u32, String> = BTreeMap::new();
108 let wrapper = Wrapper(map.clone());
109
110 let bytes = to_cbor(&wrapper).unwrap();
111 let decoded: Wrapper = from_cbor(&bytes).unwrap();
112
113 assert!(decoded.0.is_empty());
114 assert_eq!(decoded.0, map);
115 }
116}