simd_json_derive/impls/
collections.rs

1use std::{
2    collections::{BTreeMap, HashMap},
3    ops::Range,
4};
5
6#[cfg(feature = "heap-array")]
7use heap_array::HeapArray;
8
9use crate::{de, Deserialize, Result, Serialize, SerializeAsKey, Tape, Write};
10use std::collections;
11use std::io;
12
13macro_rules! vec_like {
14    ($t:ty) => {
15        impl<T> Serialize for $t
16        where
17            T: Serialize,
18        {
19            #[inline]
20            fn json_write<W>(&self, writer: &mut W) -> Result
21            where
22                W: Write,
23            {
24                let mut i = self.iter();
25                if let Some(first) = i.next() {
26                    writer.write_all(b"[")?;
27                    first.json_write(writer)?;
28                    for e in i {
29                        writer.write_all(b",")?;
30                        e.json_write(writer)?;
31                    }
32                    writer.write_all(b"]")
33                } else {
34                    writer.write_all(b"[]")
35                }
36            }
37        }
38    };
39}
40
41vec_like!(Vec<T>);
42impl<'input, T> Deserialize<'input> for Vec<T>
43where
44    T: Deserialize<'input>,
45{
46    #[inline]
47    fn from_tape(tape: &mut Tape<'input>) -> de::Result<Self>
48    where
49        Self: Sized + 'input,
50    {
51        let Some(simd_json::Node::Array { len, .. }) = tape.next() else {
52            return Err(de::Error::expected_array());
53        };
54        let mut res = Vec::with_capacity(len);
55        for _ in 0..len {
56            let t = T::from_tape(tape)?;
57            res.push(t);
58        }
59        Ok(res)
60    }
61}
62
63vec_like!([T]);
64vec_like!(collections::VecDeque<T>);
65impl<'input, T> Deserialize<'input> for collections::VecDeque<T>
66where
67    T: Deserialize<'input>,
68{
69    #[inline]
70    fn from_tape(tape: &mut Tape<'input>) -> de::Result<Self>
71    where
72        Self: Sized + 'input,
73    {
74        if let Some(simd_json::Node::Array { len, .. }) = tape.next() {
75            let mut v = collections::VecDeque::new();
76            for _ in 0..len {
77                v.push_back(T::from_tape(tape)?);
78            }
79            Ok(v)
80        } else {
81            Err(de::Error::expected_array())
82        }
83    }
84}
85vec_like!(collections::BinaryHeap<T>);
86impl<'input, T> Deserialize<'input> for collections::BinaryHeap<T>
87where
88    T: Deserialize<'input> + Ord,
89{
90    #[inline]
91    fn from_tape(tape: &mut Tape<'input>) -> de::Result<Self>
92    where
93        Self: Sized + 'input,
94    {
95        if let Some(simd_json::Node::Array { len, .. }) = tape.next() {
96            let mut v = collections::BinaryHeap::new();
97            for _ in 0..len {
98                v.push(T::from_tape(tape)?);
99            }
100            Ok(v)
101        } else {
102            Err(de::Error::expected_array())
103        }
104    }
105}
106vec_like!(collections::BTreeSet<T>);
107impl<'input, T> Deserialize<'input> for collections::BTreeSet<T>
108where
109    T: Deserialize<'input> + Ord,
110{
111    #[inline]
112    fn from_tape(tape: &mut Tape<'input>) -> de::Result<Self>
113    where
114        Self: Sized + 'input,
115    {
116        if let Some(simd_json::Node::Array { len, .. }) = tape.next() {
117            let mut v = collections::BTreeSet::new();
118            for _ in 0..len {
119                v.insert(T::from_tape(tape)?);
120            }
121            Ok(v)
122        } else {
123            Err(de::Error::expected_array())
124        }
125    }
126}
127vec_like!(collections::LinkedList<T>);
128impl<'input, T> Deserialize<'input> for collections::LinkedList<T>
129where
130    T: Deserialize<'input> + Ord,
131{
132    #[inline]
133    fn from_tape(tape: &mut Tape<'input>) -> de::Result<Self>
134    where
135        Self: Sized + 'input,
136    {
137        if let Some(simd_json::Node::Array { len, .. }) = tape.next() {
138            let mut v = collections::LinkedList::new();
139            for _ in 0..len {
140                v.push_back(T::from_tape(tape)?);
141            }
142            Ok(v)
143        } else {
144            Err(de::Error::expected_array())
145        }
146    }
147}
148impl<T, H> Serialize for collections::HashSet<T, H>
149where
150    T: Serialize,
151    H: std::hash::BuildHasher,
152{
153    #[inline]
154    fn json_write<W>(&self, writer: &mut W) -> io::Result<()>
155    where
156        W: Write,
157    {
158        let mut i = self.iter();
159        if let Some(first) = i.next() {
160            writer.write_all(b"[")?;
161            first.json_write(writer)?;
162            for e in i {
163                writer.write_all(b",")?;
164                e.json_write(writer)?;
165            }
166            writer.write_all(b"]")
167        } else {
168            writer.write_all(b"[]")
169        }
170    }
171}
172impl<'input, T, H> Deserialize<'input> for collections::HashSet<T, H>
173where
174    T: Deserialize<'input> + std::hash::Hash + Eq,
175    H: std::hash::BuildHasher + Default,
176{
177    #[inline]
178    fn from_tape(tape: &mut Tape<'input>) -> de::Result<Self>
179    where
180        Self: Sized + 'input,
181    {
182        if let Some(simd_json::Node::Array { len, .. }) = tape.next() {
183            let mut v = collections::HashSet::with_capacity_and_hasher(len, H::default());
184            for _ in 0..len {
185                v.insert(T::from_tape(tape)?);
186            }
187            Ok(v)
188        } else {
189            Err(de::Error::expected_array())
190        }
191    }
192}
193
194macro_rules! ser_map_like {
195    ($name:ident <$($generic:ident: $constraint:tt),*>) => {
196        impl<$($generic: $constraint),*> Serialize for $name<$($generic),*> {
197            #[inline]
198            fn json_write<W>(&self, writer: &mut W) -> Result
199            where
200                W: Write,
201            {
202                let mut i = self.iter();
203                if let Some((k, v)) = i.next() {
204                    writer.write_all(b"{")?;
205                    k.json_write(writer)?;
206                    writer.write_all(b":")?;
207                    v.json_write(writer)?;
208                    for (k, v) in i {
209                        writer.write_all(b",")?;
210                        k.json_write(writer)?;
211                        writer.write_all(b":")?;
212                        v.json_write(writer)?;
213                    }
214                    writer.write_all(b"}")
215                } else {
216                    writer.write_all(b"{}")
217                }
218            }
219        }
220    };
221}
222
223ser_map_like!(HashMap<K: SerializeAsKey, V: Serialize, H: (std::hash::BuildHasher)>);
224ser_map_like!(BTreeMap<K: SerializeAsKey, V: Serialize>);
225
226impl<'input, K, V, H> Deserialize<'input> for HashMap<K, V, H>
227where
228    K: Deserialize<'input> + std::hash::Hash + Eq,
229    V: Deserialize<'input>,
230    H: std::hash::BuildHasher + Default,
231{
232    #[inline]
233    fn from_tape(tape: &mut Tape<'input>) -> de::Result<Self>
234    where
235        Self: Sized + 'input,
236    {
237        if let Some(simd_json::Node::Object { len, .. }) = tape.next() {
238            let mut v = collections::HashMap::with_capacity_and_hasher(len, H::default());
239            for _ in 0..len {
240                let k = K::from_tape(tape)?;
241                v.insert(k, V::from_tape(tape)?);
242            }
243            Ok(v)
244        } else {
245            Err(de::Error::expected_map())
246        }
247    }
248}
249
250impl<'input, K, V> Deserialize<'input> for BTreeMap<K, V>
251where
252    K: Deserialize<'input> + Ord,
253    V: Deserialize<'input>,
254{
255    #[inline]
256    fn from_tape(tape: &mut Tape<'input>) -> de::Result<Self>
257    where
258        Self: Sized + 'input,
259    {
260        if let Some(simd_json::Node::Object { len, .. }) = tape.next() {
261            let mut v = collections::BTreeMap::new();
262            for _ in 0..len {
263                let k = K::from_tape(tape)?;
264                v.insert(k, V::from_tape(tape)?);
265            }
266            Ok(v)
267        } else {
268            Err(de::Error::expected_map())
269        }
270    }
271}
272
273impl<T> Serialize for Range<T>
274where
275    T: Serialize,
276{
277    #[inline]
278    fn json_write<W>(&self, writer: &mut W) -> Result
279    where
280        W: Write,
281    {
282        writer.write_all(b"{\"start\":")?;
283        self.start.json_write(writer)?;
284        writer.write_all(b",\"end\":")?;
285        self.end.json_write(writer)?;
286        writer.write_all(b"}")
287    }
288}
289
290impl<'input, T> Deserialize<'input> for Range<T>
291where
292    T: Deserialize<'input>,
293{
294    #[inline]
295    fn from_tape(tape: &mut Tape<'input>) -> de::Result<Self>
296    where
297        Self: Sized + 'input,
298    {
299        if let Some(simd_json::Node::Object { len: 2, .. }) = tape.next() {
300            match tape.next() {
301                Some(simd_json::Node::String("start")) => {
302                    let start = Deserialize::from_tape(tape)?;
303                    if let Some(simd_json::Node::String("end")) = tape.next() {
304                        let end = Deserialize::from_tape(tape)?;
305                        Ok(start..end)
306                    } else {
307                        Err(de::Error::expected_string())
308                    }
309                }
310                Some(simd_json::Node::String("end")) => {
311                    let end = Deserialize::from_tape(tape)?;
312                    if let Some(simd_json::Node::String("start")) = tape.next() {
313                        let start = Deserialize::from_tape(tape)?;
314                        Ok(start..end)
315                    } else {
316                        Err(de::Error::expected_string())
317                    }
318                }
319                _ => Err(de::Error::expected_string()),
320            }
321        } else {
322            Err(de::Error::expected_map())
323        }
324    }
325}
326
327#[cfg(feature = "heap-array")]
328vec_like!(HeapArray<T>);
329
330#[cfg(feature = "heap-array")]
331impl<'input, T: Deserialize<'input>> Deserialize<'input> for HeapArray<T> {
332    fn from_tape(tape: &mut Tape<'input>) -> de::Result<Self>
333    where
334        Self: Sized + 'input,
335    {
336        if let Some(simd_json::Node::Array { len, .. }) = tape.next() {
337            HeapArray::try_from_fn(len, |_| T::from_tape(tape))
338        } else {
339            Err(de::Error::expected_array())
340        }
341    }
342}
343
344#[cfg(test)]
345mod test {
346    use std::ops::Range;
347
348    use crate::*;
349    #[test]
350    fn vec() {
351        let mut v: Vec<u8> = Vec::new();
352        assert_eq!(v.json_string().expect("invalid data"), "[]");
353
354        v.push(1);
355        let mut s = v.json_string().expect("invalid data");
356        assert_eq!(s, "[1]");
357        let s: Vec<u8> = unsafe { Vec::from_str(s.as_mut_str()) }.expect("invalid data");
358        assert_eq!(s, v);
359
360        v.push(2);
361        let mut s = v.json_string().expect("invalid test data");
362        assert_eq!(s, "[1,2]");
363        let s: Vec<u8> = unsafe { Vec::from_str(s.as_mut_str()) }.expect("invalid test data");
364        assert_eq!(s, v);
365
366        v.push(3);
367        let mut s = v.json_string().expect("invalid test data");
368        assert_eq!(s, "[1,2,3]");
369        let s: Vec<u8> = unsafe { Vec::from_str(s.as_mut_str()) }.expect("invalid test data");
370        assert_eq!(s, v);
371    }
372
373    #[test]
374    fn range() {
375        let r = 1..42;
376        let mut v = r.json_vec().expect("invalid test data");
377        assert_eq!(br#"{"start":1,"end":42}"#, v.as_slice());
378        let r1 = Range::from_slice(v.as_mut_slice()).expect("invalid test data");
379        assert_eq!(r, r1);
380    }
381}