snops_common/format/
impl_tuples.rs

1use std::io::{Read, Write};
2
3use super::{DataFormat, DataReadError, DataWriteError};
4
5macro_rules! impl_tuple_dataformat {
6    ($($name:ident),+) => {
7        impl<$($name: DataFormat),+> DataFormat for ($($name,)+) {
8            type Header = ($($name::Header,)+);
9            // TODO: potentially make these into references
10            const LATEST_HEADER: Self::Header = ($($name::LATEST_HEADER,)+);
11
12            paste::paste! {
13                fn write_header<W: Write>(&self, writer: &mut W) -> Result<usize, DataWriteError> {
14                    let ($([<$name:lower>],)+) = self;
15                    let mut written = 0;
16                    $(written += [<$name:lower>].write_header(writer)?;)+
17                    Ok(written)
18                }
19
20                fn read_header<R: Read>(reader: &mut R) -> Result<Self::Header, DataReadError> {
21                    Ok(($($name::read_header(reader)?,)+))
22                }
23
24                fn write_data<W: Write>(&self, writer: &mut W) -> Result<usize, DataWriteError>{
25                    let ($([<$name:lower>],)+) = self;
26                    let mut written = 0;
27                    $(written += [<$name:lower>].write_data(writer)?;)+
28                    Ok(written)
29                }
30
31                fn read_data<R: Read>(reader: &mut R, header: &Self::Header) -> Result<Self, DataReadError> {
32                    let ($([<$name:lower>],)+) = header;
33                    Ok(($($name::read_data(reader, [<$name:lower>])?,)+))
34                }
35
36            }
37        }
38    };
39}
40
41impl_tuple_dataformat!(A, B);
42impl_tuple_dataformat!(A, B, C);
43
44impl DataFormat for () {
45    type Header = ();
46    const LATEST_HEADER: Self::Header = ();
47
48    fn write_header<W: Write>(&self, _writer: &mut W) -> Result<usize, DataWriteError> {
49        Ok(0)
50    }
51
52    fn read_header<R: Read>(_reader: &mut R) -> Result<Self::Header, DataReadError> {
53        Ok(())
54    }
55
56    fn write_data<W: Write>(&self, _writer: &mut W) -> Result<usize, DataWriteError> {
57        Ok(0)
58    }
59
60    fn read_data<R: Read>(_reader: &mut R, _header: &Self::Header) -> Result<Self, DataReadError> {
61        Ok(())
62    }
63}
64
65#[cfg(test)]
66#[rustfmt::skip]
67mod test {
68    use crate::format::DataFormat;
69
70    macro_rules! case {
71        ($name:ident, $ty:ty, $a:expr, $b:expr) => {
72            #[test]
73            fn $name() {
74                let mut data = Vec::new();
75                $a.write_data(&mut data).unwrap();
76                assert_eq!(data, &$b);
77
78                let mut reader = &data[..];
79                let read_value = <$ty>::read_data(&mut reader, &<$ty as DataFormat>::LATEST_HEADER).unwrap();
80                assert_eq!(read_value, $a);
81
82            }
83
84        };
85    }
86
87    case!(test_tuple_0, (), (), [0u8; 0]);
88    case!(test_tuple_2, (u8, u16), (1u8, 2u16), [1, 2, 0]);
89    case!(test_tuple_3, (u8, u16, u32), (1u8, 2u16, 3u32), [
90        1,
91        2, 0,
92        3, 0, 0, 0
93    ]);
94    case!(test_tuple_2_1, ((u8, u16), u32), ((1u8, 2u16), 3u32), [
95        1,
96        2, 0,
97        3, 0, 0, 0
98    ]);
99    case!(test_tuple_2_2, ((u8, u16), (u32, u64)), ((1u8, 2u16), (3u32, 4u64)), [
100        1,
101        2, 0,
102        3, 0, 0, 0,
103        4, 0, 0, 0, 0, 0, 0, 0
104    ]);
105    case!(test_tuple_2_rev, (u16, u8), (2u16, 1u8), [2, 0, 1]);
106    case!(test_tuple_2_1_rev, (u32, (u16, u8)), (3u32, (2u16, 1u8)), [
107        3, 0, 0, 0,
108        2, 0,
109        1
110    ]);
111    case!(test_tuple_2_2_rev, ((u32, u64), (u16, u8)), ((3u32, 4u64), (2u16, 1u8)), [
112        3, 0, 0, 0,
113        4, 0, 0, 0, 0, 0, 0, 0,
114        2,
115        0, 1
116    ]);
117
118}