1use std::io::{Read, Result as IoResult};
2
3use byteorder::{BigEndian, ByteOrder, LittleEndian, ReadBytesExt};
4
5pub trait UnpackFrom: Sized {
7 fn unpack_from<E: ByteOrder, R: Read + ?Sized>(src: &mut R) -> IoResult<Self>;
23
24 fn unpack_from_be<R: Read + ?Sized>(src: &mut R) -> IoResult<Self> {
39 Self::unpack_from::<BigEndian, _>(src)
40 }
41
42 fn unpack_from_le<R: Read + ?Sized>(src: &mut R) -> IoResult<Self> {
57 Self::unpack_from::<LittleEndian, _>(src)
58 }
59
60 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}