snops_common/format/
impl_collections.rs

1use std::{
2    collections::{HashMap, HashSet},
3    io::{Read, Write},
4};
5
6use indexmap::{IndexMap, IndexSet};
7
8use super::{
9    packed_int::PackedUint, DataFormat, DataFormatReader, DataFormatWriter, DataReadError,
10    DataWriteError,
11};
12
13impl<T: DataFormat + Default + Copy, const N: usize> DataFormat for [T; N] {
14    type Header = T::Header;
15    const LATEST_HEADER: Self::Header = T::LATEST_HEADER;
16
17    fn write_data<W: Write>(&self, writer: &mut W) -> Result<usize, DataWriteError> {
18        let mut written = 0;
19        for item in self.iter() {
20            written += item.write_data(writer)?;
21        }
22        Ok(written)
23    }
24
25    fn read_data<R: Read>(reader: &mut R, header: &Self::Header) -> Result<Self, DataReadError> {
26        let mut data = [T::default(); N];
27        for item in data.iter_mut() {
28            *item = reader.read_data(header)?;
29        }
30        Ok(data)
31    }
32}
33
34impl<T: DataFormat> DataFormat for Vec<T> {
35    type Header = T::Header;
36    const LATEST_HEADER: Self::Header = T::LATEST_HEADER;
37
38    fn write_data<W: Write>(&self, writer: &mut W) -> Result<usize, DataWriteError> {
39        let mut written = PackedUint::from(self.len()).write_data(writer)?;
40        for item in self.iter() {
41            written += writer.write_data(item)?;
42        }
43        Ok(written)
44    }
45
46    fn read_data<R: Read>(reader: &mut R, header: &Self::Header) -> Result<Self, DataReadError> {
47        let len = usize::from(PackedUint::read_data(reader, &())?);
48        let mut data = Vec::with_capacity(len);
49        for _ in 0..len {
50            data.push(reader.read_data(header)?);
51        }
52        Ok(data)
53    }
54}
55
56macro_rules! impl_set {
57    ($set_ty:ident) => {
58        impl<T> DataFormat for $set_ty<T>
59        where
60            T: DataFormat + Eq + std::hash::Hash,
61        {
62            type Header = T::Header;
63            const LATEST_HEADER: Self::Header = T::LATEST_HEADER;
64
65            fn write_data<W: Write>(&self, writer: &mut W) -> Result<usize, DataWriteError> {
66                let mut written = PackedUint::from(self.len()).write_data(writer)?;
67                for item in self.iter() {
68                    written += writer.write_data(item)?;
69                }
70                Ok(written)
71            }
72
73            fn read_data<R: Read>(
74                reader: &mut R,
75                header: &Self::Header,
76            ) -> Result<Self, DataReadError> {
77                let len = usize::from(PackedUint::read_data(reader, &())?);
78                let mut data = $set_ty::with_capacity(len);
79                for _ in 0..len {
80                    data.insert(reader.read_data(header)?);
81                }
82                Ok(data)
83            }
84        }
85    };
86}
87
88impl_set!(HashSet);
89impl_set!(IndexSet);
90
91macro_rules! impl_map {
92    ($map_ty:ident) => {
93        impl<K, V> DataFormat for $map_ty<K, V>
94        where
95            K: DataFormat + Eq + std::hash::Hash,
96            V: DataFormat,
97        {
98            type Header = (K::Header, V::Header);
99            const LATEST_HEADER: Self::Header = (K::LATEST_HEADER, V::LATEST_HEADER);
100
101            fn write_data<W: Write>(&self, writer: &mut W) -> Result<usize, DataWriteError> {
102                let mut written = PackedUint::from(self.len()).write_data(writer)?;
103                for (key, value) in self.iter() {
104                    written += writer.write_data(key)?;
105                    written += writer.write_data(value)?;
106                }
107                Ok(written)
108            }
109
110            fn read_data<R: Read>(
111                reader: &mut R,
112                (key_header, value_header): &Self::Header,
113            ) -> Result<Self, DataReadError> {
114                let len = usize::from(PackedUint::read_data(reader, &())?);
115                let mut data = $map_ty::with_capacity(len);
116                for _ in 0..len {
117                    data.insert(
118                        reader.read_data(key_header)?,
119                        reader.read_data(value_header)?,
120                    );
121                }
122                Ok(data)
123            }
124        }
125    };
126}
127
128impl_map!(HashMap);
129impl_map!(IndexMap);
130
131#[cfg(test)]
132#[rustfmt::skip]
133mod test {
134    use crate::format::DataFormat;
135
136    macro_rules! case {
137        ($name:ident, $ty:ty, $a:expr, $b:expr) => {
138            #[test]
139            fn $name() {
140                let mut data = Vec::new();
141                let value: $ty = $a;
142                value.write_data(&mut data).unwrap();
143                // we're not doing an assert here because
144                // the order of the elements in the collection is not guaranteed
145                // assert_eq!(data, &$b);
146
147                let mut reader = &data[..];
148                let read_value = <$ty>::read_data(&mut reader, &<$ty as DataFormat>::LATEST_HEADER).unwrap();
149                assert_eq!(read_value, value);
150
151            }
152
153        };
154    }
155
156    case!(test_vec_u8, Vec<u8>, vec![1, 2, 3], [
157        1, 3,
158        1, 2, 3
159    ]);
160    case!(test_vec_u16, Vec<u16>, vec![1, 2, 3], [
161        1, 3,
162        1, 0,
163        2, 0,
164        3, 0
165    ]);
166
167    case!(test_hashset_u8, std::collections::HashSet<u8>, [1, 2, 3].into_iter().collect(), [
168        1, 3,
169        1, 2, 3
170    ]);
171    case!(test_hashset_u16, std::collections::HashSet<u16>, [1, 2, 3].into_iter().collect(), [
172        1, 3,
173        1, 0,
174        2, 0,
175        3, 0
176    ]);
177
178    case!(test_hashmap_u8_u16, std::collections::HashMap<u8, u16>, [(1, 2), (3, 4)].into_iter().collect(), [
179        1, 4,
180        1, 0,
181        2, 0,
182        3, 0,
183        4, 0
184    ]);
185}