1use super::LiteMap;
6use crate::store::*;
7use alloc::vec::Vec;
8use core::fmt;
9use core::marker::PhantomData;
10use serde::{
11 de::{MapAccess, SeqAccess, Visitor},
12 ser::{SerializeMap, SerializeSeq},
13 Deserialize, Deserializer, Serialize, Serializer,
14};
15
16impl<K, V, R> Serialize for LiteMap<K, V, R>
17where
18 K: Serialize,
19 V: Serialize,
20 R: Store<K, V>,
21{
22 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
23 where
24 S: Serializer,
25 {
26 if serializer.is_human_readable() {
30 let k_is_num_or_string = self
31 .values
32 .lm_get(0)
33 .is_some_and(|(k, _)| super::serde_helpers::is_num_or_string(k));
34 if !k_is_num_or_string {
35 let mut seq = serializer.serialize_seq(Some(self.len()))?;
36 for index in 0..self.len() {
38 #[allow(clippy::unwrap_used)] seq.serialize_element(&self.get_indexed(index).unwrap())?;
40 }
41 return seq.end();
42 }
43 }
45
46 let mut map = serializer.serialize_map(Some(self.len()))?;
53 for index in 0..self.len() {
54 #[allow(clippy::unwrap_used)] let (k, v) = self.get_indexed(index).unwrap();
56 map.serialize_entry(k, v)?;
57 }
58 map.end()
59 }
60}
61
62#[allow(clippy::type_complexity)]
64struct LiteMapVisitor<K, V, R> {
65 marker: PhantomData<fn() -> LiteMap<K, V, R>>,
66}
67
68impl<K, V, R> LiteMapVisitor<K, V, R> {
69 fn new() -> Self {
70 Self {
71 marker: PhantomData,
72 }
73 }
74}
75
76impl<'de, K, V, R> Visitor<'de> for LiteMapVisitor<K, V, R>
77where
78 K: Deserialize<'de> + Ord,
79 V: Deserialize<'de>,
80 R: StoreBulkMut<K, V>,
81{
82 type Value = LiteMap<K, V, R>;
83
84 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
85 formatter.write_str("a map produced by LiteMap")
86 }
87
88 fn visit_seq<S>(self, mut access: S) -> Result<Self::Value, S::Error>
89 where
90 S: SeqAccess<'de>,
91 {
92 let mut map = LiteMap::with_capacity(access.size_hint().unwrap_or(0));
94 let mut out_of_order = Vec::new();
95
96 while let Some((key, value)) = access.next_element()? {
97 if let Some((key, value)) = map.try_append(key, value) {
98 out_of_order.push((key, value));
99 }
100 }
101
102 if !out_of_order.is_empty() {
103 map.extend(out_of_order);
104 }
105
106 Ok(map)
107 }
108
109 fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error>
110 where
111 M: MapAccess<'de>,
112 {
113 let mut map = LiteMap::with_capacity(access.size_hint().unwrap_or(0));
114 let mut out_of_order = Vec::new();
115
116 while let Some((key, value)) = access.next_entry()? {
119 if let Some((key, value)) = map.try_append(key, value) {
127 out_of_order.push((key, value));
128 }
129 }
130
131 if !out_of_order.is_empty() {
132 map.extend(out_of_order);
133 }
134
135 Ok(map)
136 }
137}
138
139impl<'de, K, V, R> Deserialize<'de> for LiteMap<K, V, R>
140where
141 K: Ord + Deserialize<'de>,
142 V: Deserialize<'de>,
143 R: StoreBulkMut<K, V>,
144{
145 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
146 where
147 D: Deserializer<'de>,
148 {
149 if deserializer.is_human_readable() {
150 deserializer.deserialize_any(LiteMapVisitor::new())
153 } else {
154 deserializer.deserialize_map(LiteMapVisitor::new())
155 }
156 }
157}
158
159#[cfg(test)]
160mod test {
161 use crate::LiteMap;
162 use alloc::borrow::ToOwned;
163 use alloc::string::String;
164
165 fn get_simple_map() -> LiteMap<u32, String> {
166 [
167 (1, "one".to_owned()),
168 (2, "two".to_owned()),
169 (4, "four".to_owned()),
170 (5, "five".to_owned()),
171 ]
172 .into_iter()
173 .collect()
174 }
175
176 fn get_tuple_map() -> LiteMap<(u32, String), String> {
177 [
178 ((1, "en".to_owned()), "one".to_owned()),
179 ((1, "zh".to_owned()), "一".to_owned()),
180 ((2, "en".to_owned()), "two".to_owned()),
181 ((2, "zh".to_owned()), "二".to_owned()),
182 ((4, "en".to_owned()), "four".to_owned()),
183 ((5, "en".to_owned()), "five".to_owned()),
184 ((5, "zh".to_owned()), "五".to_owned()),
185 ((7, "zh".to_owned()), "七".to_owned()),
186 ]
187 .into_iter()
188 .collect()
189 }
190
191 #[test]
192 fn test_roundtrip_json() {
193 let map = get_simple_map();
194 let json = serde_json::to_string(&map).unwrap();
195 assert_eq!(
196 json,
197 "{\"1\":\"one\",\"2\":\"two\",\"4\":\"four\",\"5\":\"five\"}"
198 );
199 let deserialized: LiteMap<u32, String> = serde_json::from_str(&json).unwrap();
200 assert_eq!(map, deserialized);
201
202 let map = get_tuple_map();
203 let json = serde_json::to_string(&map).unwrap();
204 assert_eq!(
205 json,
206 "[[[1,\"en\"],\"one\"],[[1,\"zh\"],\"一\"],[[2,\"en\"],\"two\"],\
207 [[2,\"zh\"],\"二\"],[[4,\"en\"],\"four\"],[[5,\"en\"],\"five\"],\
208 [[5,\"zh\"],\"五\"],[[7,\"zh\"],\"七\"]]"
209 );
210 let deserialized: LiteMap<(u32, String), String> = serde_json::from_str(&json).unwrap();
211 assert_eq!(map, deserialized);
212 }
213
214 #[test]
215 fn test_roundtrip_postcard() {
216 let map = get_simple_map();
217 let postcard = postcard::to_stdvec(&map).unwrap();
218 let deserialized: LiteMap<u32, String> = postcard::from_bytes(&postcard).unwrap();
219 assert_eq!(map, deserialized);
220
221 let map = get_tuple_map();
222 let postcard = postcard::to_stdvec(&map).unwrap();
223 let deserialized: LiteMap<(u32, String), String> = postcard::from_bytes(&postcard).unwrap();
224 assert_eq!(map, deserialized);
225 }
226
227 #[test]
230 fn test_deserialize_capacity() {
231 for len in 0..50 {
232 let mut map = (0..len).map(|i| (i, i.to_string())).collect::<Vec<_>>();
233 let postcard = postcard::to_stdvec(&map).unwrap();
234 let deserialized: LiteMap<u32, String> = postcard::from_bytes(&postcard).unwrap();
235 assert_eq!(deserialized.values.capacity(), len);
236 assert_eq!(deserialized.values.len(), len);
237 rand::seq::SliceRandom::shuffle(&mut map[..], &mut rand::rng());
239 let postcard = postcard::to_stdvec(&map).unwrap();
240 let deserialized: LiteMap<u32, String> = postcard::from_bytes(&postcard).unwrap();
241 assert_eq!(deserialized.values.capacity(), len);
242 assert_eq!(deserialized.values.len(), len);
243 }
244 }
245}