data_stream/
collections.rs

1use crate::{FromStream, ToStream, from_stream, numbers::EndianSettings, to_stream};
2
3use std::{
4    collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, LinkedList, VecDeque},
5    hash::Hash,
6    io::{Read, Result, Write},
7};
8
9/// The encoding for sizes for collections.
10pub enum Size {
11    /// Encodes sizes as `usize`.
12    Usize,
13    /// Encodes sizes as `u8`.
14    U8,
15    /// Encodes sizes as `u16`.
16    U16,
17    /// Encodes sizes as `u32`.
18    U32,
19    /// Encodes sizes as `u64`.
20    U64,
21    /// Encodes sizes as `u128`.
22    U128,
23}
24
25/// The size settings required for reading and writing collections.
26pub trait SizeSettings: EndianSettings {
27    /// The size used by these size settings.
28    const SIZE: Size;
29
30    /// Writes some size using specific settings.
31    fn size_to_stream<W: Write>(size: usize, stream: &mut W) -> Result<()> {
32        use Size::*;
33        match Self::SIZE {
34            U8 => to_stream::<Self, _, _>(&(size as u8), stream),
35            U16 => to_stream::<Self, _, _>(&(size as u16), stream),
36            U32 => to_stream::<Self, _, _>(&(size as u32), stream),
37            U64 => to_stream::<Self, _, _>(&(size as u64), stream),
38            U128 => to_stream::<Self, _, _>(&(size as u128), stream),
39            Usize => to_stream::<Self, _, _>(&size, stream),
40        }
41    }
42
43    /// Reads some size using specific settings.
44    fn size_from_stream<R: Read>(stream: &mut R) -> Result<usize> {
45        use Size::*;
46        Ok(match Self::SIZE {
47            U8 => from_stream::<Self, u8, _>(stream)? as usize,
48            U16 => from_stream::<Self, u16, _>(stream)? as usize,
49            U32 => from_stream::<Self, u32, _>(stream)? as usize,
50            U64 => from_stream::<Self, u64, _>(stream)? as usize,
51            U128 => from_stream::<Self, u128, _>(stream)? as usize,
52            Usize => from_stream::<Self, usize, _>(stream)?,
53        })
54    }
55}
56
57macro_rules! impl_list_collection {
58    ($t: ident) => {
59        impl<T: ToStream<S>, S: SizeSettings> ToStream<S> for $t<T> {
60            fn to_stream<W: Write>(&self, stream: &mut W) -> Result<()> {
61                S::size_to_stream(self.len(), stream)?;
62
63                for element in self {
64                    element.to_stream(stream)?
65                }
66
67                Ok(())
68            }
69        }
70
71        impl<T: FromStream<S>, S: SizeSettings> FromStream<S> for $t<T> {
72            fn from_stream<R: Read>(stream: &mut R) -> Result<Self> {
73                let size = S::size_from_stream(stream)?;
74
75                (0..size)
76                    .map(|_| from_stream(stream))
77                    .collect::<Result<_>>()
78            }
79        }
80    };
81    ($t: ident, $($rest: ident),+) => {
82        impl_list_collection!($t);
83        impl_list_collection!($($rest),+);
84    };
85}
86
87impl_list_collection!(Vec, VecDeque, LinkedList);
88
89macro_rules! impl_set_collection {
90    ($t: ident, $bound: tt $(+ $others: tt )*) => {
91        impl<T: ToStream<S> + $bound $(+ $others)*, S: SizeSettings> ToStream<S> for $t<T> {
92            fn to_stream<W: Write>(&self, stream: &mut W) -> Result<()> {
93                S::size_to_stream(self.len(), stream)?;
94
95                for element in self {
96                    element.to_stream(stream)?
97                }
98
99                Ok(())
100            }
101        }
102
103        impl<T: FromStream<S> + $bound $(+ $others)*, S: SizeSettings> FromStream<S> for $t<T> {
104            fn from_stream<R: Read>(stream: &mut R) -> Result<Self> {
105                let size = S::size_from_stream(stream)?;
106
107                (0..size)
108                    .map(|_| from_stream(stream))
109                    .collect::<Result<_>>()
110            }
111        }
112    };
113}
114
115impl_set_collection!(HashSet, Eq + Hash);
116impl_set_collection!(BTreeSet, Ord);
117impl_set_collection!(BinaryHeap, Ord);
118
119macro_rules! impl_map_collection {
120    ($t: ident, $bound: tt $(+ $others: tt )*) => {
121        impl<K: ToStream<S> + $bound $(+ $others)*, V: ToStream<S>, S: SizeSettings> ToStream<S> for $t<K, V> {
122            fn to_stream<W: Write>(&self, stream: &mut W) -> Result<()> {
123                S::size_to_stream(self.len(), stream)?;
124
125                for (key, value) in self {
126                    key.to_stream(stream)?;
127                    value.to_stream(stream)?;
128                }
129
130                Ok(())
131            }
132        }
133
134        impl<K: FromStream<S> + $bound $(+ $others)*, V: FromStream<S>, S: SizeSettings> FromStream<S> for $t<K, V> {
135            fn from_stream<R: Read>(stream: &mut R) -> Result<Self> {
136                let size = S::size_from_stream(stream)?;
137
138                (0..size)
139                    .map(|_| Ok((from_stream(stream)?, from_stream(stream)?)))
140                    .collect::<Result<_>>()
141            }
142        }
143    };
144}
145
146impl_map_collection!(HashMap, Eq + Hash);
147impl_map_collection!(BTreeMap, Ord);