]> git.proxmox.com Git - rustc.git/blob - vendor/litemap/src/serde.rs
New upstream version 1.67.1+dfsg1
[rustc.git] / vendor / litemap / src / serde.rs
1 // This file is part of ICU4X. For terms of use, please see the file
2 // called LICENSE at the top level of the ICU4X source tree
3 // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
4
5 use super::LiteMap;
6 use crate::store::*;
7 use core::fmt;
8 use core::marker::PhantomData;
9 use serde::de::{MapAccess, SeqAccess, Visitor};
10 use serde::{Deserialize, Deserializer};
11
12 #[cfg(feature = "serde")]
13 use serde::{ser::SerializeMap, Serialize, Serializer};
14
15 #[cfg(feature = "serde")]
16 impl<K, V, R> Serialize for LiteMap<K, V, R>
17 where
18 K: Serialize,
19 V: Serialize,
20 R: Store<K, V> + Serialize,
21 {
22 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
23 where
24 S: Serializer,
25 {
26 // Many human-readable formats don't support values other
27 // than numbers and strings as map keys. For them, we can serialize
28 // as a vec of tuples instead
29 if serializer.is_human_readable() {
30 if let Some((ref k, _)) = self.values.lm_get(0) {
31 if !super::serde_helpers::is_num_or_string(k) {
32 return self.values.serialize(serializer);
33 }
34 // continue to regular serialization
35 }
36 }
37 let mut map = serializer.serialize_map(Some(self.len()))?;
38 let mut i = 0;
39 while i < self.values.lm_len() {
40 #[allow(clippy::unwrap_used)] // i is in range
41 let (k, v) = self.values.lm_get(i).unwrap();
42 map.serialize_entry(k, v)?;
43 i += 1;
44 }
45 map.end()
46 }
47 }
48
49 /// Modified example from https://serde.rs/deserialize-map.html
50 #[allow(clippy::type_complexity)]
51 struct LiteMapVisitor<K, V, R> {
52 marker: PhantomData<fn() -> LiteMap<K, V, R>>,
53 }
54
55 impl<K, V, R> LiteMapVisitor<K, V, R> {
56 fn new() -> Self {
57 Self {
58 marker: PhantomData,
59 }
60 }
61 }
62
63 impl<'de, K, V, R> Visitor<'de> for LiteMapVisitor<K, V, R>
64 where
65 K: Deserialize<'de> + Ord,
66 V: Deserialize<'de>,
67 R: StoreMut<K, V>,
68 {
69 type Value = LiteMap<K, V, R>;
70
71 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
72 formatter.write_str("a map produced by LiteMap")
73 }
74
75 fn visit_seq<S>(self, mut access: S) -> Result<Self::Value, S::Error>
76 where
77 S: SeqAccess<'de>,
78 {
79 let mut map = LiteMap::with_capacity(access.size_hint().unwrap_or(0));
80
81 // While there are entries remaining in the input, add them
82 // into our map.
83 while let Some((key, value)) = access.next_element()? {
84 // Try to append it at the end, hoping for a sorted map.
85 // If not sorted, insert as usual.
86 // This allows for arbitrary maps (e.g. from user JSON)
87 // to be deserialized into LiteMap
88 // without impacting performance in the case of deserializing
89 // a serialized map that came from another LiteMap
90 if let Some((key, value)) = map.try_append(key, value) {
91 // Note: this effectively selection sorts the map,
92 // which isn't efficient for large maps
93 map.insert(key, value);
94 }
95 }
96
97 Ok(map)
98 }
99
100 fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error>
101 where
102 M: MapAccess<'de>,
103 {
104 let mut map = LiteMap::with_capacity(access.size_hint().unwrap_or(0));
105
106 // While there are entries remaining in the input, add them
107 // into our map.
108 while let Some((key, value)) = access.next_entry()? {
109 // Try to append it at the end, hoping for a sorted map.
110 // If not sorted, insert as usual.
111 // This allows for arbitrary maps (e.g. from user JSON)
112 // to be deserialized into LiteMap
113 // without impacting performance in the case of deserializing
114 // a serialized map that came from another LiteMap
115 if let Some((key, value)) = map.try_append(key, value) {
116 // Note: this effectively selection sorts the map,
117 // which isn't efficient for large maps
118 map.insert(key, value);
119 }
120 }
121
122 Ok(map)
123 }
124 }
125
126 impl<'de, K, V, R> Deserialize<'de> for LiteMap<K, V, R>
127 where
128 K: Ord + Deserialize<'de>,
129 V: Deserialize<'de>,
130 R: StoreMut<K, V>,
131 {
132 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
133 where
134 D: Deserializer<'de>,
135 {
136 if deserializer.is_human_readable() {
137 // deserialize_any only works on self-describing (human-readable)
138 // formats
139 deserializer.deserialize_any(LiteMapVisitor::new())
140 } else {
141 deserializer.deserialize_map(LiteMapVisitor::new())
142 }
143 }
144 }
145
146 #[cfg(test)]
147 mod test {
148 use crate::LiteMap;
149 use alloc::borrow::ToOwned;
150 use alloc::string::String;
151 use alloc::vec;
152
153 fn get_simple_map() -> LiteMap<u32, String> {
154 vec![
155 (1, "one".to_owned()),
156 (2, "two".to_owned()),
157 (4, "four".to_owned()),
158 (5, "five".to_owned()),
159 ]
160 .into_iter()
161 .collect()
162 }
163
164 fn get_tuple_map() -> LiteMap<(u32, String), String> {
165 vec![
166 ((1, "en".to_owned()), "one".to_owned()),
167 ((1, "zh".to_owned()), "一".to_owned()),
168 ((2, "en".to_owned()), "two".to_owned()),
169 ((2, "zh".to_owned()), "二".to_owned()),
170 ((4, "en".to_owned()), "four".to_owned()),
171 ((5, "en".to_owned()), "five".to_owned()),
172 ((5, "zh".to_owned()), "五".to_owned()),
173 ((7, "zh".to_owned()), "七".to_owned()),
174 ]
175 .into_iter()
176 .collect()
177 }
178
179 #[test]
180 fn test_roundtrip_json() {
181 let map = get_simple_map();
182 let json = serde_json::to_string(&map).unwrap();
183 assert_eq!(
184 json,
185 "{\"1\":\"one\",\"2\":\"two\",\"4\":\"four\",\"5\":\"five\"}"
186 );
187 let deserialized: LiteMap<u32, String> = serde_json::from_str(&json).unwrap();
188 assert_eq!(map, deserialized);
189
190 let map = get_tuple_map();
191 let json = serde_json::to_string(&map).unwrap();
192 assert_eq!(
193 json,
194 "[[[1,\"en\"],\"one\"],[[1,\"zh\"],\"\"],[[2,\"en\"],\"two\"],\
195 [[2,\"zh\"],\"\"],[[4,\"en\"],\"four\"],[[5,\"en\"],\"five\"],\
196 [[5,\"zh\"],\"\"],[[7,\"zh\"],\"\"]]"
197 );
198 let deserialized: LiteMap<(u32, String), String> = serde_json::from_str(&json).unwrap();
199 assert_eq!(map, deserialized);
200 }
201
202 #[test]
203 fn test_roundtrip_postcard() {
204 let map = get_simple_map();
205 let postcard = postcard::to_stdvec(&map).unwrap();
206 let deserialized: LiteMap<u32, String> = postcard::from_bytes(&postcard).unwrap();
207 assert_eq!(map, deserialized);
208
209 let map = get_tuple_map();
210 let postcard = postcard::to_stdvec(&map).unwrap();
211 let deserialized: LiteMap<(u32, String), String> = postcard::from_bytes(&postcard).unwrap();
212 assert_eq!(map, deserialized);
213 }
214 }