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 ).
8 use core
::marker
::PhantomData
;
9 use serde
::de
::{MapAccess, SeqAccess, Visitor}
;
10 use serde
::{Deserialize, Deserializer}
;
12 #[cfg(feature = "serde")]
13 use serde
::{ser::SerializeMap, Serialize, Serializer}
;
15 #[cfg(feature = "serde")]
16 impl<K
, V
, R
> Serialize
for LiteMap
<K
, V
, R
>
20 R
: Store
<K
, V
> + Serialize
,
22 fn serialize
<S
>(&self, serializer
: S
) -> Result
<S
::Ok
, S
::Error
>
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
);
34 // continue to regular serialization
37 let mut map
= serializer
.serialize_map(Some(self.len()))?
;
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
)?
;
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
>>,
55 impl<K
, V
, R
> LiteMapVisitor
<K
, V
, R
> {
63 impl<'de
, K
, V
, R
> Visitor
<'de
> for LiteMapVisitor
<K
, V
, R
>
65 K
: Deserialize
<'de
> + Ord
,
69 type Value
= LiteMap
<K
, V
, R
>;
71 fn expecting(&self, formatter
: &mut fmt
::Formatter
) -> fmt
::Result
{
72 formatter
.write_str("a map produced by LiteMap")
75 fn visit_seq
<S
>(self, mut access
: S
) -> Result
<Self::Value
, S
::Error
>
79 let mut map
= LiteMap
::with_capacity(access
.size_hint().unwrap_or(0));
81 // While there are entries remaining in the input, add them
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
);
100 fn visit_map
<M
>(self, mut access
: M
) -> Result
<Self::Value
, M
::Error
>
104 let mut map
= LiteMap
::with_capacity(access
.size_hint().unwrap_or(0));
106 // While there are entries remaining in the input, add them
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
);
126 impl<'de
, K
, V
, R
> Deserialize
<'de
> for LiteMap
<K
, V
, R
>
128 K
: Ord
+ Deserialize
<'de
>,
132 fn deserialize
<D
>(deserializer
: D
) -> Result
<Self, D
::Error
>
134 D
: Deserializer
<'de
>,
136 if deserializer
.is_human_readable() {
137 // deserialize_any only works on self-describing (human-readable)
139 deserializer
.deserialize_any(LiteMapVisitor
::new())
141 deserializer
.deserialize_map(LiteMapVisitor
::new())
149 use alloc
::borrow
::ToOwned
;
150 use alloc
::string
::String
;
153 fn get_simple_map() -> LiteMap
<u32, String
> {
155 (1, "one".to_owned()),
156 (2, "two".to_owned()),
157 (4, "four".to_owned()),
158 (5, "five".to_owned()),
164 fn get_tuple_map() -> LiteMap
<(u32, String
), String
> {
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()),
180 fn test_roundtrip_json() {
181 let map
= get_simple_map();
182 let json
= serde_json
::to_string(&map
).unwrap();
185 "{\"1\":\"one\",\"2\":\"two\",\"4\":\"four\",\"5\":\"five\"}"
187 let deserialized
: LiteMap
<u32, String
> = serde_json
::from_str(&json
).unwrap();
188 assert_eq
!(map
, deserialized
);
190 let map
= get_tuple_map();
191 let json
= serde_json
::to_string(&map
).unwrap();
194 "[[[1,\"en\"],\"one\"],[[1,\"zh\"],\"一\"],[[2,\"en\"],\"two\"],\
195 [[2,\"zh\"],\"二\"],[[4,\"en\"],\"four\"],[[5,\"en\"],\"five\"],\
196 [[5,\"zh\"],\"五\"],[[7,\"zh\"],\"七\"]]"
198 let deserialized
: LiteMap
<(u32, String
), String
> = serde_json
::from_str(&json
).unwrap();
199 assert_eq
!(map
, deserialized
);
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
);
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
);