byteorder_pack/
unpack.rs

1use std::io::{Read, Result as IoResult};
2
3use byteorder::{BigEndian, ByteOrder, LittleEndian, ReadBytesExt};
4
5/// Read a value from a [`Read`].
6pub trait UnpackFrom: Sized {
7    /// Unpack a single value from `src`.
8    /// # Example
9    /// ```rust
10    /// use std::io::Cursor;
11    /// use byteorder::BigEndian;
12    /// use byteorder_pack::UnpackFrom;
13    ///
14    /// let mut cursor = Cursor::new(vec![0x01, 0x02, 0x00, 0x03, 0x00, 0x04]);
15    ///
16    /// let (a, b, cd) = <(u8, u8, [u16; 2])>::unpack_from::<BigEndian, _>(&mut cursor).unwrap();
17    ///
18    /// assert_eq!(a, 1);
19    /// assert_eq!(b, 2);
20    /// assert_eq!(cd, [3, 4]);
21    /// ```
22    fn unpack_from<E: ByteOrder, R: Read + ?Sized>(src: &mut R) -> IoResult<Self>;
23
24    /// Unpack binary data contained in `src` to a tuple, in [`BigEndian`] order.
25    /// # Example
26    /// ```rust
27    /// use std::io::Cursor;
28    /// use byteorder_pack::{UnpackFrom};
29    ///
30    /// let mut cursor = Cursor::new(vec![0x01, 0x02, 0x00, 0x03, 0x00, 0x04]);
31    ///
32    /// let (a, b, cd) = <(u8, u8, [u16; 2])>::unpack_from_be(&mut cursor).unwrap();
33    ///
34    /// assert_eq!(a, 1);
35    /// assert_eq!(b, 2);
36    /// assert_eq!(cd, [3, 4]);
37    /// ```
38    fn unpack_from_be<R: Read + ?Sized>(src: &mut R) -> IoResult<Self> {
39        Self::unpack_from::<BigEndian, _>(src)
40    }
41
42    /// Unpack binary data contained in `src` to a tuple, in [`LittleEndian`] order.
43    /// # Example
44    /// ```rust
45    /// use std::io::Cursor;
46    /// use byteorder_pack::UnpackFrom;
47    ///
48    /// let mut cursor = Cursor::new(vec![0x01, 0x02, 0x03, 0x00, 0x04, 0x00]);
49    ///
50    /// let (a, b, cd) = <(u8, u8, [u16; 2])>::unpack_from_le(&mut cursor).unwrap();
51    ///
52    /// assert_eq!(a, 1);
53    /// assert_eq!(b, 2);
54    /// assert_eq!(cd, [3, 4]);
55    /// ```
56    fn unpack_from_le<R: Read + ?Sized>(src: &mut R) -> IoResult<Self> {
57        Self::unpack_from::<LittleEndian, _>(src)
58    }
59
60    /// Unpack multiple values from `src`.
61    fn unpack_multiple_into<E: ByteOrder, R: Read + ?Sized>(
62        src: &mut R,
63        dst: &mut [Self],
64    ) -> IoResult<()> {
65        for i in dst {
66            *i = Self::unpack_from::<E, _>(src)?;
67        }
68        Ok(())
69    }
70}
71
72impl<T: UnpackFrom + Default + Copy, const N: usize> UnpackFrom for [T; N] {
73    fn unpack_from<E: ByteOrder, R: Read + ?Sized>(src: &mut R) -> IoResult<Self> {
74        let mut dst = [T::default(); N];
75        T::unpack_multiple_into::<E, _>(src, &mut dst)?;
76        Ok(dst)
77    }
78}
79
80macro_rules! impl_tuple {
81    ($($n:ident),+) => {
82        impl<$($n: UnpackFrom),+> UnpackFrom for ($($n,)+)
83        {
84            #[inline]
85            fn unpack_from<E: ByteOrder, R: Read + ?Sized>(src: &mut R) -> IoResult<Self> {
86                Ok(
87                    (
88                        $($n::unpack_from::<E, _>(src)?,)+
89                    )
90                )
91            }
92        }
93    };
94}
95impl_tuple!(T1);
96impl_tuple!(T1, T2);
97impl_tuple!(T1, T2, T3);
98impl_tuple!(T1, T2, T3, T4);
99impl_tuple!(T1, T2, T3, T4, T5);
100impl_tuple!(T1, T2, T3, T4, T5, T6);
101impl_tuple!(T1, T2, T3, T4, T5, T6, T7);
102impl_tuple!(T1, T2, T3, T4, T5, T6, T7, T8);
103impl_tuple!(T1, T2, T3, T4, T5, T6, T7, T8, T9);
104impl_tuple!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10);
105impl_tuple!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11);
106impl_tuple!(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12);
107
108macro_rules! impl_primitive {
109    ($($name:ident + $name2:ident => $ty:ty),+) => {
110        $(
111            impl UnpackFrom for $ty {
112                fn unpack_from<E: ByteOrder, R: Read + ?Sized>(src: &mut R) -> IoResult<Self> {
113                    src.$name::<E>()
114                }
115
116                fn unpack_multiple_into<E: ByteOrder, R: Read + ?Sized>(
117                    src: &mut R,
118                    dst: &mut [Self],
119                ) -> IoResult<()> {
120                    src.$name2::<E>(dst)
121                }
122            }
123        )+
124    };
125}
126
127impl_primitive!(
128    read_u16 + read_u16_into => u16, read_u32 + read_u32_into => u32, read_u64 + read_u64_into => u64, read_u128 + read_u128_into => u128,
129    read_i16 + read_i16_into => i16, read_i32 + read_i32_into => i32, read_i64 + read_i64_into => i64, read_i128 + read_i128_into => i128,
130    read_f32 + read_f32_into => f32, read_f64 + read_f64_into => f64
131);
132
133impl UnpackFrom for u8 {
134    fn unpack_from<E: ByteOrder, R: Read + ?Sized>(src: &mut R) -> IoResult<Self> {
135        src.read_u8()
136    }
137
138    fn unpack_multiple_into<E: ByteOrder, R: Read + ?Sized>(
139        src: &mut R,
140        dst: &mut [Self],
141    ) -> IoResult<()> {
142        src.read_exact(dst)
143    }
144}
145
146impl UnpackFrom for i8 {
147    fn unpack_from<E: ByteOrder, R: Read + ?Sized>(src: &mut R) -> IoResult<Self> {
148        src.read_i8()
149    }
150
151    fn unpack_multiple_into<E: ByteOrder, R: Read + ?Sized>(
152        src: &mut R,
153        dst: &mut [Self],
154    ) -> IoResult<()> {
155        src.read_i8_into(dst)
156    }
157}