const_num_traits/ops/
bytes.rs1use core::borrow::{Borrow, BorrowMut};
2use core::cmp::{Eq, Ord, PartialEq, PartialOrd};
3use core::fmt::Debug;
4use core::hash::Hash;
5
6c0nst::c0nst! {
7pub c0nst trait NumBytes:
8 Debug
9 + AsRef<[u8]>
10 + AsMut<[u8]>
11 + PartialEq
12 + Eq
13 + PartialOrd
14 + Ord
15 + Hash
16 + Borrow<[u8]>
17 + BorrowMut<[u8]>
18{
19}
20}
21
22c0nst::c0nst! {
23c0nst impl<T> NumBytes for T where
24 T: Debug
25 + AsRef<[u8]>
26 + AsMut<[u8]>
27 + PartialEq
28 + Eq
29 + PartialOrd
30 + Ord
31 + Hash
32 + Borrow<[u8]>
33 + BorrowMut<[u8]>
34 + ?Sized
35{
36}
37}
38
39c0nst::c0nst! {
40pub c0nst trait ToBytes: Sized {
41 type Bytes: NumBytes;
42
43 fn to_be_bytes(self) -> Self::Bytes;
54
55 fn to_le_bytes(self) -> Self::Bytes;
66
67 fn to_ne_bytes(self) -> Self::Bytes {
90 #[cfg(target_endian = "big")]
91 let bytes = self.to_be_bytes();
92 #[cfg(target_endian = "little")]
93 let bytes = self.to_le_bytes();
94 bytes
95 }
96}
97}
98
99c0nst::c0nst! {
100pub c0nst trait FromBytes: Sized {
101 type Bytes: NumBytes + ?Sized;
105
106 fn from_be_bytes(bytes: &Self::Bytes) -> Self;
117
118 fn from_le_bytes(bytes: &Self::Bytes) -> Self;
129
130 fn from_ne_bytes(bytes: &Self::Bytes) -> Self {
153 #[cfg(target_endian = "big")]
154 let this = Self::from_be_bytes(bytes);
155 #[cfg(target_endian = "little")]
156 let this = Self::from_le_bytes(bytes);
157 this
158 }
159}
160}
161
162macro_rules! float_to_from_bytes_impl {
163 ($T:ty, $L:expr) => {
164 c0nst::c0nst! {
165 c0nst impl ToBytes for $T {
166 type Bytes = [u8; $L];
167
168 #[inline]
169 fn to_be_bytes(self) -> Self::Bytes {
170 <$T>::to_be_bytes(self)
171 }
172
173 #[inline]
174 fn to_le_bytes(self) -> Self::Bytes {
175 <$T>::to_le_bytes(self)
176 }
177
178 #[inline]
179 fn to_ne_bytes(self) -> Self::Bytes {
180 <$T>::to_ne_bytes(self)
181 }
182 }
183 }
184
185 c0nst::c0nst! {
186 c0nst impl FromBytes for $T {
187 type Bytes = [u8; $L];
188
189 #[inline]
190 fn from_be_bytes(bytes: &Self::Bytes) -> Self {
191 <$T>::from_be_bytes(*bytes)
192 }
193
194 #[inline]
195 fn from_le_bytes(bytes: &Self::Bytes) -> Self {
196 <$T>::from_le_bytes(*bytes)
197 }
198
199 #[inline]
200 fn from_ne_bytes(bytes: &Self::Bytes) -> Self {
201 <$T>::from_ne_bytes(*bytes)
202 }
203 }
204 }
205 };
206}
207
208macro_rules! int_to_from_bytes_impl {
209 ($T:ty, $L:expr) => {
210 c0nst::c0nst! {
211 c0nst impl ToBytes for $T {
212 type Bytes = [u8; $L];
213
214 #[inline]
215 fn to_be_bytes(self) -> Self::Bytes {
216 <$T>::to_be_bytes(self)
217 }
218
219 #[inline]
220 fn to_le_bytes(self) -> Self::Bytes {
221 <$T>::to_le_bytes(self)
222 }
223
224 #[inline]
225 fn to_ne_bytes(self) -> Self::Bytes {
226 <$T>::to_ne_bytes(self)
227 }
228 }
229 }
230
231 c0nst::c0nst! {
232 c0nst impl FromBytes for $T {
233 type Bytes = [u8; $L];
234
235 #[inline]
236 fn from_be_bytes(bytes: &Self::Bytes) -> Self {
237 <$T>::from_be_bytes(*bytes)
238 }
239
240 #[inline]
241 fn from_le_bytes(bytes: &Self::Bytes) -> Self {
242 <$T>::from_le_bytes(*bytes)
243 }
244
245 #[inline]
246 fn from_ne_bytes(bytes: &Self::Bytes) -> Self {
247 <$T>::from_ne_bytes(*bytes)
248 }
249 }
250 }
251 };
252}
253
254int_to_from_bytes_impl!(u8, 1);
255int_to_from_bytes_impl!(u16, 2);
256int_to_from_bytes_impl!(u32, 4);
257int_to_from_bytes_impl!(u64, 8);
258int_to_from_bytes_impl!(u128, 16);
259#[cfg(target_pointer_width = "64")]
260int_to_from_bytes_impl!(usize, 8);
261#[cfg(target_pointer_width = "32")]
262int_to_from_bytes_impl!(usize, 4);
263
264int_to_from_bytes_impl!(i8, 1);
265int_to_from_bytes_impl!(i16, 2);
266int_to_from_bytes_impl!(i32, 4);
267int_to_from_bytes_impl!(i64, 8);
268int_to_from_bytes_impl!(i128, 16);
269#[cfg(target_pointer_width = "64")]
270int_to_from_bytes_impl!(isize, 8);
271#[cfg(target_pointer_width = "32")]
272int_to_from_bytes_impl!(isize, 4);
273
274float_to_from_bytes_impl!(f32, 4);
275float_to_from_bytes_impl!(f64, 8);
276
277#[cfg(test)]
278mod tests {
279 use super::*;
280
281 macro_rules! check_to_from_bytes {
282 ($( $ty:ty )+) => {$({
283 let n = 1;
284 let be = <$ty as ToBytes>::to_be_bytes(n);
285 let le = <$ty as ToBytes>::to_le_bytes(n);
286 let ne = <$ty as ToBytes>::to_ne_bytes(n);
287
288 assert_eq!(*be.last().unwrap(), 1);
289 assert_eq!(*le.first().unwrap(), 1);
290 if cfg!(target_endian = "big") {
291 assert_eq!(*ne.last().unwrap(), 1);
292 } else {
293 assert_eq!(*ne.first().unwrap(), 1);
294 }
295
296 assert_eq!(<$ty as FromBytes>::from_be_bytes(&be), n);
297 assert_eq!(<$ty as FromBytes>::from_le_bytes(&le), n);
298 if cfg!(target_endian = "big") {
299 assert_eq!(<$ty as FromBytes>::from_ne_bytes(&be), n);
300 } else {
301 assert_eq!(<$ty as FromBytes>::from_ne_bytes(&le), n);
302 }
303 })+}
304 }
305
306 #[test]
307 fn convert_between_int_and_bytes() {
308 check_to_from_bytes!(u8 u16 u32 u64 u128 usize);
309 check_to_from_bytes!(i8 i16 i32 i64 i128 isize);
310 }
311
312 #[test]
313 fn convert_between_float_and_bytes() {
314 macro_rules! check_to_from_bytes {
315 ($( $ty:ty )+) => {$(
316 let n: $ty = 3.5;
317
318 let be = <$ty as ToBytes>::to_be_bytes(n);
319 let le = <$ty as ToBytes>::to_le_bytes(n);
320 let ne = <$ty as ToBytes>::to_ne_bytes(n);
321
322 assert_eq!(<$ty as FromBytes>::from_be_bytes(&be), n);
323 assert_eq!(<$ty as FromBytes>::from_le_bytes(&le), n);
324 if cfg!(target_endian = "big") {
325 assert_eq!(ne, be);
326 assert_eq!(<$ty as FromBytes>::from_ne_bytes(&be), n);
327 } else {
328 assert_eq!(ne, le);
329 assert_eq!(<$ty as FromBytes>::from_ne_bytes(&le), n);
330 }
331 )+}
332 }
333
334 check_to_from_bytes!(f32 f64);
335 }
336}