wagyu_model/utilities/
bytes.rs1use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
2use std::io::{Read, Result as IoResult, Write};
3
4pub trait ToBytes {
5 fn write<W: Write>(&self, writer: W) -> IoResult<()>;
7}
8
9pub trait FromBytes: Sized {
10 fn read<R: Read>(reader: R) -> IoResult<Self>;
12}
13
14macro_rules! array_bytes {
15 ($N:expr) => {
16 impl ToBytes for [u8; $N] {
17 #[inline]
18 fn write<W: Write>(&self, mut writer: W) -> IoResult<()> {
19 writer.write_all(self)
20 }
21 }
22
23 impl FromBytes for [u8; $N] {
24 #[inline]
25 fn read<R: Read>(mut reader: R) -> IoResult<Self> {
26 let mut arr = [0u8; $N];
27 reader.read_exact(&mut arr)?;
28 Ok(arr)
29 }
30 }
31
32 impl ToBytes for [u16; $N] {
33 #[inline]
34 fn write<W: Write>(&self, mut writer: W) -> IoResult<()> {
35 for num in self {
36 writer.write_u16::<LittleEndian>(*num)?;
37 }
38 Ok(())
39 }
40 }
41
42 impl FromBytes for [u16; $N] {
43 #[inline]
44 fn read<R: Read>(mut reader: R) -> IoResult<Self> {
45 let mut res = [0u16; $N];
46 reader.read_u16_into::<LittleEndian>(&mut res)?;
47 Ok(res)
48 }
49 }
50
51 impl ToBytes for [u32; $N] {
52 #[inline]
53 fn write<W: Write>(&self, mut writer: W) -> IoResult<()> {
54 for num in self {
55 writer.write_u32::<LittleEndian>(*num)?;
56 }
57 Ok(())
58 }
59 }
60
61 impl FromBytes for [u32; $N] {
62 #[inline]
63 fn read<R: Read>(mut reader: R) -> IoResult<Self> {
64 let mut res = [0u32; $N];
65 reader.read_u32_into::<LittleEndian>(&mut res)?;
66 Ok(res)
67 }
68 }
69
70 impl ToBytes for [u64; $N] {
71 #[inline]
72 fn write<W: Write>(&self, mut writer: W) -> IoResult<()> {
73 for num in self {
74 writer.write_u64::<LittleEndian>(*num)?;
75 }
76 Ok(())
77 }
78 }
79
80 impl FromBytes for [u64; $N] {
81 #[inline]
82 fn read<R: Read>(mut reader: R) -> IoResult<Self> {
83 let mut res = [0u64; $N];
84 reader.read_u64_into::<LittleEndian>(&mut res)?;
85 Ok(res)
86 }
87 }
88 };
89}
90
91array_bytes!(0);
92array_bytes!(1);
93array_bytes!(2);
94array_bytes!(3);
95array_bytes!(4);
96array_bytes!(5);
97array_bytes!(6);
98array_bytes!(7);
99array_bytes!(8);
100array_bytes!(9);
101array_bytes!(10);
102array_bytes!(11);
103array_bytes!(12);
104array_bytes!(13);
105array_bytes!(14);
106array_bytes!(15);
107array_bytes!(16);
108array_bytes!(17);
109array_bytes!(18);
110array_bytes!(19);
111array_bytes!(20);
112array_bytes!(21);
113array_bytes!(22);
114array_bytes!(23);
115array_bytes!(24);
116array_bytes!(25);
117array_bytes!(26);
118array_bytes!(27);
119array_bytes!(28);
120array_bytes!(29);
121array_bytes!(30);
122array_bytes!(31);
123array_bytes!(32);
124
125#[macro_export]
129macro_rules! to_bytes {
130 ($($x:expr),*) => ({
131 use std::io::Cursor;
132 let mut buf = Cursor::new(vec![]);
133 {$crate::push_to_vec!(buf, $($x),*)}.map(|_| buf.into_inner())
134 });
135}
136
137#[macro_export]
138macro_rules! push_to_vec {
139 ($buf:expr, $y:expr, $($x:expr),*) => ({
140 {
141 ToBytes::write(&$y, &mut $buf)
142 }.and({$crate::push_to_vec!($buf, $($x),*)})
143 });
144
145 ($buf:expr, $x:expr) => ({
146 ToBytes::write(&$x, &mut $buf)
147 })
148}
149
150impl ToBytes for u8 {
151 #[inline]
152 fn write<W: Write>(&self, mut writer: W) -> IoResult<()> {
153 writer.write_u8(*self)
154 }
155}
156
157impl FromBytes for u8 {
158 #[inline]
159 fn read<R: Read>(mut reader: R) -> IoResult<Self> {
160 reader.read_u8()
161 }
162}
163
164impl ToBytes for u16 {
165 #[inline]
166 fn write<W: Write>(&self, mut writer: W) -> IoResult<()> {
167 writer.write_u16::<LittleEndian>(*self)
168 }
169}
170
171impl FromBytes for u16 {
172 #[inline]
173 fn read<R: Read>(mut reader: R) -> IoResult<Self> {
174 reader.read_u16::<LittleEndian>()
175 }
176}
177
178impl ToBytes for u32 {
179 #[inline]
180 fn write<W: Write>(&self, mut writer: W) -> IoResult<()> {
181 writer.write_u32::<LittleEndian>(*self)
182 }
183}
184
185impl FromBytes for u32 {
186 #[inline]
187 fn read<R: Read>(mut reader: R) -> IoResult<Self> {
188 reader.read_u32::<LittleEndian>()
189 }
190}
191
192impl ToBytes for u64 {
193 #[inline]
194 fn write<W: Write>(&self, mut writer: W) -> IoResult<()> {
195 writer.write_u64::<LittleEndian>(*self)
196 }
197}
198
199impl FromBytes for u64 {
200 #[inline]
201 fn read<R: Read>(mut reader: R) -> IoResult<Self> {
202 reader.read_u64::<LittleEndian>()
203 }
204}
205
206impl ToBytes for () {
207 #[inline]
208 fn write<W: Write>(&self, _writer: W) -> IoResult<()> {
209 Ok(())
210 }
211}
212
213impl FromBytes for () {
214 #[inline]
215 fn read<R: Read>(_bytes: R) -> IoResult<Self> {
216 Ok(())
217 }
218}
219
220impl ToBytes for bool {
221 #[inline]
222 fn write<W: Write>(&self, writer: W) -> IoResult<()> {
223 u8::write(&(*self as u8), writer)
224 }
225}
226
227impl FromBytes for bool {
228 #[inline]
229 fn read<R: Read>(reader: R) -> IoResult<Self> {
230 match u8::read(reader) {
231 Ok(0) => Ok(false),
232 Ok(1) => Ok(true),
233 Ok(_) => Err(::std::io::ErrorKind::Other.into()),
234 Err(err) => Err(err),
235 }
236 }
237}
238
239impl<T: ToBytes> ToBytes for [T] {
240 #[inline]
241 fn write<W: Write>(&self, mut writer: W) -> IoResult<()> {
242 for item in self {
243 item.write(&mut writer)?;
244 }
245 Ok(())
246 }
247}
248
249impl<T: ToBytes> ToBytes for Vec<T> {
250 #[inline]
251 fn write<W: Write>(&self, mut writer: W) -> IoResult<()> {
252 for item in self {
253 item.write(&mut writer)?;
254 }
255 Ok(())
256 }
257}
258
259impl<'a, T: 'a + ToBytes> ToBytes for &'a [T] {
260 #[inline]
261 fn write<W: Write>(&self, mut writer: W) -> IoResult<()> {
262 for item in *self {
263 item.write(&mut writer)?;
264 }
265 Ok(())
266 }
267}
268
269impl<'a, T: 'a + ToBytes> ToBytes for &'a T {
270 #[inline]
271 fn write<W: Write>(&self, mut writer: W) -> IoResult<()> {
272 (*self).write(&mut writer)
273 }
274}
275
276impl FromBytes for Vec<u8> {
277 #[inline]
278 fn read<R: Read>(mut reader: R) -> IoResult<Self> {
279 let mut buf = Vec::new();
280 let _ = reader.read_to_end(&mut buf)?;
281 Ok(buf)
282 }
283}
284
285#[cfg(test)]
286mod test {
287 use super::ToBytes;
288 #[test]
289 fn test_macro_empty() {
290 let array: Vec<u8> = vec![];
291 let bytes: Vec<u8> = to_bytes![array].unwrap();
292 assert_eq!(&bytes, &array);
293 assert_eq!(bytes.len(), 0);
294 }
295
296 #[test]
297 fn test_macro() {
298 let array1 = [1u8; 32];
299 let array2 = [2u8; 16];
300 let array3 = [3u8; 8];
301 let bytes = to_bytes![array1, array2, array3].unwrap();
302 assert_eq!(bytes.len(), 56);
303
304 let mut actual_bytes = Vec::new();
305 actual_bytes.extend_from_slice(&array1);
306 actual_bytes.extend_from_slice(&array2);
307 actual_bytes.extend_from_slice(&array3);
308 assert_eq!(bytes, actual_bytes);
309 }
310}