[go: up one dir, main page]

imbl/
bincode.rs

1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
5use std::hash::{BuildHasher, Hash};
6
7use archery::SharedPointerKind;
8use bincode::de::Decoder;
9use bincode::enc::Encoder;
10use bincode::error::{DecodeError, EncodeError};
11use bincode::{Decode, Encode};
12
13use crate::hashmap::GenericHashMap;
14use crate::hashset::GenericHashSet;
15use crate::ordmap::GenericOrdMap;
16use crate::ordset::GenericOrdSet;
17use crate::vector::GenericVector;
18
19// Set
20
21impl<C, A: Decode<C> + Ord + Clone, P: SharedPointerKind> Decode<C> for GenericOrdSet<A, P> {
22    fn decode<D: Decoder<Context = C>>(decoder: &mut D) -> Result<Self, DecodeError> {
23        let mut output = Self::new();
24        let length: usize = Decode::decode(decoder)?;
25        for _ in 0..length {
26            let item: A = Decode::decode(decoder)?;
27            // Duplicates are silently ignored.
28            output.insert(item);
29        }
30        Ok(output)
31    }
32}
33
34impl<A: Ord + Encode, P: SharedPointerKind> Encode for GenericOrdSet<A, P> {
35    fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), EncodeError> {
36        Encode::encode(&self.len(), encoder)?;
37        for item in self.iter() {
38            Encode::encode(item, encoder)?;
39        }
40        Ok(())
41    }
42}
43
44// Map
45
46impl<C, K: Decode<C> + Ord + Clone, V: Decode<C> + Clone, P: SharedPointerKind> Decode<C>
47    for GenericOrdMap<K, V, P>
48{
49    fn decode<D: Decoder<Context = C>>(decoder: &mut D) -> Result<Self, DecodeError> {
50        let len: usize = Decode::decode(decoder)?;
51        let mut output = Self::new();
52        for _ in 0..len {
53            let (k, v): (K, V) = Decode::decode(decoder)?;
54            // Duplicates are silently ignored
55            output.insert(k, v);
56        }
57        Ok(output)
58    }
59}
60
61impl<K: Encode + Ord + Clone, V: Encode + Clone, P: SharedPointerKind> Encode
62    for GenericOrdMap<K, V, P>
63{
64    fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), EncodeError> {
65        Encode::encode(&self.len(), encoder)?;
66        for (k, v) in self.iter() {
67            Encode::encode(&(k, v), encoder)?;
68        }
69        Ok(())
70    }
71}
72
73// HashMap
74
75impl<C, K, V, S, P: SharedPointerKind> Decode<C> for GenericHashMap<K, V, S, P>
76where
77    K: Decode<C> + Hash + Eq + Clone,
78    V: Decode<C> + Clone,
79    S: BuildHasher + Default + Clone,
80    P: SharedPointerKind,
81{
82    fn decode<D: Decoder<Context = C>>(decoder: &mut D) -> Result<Self, DecodeError> {
83        let len: usize = Decode::decode(decoder)?;
84        let mut output = Self::new();
85        for _ in 0..len {
86            let (k, v): (K, V) = Decode::decode(decoder)?;
87            // Duplicates are silently ignored
88            output.insert(k, v);
89        }
90        Ok(output)
91    }
92}
93
94impl<K, V, S, P> Encode for GenericHashMap<K, V, S, P>
95where
96    K: Encode + Hash + Eq,
97    V: Encode,
98    S: BuildHasher + Default,
99    P: SharedPointerKind,
100{
101    fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), EncodeError> {
102        Encode::encode(&self.len(), encoder)?;
103        for (k, v) in self.iter() {
104            Encode::encode(&(k, v), encoder)?;
105        }
106        Ok(())
107    }
108}
109
110// HashSet
111
112impl<C, A, S, P> Decode<C> for GenericHashSet<A, S, P>
113where
114    A: Decode<C> + Hash + Eq + Clone,
115    S: BuildHasher + Default + Clone,
116    P: SharedPointerKind,
117{
118    fn decode<D: Decoder<Context = C>>(decoder: &mut D) -> Result<Self, DecodeError> {
119        let mut output = Self::new();
120        let length: usize = Decode::decode(decoder)?;
121        for _ in 0..length {
122            let item: A = Decode::decode(decoder)?;
123            // Duplicates are silently ignored.
124            output.insert(item);
125        }
126        Ok(output)
127    }
128}
129
130impl<A: Encode + Hash + Eq, S: BuildHasher + Default, P: SharedPointerKind> Encode
131    for GenericHashSet<A, S, P>
132{
133    fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), EncodeError> {
134        Encode::encode(&self.len(), encoder)?;
135        for item in self.iter() {
136            Encode::encode(item, encoder)?;
137        }
138        Ok(())
139    }
140}
141
142// Vector
143
144impl<C, A: Clone + Decode<C>, P: SharedPointerKind> Decode<C> for GenericVector<A, P> {
145    fn decode<D: Decoder<Context = C>>(decoder: &mut D) -> Result<Self, DecodeError> {
146        let mut output = Self::new();
147        let length: usize = Decode::decode(decoder)?;
148        for _ in 0..length {
149            let item: A = Decode::decode(decoder)?;
150            output.push_back(item);
151        }
152        Ok(output)
153    }
154}
155
156impl<A: Encode, P: SharedPointerKind> Encode for GenericVector<A, P> {
157    fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), EncodeError> {
158        Encode::encode(&self.len(), encoder)?;
159        for item in self.iter() {
160            Encode::encode(item, encoder)?;
161        }
162        Ok(())
163    }
164}
165
166// Tests
167
168#[cfg(test)]
169mod test {
170    use crate::{
171        proptest::{hash_map, hash_set, ord_map, ord_set, vector},
172        HashMap, HashSet, OrdMap, OrdSet, Vector,
173    };
174    use bincode::{decode_from_slice, encode_to_vec};
175    use proptest::num::i32;
176    use proptest::proptest;
177
178    proptest! {
179        #[cfg_attr(miri, ignore)]
180        #[test]
181        fn encode_and_decode_ordset(ref v in ord_set(i32::ANY, 0..100)) {
182            let config =  bincode::config::standard();
183            assert_eq!(v,
184                &decode_from_slice::<OrdSet::<i32>, _>(&encode_to_vec(v, config).unwrap(), config).unwrap().0
185            )
186        }
187
188        #[cfg_attr(miri, ignore)]
189        #[test]
190        fn ordset_and_btree_set_encoded_the_same_way(ref bts in ::proptest::collection::btree_set(i32::ANY, 0..100)) {
191            let s = OrdSet::from(bts);
192            let config =  bincode::config::standard();
193            assert_eq!(encode_to_vec(bts, config).unwrap(), encode_to_vec(s, config).unwrap());
194        }
195
196        #[cfg_attr(miri, ignore)]
197        #[test]
198        fn encode_and_decode_ordmap(ref v in ord_map(i32::ANY, i32::ANY, 0..100)) {
199            let config =  bincode::config::standard();
200            assert_eq!(v,
201                &decode_from_slice::<OrdMap::<i32, i32>, _>(&encode_to_vec(v, config).unwrap(), config).unwrap().0
202            )
203        }
204
205        #[cfg_attr(miri, ignore)]
206        #[test]
207        fn ordmap_and_btree_map_encoded_the_same_way(ref btm in ::proptest::collection::btree_map(i32::ANY, i32::ANY, 0..100)) {
208            let s: OrdMap<i32, i32>  = OrdMap::from(btm);
209            let config =  bincode::config::standard();
210            assert_eq!(encode_to_vec(btm, config).unwrap(), encode_to_vec(s, config).unwrap());
211        }
212
213        #[cfg_attr(miri, ignore)]
214        #[test]
215        fn encode_and_decode_hashmap(ref v in hash_map(i32::ANY, i32::ANY, 0..100)) {
216            let config =  bincode::config::standard();
217            assert_eq!(v,
218                &decode_from_slice::<HashMap::<i32, i32>, _>(&encode_to_vec(v, config).unwrap(), config).unwrap().0
219            )
220        }
221
222        #[cfg_attr(miri, ignore)]
223        #[test]
224        fn encoding_std_hashmap_and_decoding_as_imbl_hashmap_is_same_as_converting(
225            ref std_hm in ::proptest::collection::hash_map(i32::ANY, i32::ANY, 0..100)
226        ) {
227            // In fact, std's HashMap and imbl's HashMap are _not_ encoded the same since the order of the items can differ.
228            let config =  bincode::config::standard();
229            let encoded = encode_to_vec(&std_hm, config).unwrap();
230            let converted = HashMap::from(std_hm);
231            let decoded : HashMap<i32, i32> = decode_from_slice(&encoded, config).unwrap().0;
232            assert_eq!(decoded, converted);
233        }
234
235        #[cfg_attr(miri, ignore)]
236        #[test]
237        fn encode_and_decode_hashset(ref v in hash_set(i32::ANY, 0..100)) {
238            let config =  bincode::config::standard();
239            assert_eq!(v,
240                &decode_from_slice::<HashSet::<i32>, _>(&encode_to_vec(v, config).unwrap(), config).unwrap().0
241            )
242        }
243
244        #[cfg_attr(miri, ignore)]
245        #[cfg_attr(miri, ignore)]
246        #[test]
247        fn encoding_std_hashset_and_decoding_as_imbl_hashset_is_same_as_converting(
248            ref std_hs in ::proptest::collection::hash_set(i32::ANY, 0..100)
249        ) {
250            // In fact, std's HashSet and imbl's HashSet are _not_ encoded the same since the order of the items can differ.
251            let config =  bincode::config::standard();
252            let encoded = encode_to_vec(&std_hs, config).unwrap();
253            let converted = HashSet::from(std_hs);
254            let decoded : HashSet<i32> = decode_from_slice(&encoded, config).unwrap().0;
255            assert_eq!(decoded, converted);
256        }
257
258        #[test]
259        fn encode_and_decode_vector(ref v in vector(i32::ANY, 0..100)) {
260            let config =  bincode::config::standard();
261            assert_eq!(v,
262                &decode_from_slice::<Vector::<i32>, _>(&encode_to_vec(v, config).unwrap(), config).unwrap().0
263            )
264        }
265
266        #[cfg_attr(miri, ignore)]
267        #[test]
268        fn vector_and_vec_encoded_the_same_way(ref vec in ::proptest::collection::vec(i32::ANY, 0..100)) {
269            let vector = Vector::from(vec);
270            let config =  bincode::config::standard();
271            assert_eq!(encode_to_vec(vec, config).unwrap(), encode_to_vec(vector, config).unwrap());
272        }
273    }
274}