1use std::convert::TryInto;
26
27#[macro_export]
30macro_rules! array_from_bytes_le {
31 ($t:ty , $n:expr , $bytes:expr) => {{
32 let size = std::mem::size_of::<$t>();
33 if $bytes.len() != size * $n {
34 return Err(FromBytesError::SizeMismatch)?;
35 }
36
37 let mut arr: [$t; $n] = [<$t>::default(); $n];
38 for i in 0..$n {
39 arr[i] = <$t>::from_le_slice(&$bytes[i * size..(i + 1) * size])?
40 }
41 let result: FromBytesResult<[$t; $n]> = Ok(arr);
42 result
43 }};
44}
45
46#[macro_export]
47macro_rules! array_from_bytes_be {
48 ($t:ty , $n:expr , $bytes:expr) => {{
49 let size = std::mem::size_of::<$t>();
50 if $bytes.len() != size * $n {
51 return Err(FromBytesError::SizeMismatch)?;
52 }
53
54 let mut arr: [$t; $n] = [<$t>::default(); $n];
55 for i in 0..$n {
56 arr[i] = <$t>::from_be_slice(&$bytes[i * size..(i + 1) * size])?
57 }
58 let result: FromBytesResult<[$t; $n]> = Ok(arr);
59 result
60 }};
61}
62
63#[inline(always)]
66#[allow(unused)]
67pub fn slice_from_bytes_le<FB>(bytes: &[u8], target: &mut [FB]) -> FromBytesResult<()>
68where
69 FB: FromBytes,
70{
71 let size = std::mem::size_of::<FB>();
72
73 if bytes.len() != size * target.len() {
74 return Err(FromBytesError::SizeMismatch);
75 }
76
77 for i in 0..target.len() {
78 target[i] = FB::from_le_slice(&bytes[i * size..(i + 1) * size])?
79 }
80
81 Ok(())
82}
83
84#[inline(always)]
87#[allow(unused)]
88pub fn slice_from_bytes_be<FB>(bytes: &[u8], target: &mut [FB]) -> FromBytesResult<()>
89where
90 FB: FromBytes,
91{
92 let size = std::mem::size_of::<FB>();
93
94 if size * bytes.len() != target.len() {
95 return Err(FromBytesError::SizeMismatch);
96 }
97
98 for i in 0..target.len() {
99 target[i] = FB::from_be_slice(&bytes[i * size..(i + 1) * size])?
100 }
101
102 Ok(())
103}
104
105pub trait FromBytes: Sized {
109 fn from_le_slice(bytes: &[u8]) -> FromBytesResult<Self>;
110 fn from_be_slice(bytes: &[u8]) -> FromBytesResult<Self>;
111}
112
113impl FromBytes for i8 {
116 #[inline(always)]
117 fn from_le_slice(bytes: &[u8]) -> FromBytesResult<Self> {
118 Ok(i8::from_le_bytes(bytes.try_into()?))
119 }
120 #[inline(always)]
121 fn from_be_slice(bytes: &[u8]) -> FromBytesResult<Self> {
122 Ok(i8::from_be_bytes(bytes.try_into()?))
123 }
124}
125
126impl FromBytes for u8 {
127 #[inline(always)]
128 fn from_le_slice(bytes: &[u8]) -> FromBytesResult<Self> {
129 Ok(u8::from_le_bytes(bytes.try_into()?))
130 }
131 #[inline(always)]
132 fn from_be_slice(bytes: &[u8]) -> FromBytesResult<Self> {
133 Ok(u8::from_be_bytes(bytes.try_into()?))
134 }
135}
136
137impl FromBytes for i16 {
138 #[inline(always)]
139 fn from_le_slice(bytes: &[u8]) -> FromBytesResult<Self> {
140 Ok(i16::from_le_bytes(bytes.try_into()?))
141 }
142 #[inline(always)]
143 fn from_be_slice(bytes: &[u8]) -> FromBytesResult<Self> {
144 Ok(i16::from_be_bytes(bytes.try_into()?))
145 }
146}
147
148impl FromBytes for u16 {
149 #[inline(always)]
150 fn from_le_slice(bytes: &[u8]) -> FromBytesResult<Self> {
151 Ok(u16::from_le_bytes(bytes.try_into()?))
152 }
153 #[inline(always)]
154 fn from_be_slice(bytes: &[u8]) -> FromBytesResult<Self> {
155 Ok(u16::from_be_bytes(bytes.try_into()?))
156 }
157}
158
159impl FromBytes for i32 {
160 #[inline(always)]
161 fn from_le_slice(bytes: &[u8]) -> FromBytesResult<Self> {
162 Ok(i32::from_le_bytes(bytes.try_into()?))
163 }
164 #[inline(always)]
165 fn from_be_slice(bytes: &[u8]) -> FromBytesResult<Self> {
166 Ok(i32::from_be_bytes(bytes.try_into()?))
167 }
168}
169
170impl FromBytes for u32 {
171 #[inline(always)]
172 fn from_le_slice(bytes: &[u8]) -> FromBytesResult<Self> {
173 Ok(u32::from_le_bytes(bytes.try_into()?))
174 }
175 #[inline(always)]
176 fn from_be_slice(bytes: &[u8]) -> FromBytesResult<Self> {
177 Ok(u32::from_be_bytes(bytes.try_into()?))
178 }
179}
180
181impl FromBytes for f32 {
182 #[inline(always)]
183 fn from_le_slice(bytes: &[u8]) -> FromBytesResult<Self> {
184 Ok(f32::from_le_bytes(bytes.try_into()?))
185 }
186 #[inline(always)]
187 fn from_be_slice(bytes: &[u8]) -> FromBytesResult<Self> {
188 Ok(f32::from_be_bytes(bytes.try_into()?))
189 }
190}
191
192impl FromBytes for i64 {
193 #[inline(always)]
194 fn from_le_slice(bytes: &[u8]) -> FromBytesResult<Self> {
195 Ok(i64::from_le_bytes(bytes.try_into()?))
196 }
197 #[inline(always)]
198 fn from_be_slice(bytes: &[u8]) -> FromBytesResult<Self> {
199 Ok(i64::from_be_bytes(bytes.try_into()?))
200 }
201}
202
203impl FromBytes for u64 {
204 #[inline(always)]
205 fn from_le_slice(bytes: &[u8]) -> FromBytesResult<Self> {
206 Ok(u64::from_le_bytes(bytes.try_into()?))
207 }
208 #[inline(always)]
209 fn from_be_slice(bytes: &[u8]) -> FromBytesResult<Self> {
210 Ok(u64::from_be_bytes(bytes.try_into()?))
211 }
212}
213
214impl FromBytes for f64 {
215 #[inline(always)]
216 fn from_le_slice(bytes: &[u8]) -> FromBytesResult<Self> {
217 Ok(f64::from_le_bytes(bytes.try_into()?))
218 }
219 #[inline(always)]
220 fn from_be_slice(bytes: &[u8]) -> FromBytesResult<Self> {
221 Ok(f64::from_be_bytes(bytes.try_into()?))
222 }
223}
224
225pub enum FromBytesError {
229 BinaryData,
230 SizeMismatch,
231}
232
233pub type FromBytesResult<T> = std::result::Result<T, FromBytesError>;
235
236impl From<std::array::TryFromSliceError> for FromBytesError {
237 fn from(_error: std::array::TryFromSliceError) -> Self {
238 FromBytesError::BinaryData
239 }
240}
241
242