Skip to main content

byterepr/
lib.rs

1use std::num::*;
2use std::mem::{
3    MaybeUninit,
4    transmute_copy,
5};
6use bytemuck::Pod;
7
8/// A trait that allows an object to be converted to and from arbitrary endianness bytes.
9pub trait ByteRepr: Sized + Pod + Clone {
10    /// The length of the value in bytes.
11    const BYTE_LEN: usize;
12
13    /// Convert little endian bytes into Self.
14    /// Returns None if the conversion fails.
15    fn try_from_le_bytes(b: &[u8]) -> Option<Self> {
16        if b.len() >= Self::BYTE_LEN {
17            Some(<Self as ByteRepr>::from_le_bytes(b))
18        } else {
19            None
20        }
21    }
22
23    /// Convert little endian bytes into Self.
24    /// Panics if the conversion fails!
25    fn from_le_bytes(b: &[u8]) -> Self;
26
27    /// Copy Self into a little endian byte buffer.
28    /// Panics if `dest` is too small to contain Self.
29    fn copy_to_le_bytes(self, dest: &mut [u8]);
30
31    /// Convert Self into a little endian byte buffer.
32    fn into_le_bytes(self) -> Vec<u8>;
33
34    /// Convert big endian bytes into Self.
35    /// Returns None if the conversion fails.
36    fn try_from_be_bytes(b: &[u8]) -> Option<Self> {
37        if b.len() >= Self::BYTE_LEN {
38            Some(<Self as ByteRepr>::from_be_bytes(b))
39        } else {
40            None
41        }
42    }
43
44    /// Convert little endian bytes into Self.
45    /// Panics if the conversion fails!
46    fn from_be_bytes(b: &[u8]) -> Self;
47
48    /// Copy Self into a big endian byte buffer.
49    /// Panics if `dest` is too small to contain Self.
50    fn copy_to_be_bytes(self, dest: &mut [u8]);
51
52    /// Convert Self into a big endian byte buffer.
53    fn into_be_bytes(self) -> Vec<u8>;
54
55    /// Convert big endian bytes into Self.
56    /// Returns None if the conversion fails.
57    fn try_from_ne_bytes(b: &[u8]) -> Option<Self> {
58        if b.len() >= Self::BYTE_LEN {
59            Some(<Self as ByteRepr>::from_ne_bytes(b))
60        } else {
61            None
62        }
63    }
64
65    /// Convert little endian bytes into Self.
66    /// Panics if the conversion fails!
67    fn from_ne_bytes(b: &[u8]) -> Self {
68        if cfg!(endianness = "little") {
69            <Self as ByteRepr>::from_le_bytes(b)
70        } else {
71            <Self as ByteRepr>::from_be_bytes(b)
72        }
73    }
74
75    /// Copy Self into a big endian byte buffer.
76    /// Panics if `dest` is too small to contain Self.
77    fn copy_to_ne_bytes(self, dest: &mut [u8]) {
78        if cfg!(endianness = "little") {
79            <Self as ByteRepr>::copy_to_le_bytes(self, dest)
80        } else {
81            <Self as ByteRepr>::copy_to_be_bytes(self, dest)
82        }
83    }
84
85    /// Convert Self into a big endian byte buffer.
86    fn into_ne_bytes(self) -> Vec<u8> {
87        if cfg!(endianness = "little") {
88            <Self as ByteRepr>::into_le_bytes(self)
89        } else {
90            <Self as ByteRepr>::into_be_bytes(self)
91        }
92    }
93}
94
95/// Marker trait for number types that implement ByteRepr
96pub trait ByteReprNum: ByteRepr {}
97
98macro_rules! gen_byterepr_impls_nums {
99    ($($T:ty)+) => {
100        $(
101        impl ByteRepr for $T {
102            const BYTE_LEN: usize = std::mem::size_of::<$T>();
103        
104            #[inline]
105            fn from_le_bytes(b: &[u8]) -> Self {
106                assert!(b.len() >= Self::BYTE_LEN);
107                let mut boilerplate: [u8; Self::BYTE_LEN] = [0; Self::BYTE_LEN];
108                boilerplate.copy_from_slice(&b[0..Self::BYTE_LEN]);
109                Self::from_le_bytes(boilerplate)
110            }
111            
112            #[inline]
113            fn from_be_bytes(b: &[u8]) -> Self {
114                let mut boilerplate: [u8; Self::BYTE_LEN] = [0; Self::BYTE_LEN];
115                boilerplate.copy_from_slice(&b[0..Self::BYTE_LEN]);
116                Self::from_be_bytes(boilerplate)
117            }
118        
119            #[inline]
120            fn copy_to_le_bytes(self, dest: &mut [u8]) {
121                let bytes = self.to_le_bytes();
122                dest[..Self::BYTE_LEN].copy_from_slice(&bytes[0..Self::BYTE_LEN]);
123            }
124        
125            #[inline]
126            fn copy_to_be_bytes(self, dest: &mut [u8]) {
127                let bytes = self.to_be_bytes();
128                dest[..Self::BYTE_LEN].copy_from_slice(&bytes[0..Self::BYTE_LEN]);
129            }
130        
131            fn into_be_bytes(self) -> Vec<u8> {
132                self.to_be_bytes().to_vec()
133            }
134        
135            fn into_le_bytes(self) -> Vec<u8> {
136                self.to_le_bytes().to_vec()
137            }
138        }
139        impl ByteReprNum for $T {}
140        )+
141    }
142}
143
144gen_byterepr_impls_nums!(u8 i8 u16 i16 u32 i32 f32 u64 i64 f64 u128 i128);
145
146macro_rules! gen_byterepr_impls_nonzero_nums {
147    ($($T:ty, $J:ty)+) => {
148        $(
149        impl ByteRepr for Option<$T> {
150            const BYTE_LEN: usize = std::mem::size_of::<Option<$T>>();
151        
152            #[inline]
153            fn from_le_bytes(b: &[u8]) -> Self {
154                let val = <$J as ByteRepr>::from_le_bytes(b);
155                <$T>::new(val)
156            }
157        
158            #[inline]
159            fn from_be_bytes(b: &[u8]) -> Self {
160                let val = <$J as ByteRepr>::from_be_bytes(b);
161                <$T>::new(val)
162            }
163        
164            #[inline]
165            fn copy_to_le_bytes(self, dest: &mut [u8]) {
166                match self {
167                    Some(v) => <$J as ByteRepr>::copy_to_le_bytes(v.get(), dest),
168                    None => <$J as ByteRepr>::copy_to_le_bytes(0, dest),
169                }
170            }
171        
172            #[inline]
173            fn copy_to_be_bytes(self, dest: &mut [u8]) {
174                match self {
175                    Some(v) => <$J as ByteRepr>::copy_to_be_bytes(v.get(), dest),
176                    None => <$J as ByteRepr>::copy_to_be_bytes(0, dest),
177                }
178            }
179        
180            fn into_be_bytes(self) -> Vec<u8> {
181                let val = match self {
182                    Some(v) => v.get(),
183                    None => 0 as $J,
184                };
185                val.to_be_bytes().to_vec()
186            }
187        
188            fn into_le_bytes(self) -> Vec<u8> {
189                let val = match self {
190                    Some(v) => v.get(),
191                    None => 0 as $J,
192                };
193                val.to_le_bytes().to_vec()
194            }
195        }
196        )+
197    }
198}
199
200gen_byterepr_impls_nonzero_nums!(NonZeroI8, i8 NonZeroU8, u8 NonZeroI16, i16 NonZeroU16, u16);
201
202impl<T: ByteRepr> ByteRepr for Wrapping<T> {
203    const BYTE_LEN: usize = T::BYTE_LEN;
204
205    fn from_le_bytes(b: &[u8]) -> Self {
206        Wrapping(<T as ByteRepr>::from_le_bytes(b))
207    }
208
209    fn from_be_bytes(b: &[u8]) -> Self {
210        Wrapping(<T as ByteRepr>::from_be_bytes(b))
211    }
212
213    fn copy_to_le_bytes(self, dest: &mut [u8]) {
214        self.0.copy_to_le_bytes(dest);
215    }
216
217    fn copy_to_be_bytes(self, dest: &mut [u8]) {
218        self.0.copy_to_be_bytes(dest);
219    }
220
221    fn into_be_bytes(self) -> Vec<u8> {
222        self.0.into_be_bytes()
223    }
224
225    fn into_le_bytes(self) -> Vec<u8> {
226        self.0.into_le_bytes()
227    }
228}
229
230macro_rules! gen_byterepr_impls_array {
231    ($($arrlen:literal)+) => {
232        $(
233            impl<T: ByteRepr + Copy> ByteRepr for [T; $arrlen] {
234                const BYTE_LEN: usize = T::BYTE_LEN * $arrlen;
235            
236                fn from_le_bytes(b: &[u8]) -> Self {
237                    assert!(b.len() >= Self::BYTE_LEN);
238                    let mut out: [MaybeUninit<T>; $arrlen] = unsafe {
239                        MaybeUninit::uninit().assume_init()
240                    };
241
242                    if cfg!(endianness = "little") {
243                        let bptr: *const u8 = b.as_ptr();
244                        let optr: *mut [MaybeUninit<T>; $arrlen] = &mut out;
245    
246                        unsafe {
247                            bptr.copy_to(optr as *mut u8, Self::BYTE_LEN);
248                        }
249                    } else {
250                        for i in 0..(out.len()) {
251                            let val_start = T::BYTE_LEN * i;
252                            let val_end = val_start + T::BYTE_LEN;
253                            out[i] = MaybeUninit::new(T::from_le_bytes(&b[val_start..val_end]));
254                        }
255                    }
256            
257                    unsafe { transmute_copy::<_, [T; $arrlen]>(&out) }
258                }
259            
260                fn from_be_bytes(b: &[u8]) -> Self {
261                    assert!(b.len() >= Self::BYTE_LEN);
262                    let mut out: [MaybeUninit<T>; $arrlen] = unsafe {
263                        MaybeUninit::uninit().assume_init()
264                    };
265            
266                    if cfg!(endianness = "big") {
267                        let bptr: *const u8 = b.as_ptr();
268                        let optr: *mut [MaybeUninit<T>; $arrlen] = &mut out;
269    
270                        unsafe {
271                            bptr.copy_to(optr as *mut u8, Self::BYTE_LEN);
272                        }
273                    } else {
274                        for i in 0..(out.len()) {
275                            let val_start = T::BYTE_LEN * i;
276                            let val_end = val_start + T::BYTE_LEN;
277                            out[i] = MaybeUninit::new(T::from_be_bytes(&b[val_start..val_end]));
278                        }
279                    }
280            
281                    unsafe { transmute_copy::<_, [T; $arrlen]>(&out) }
282                }
283            
284                fn copy_to_le_bytes(self, dest: &mut [u8]) {
285                    assert!(dest.len() >= Self::BYTE_LEN);
286            
287                    for i in 0..$arrlen {
288                        let val_start = T::BYTE_LEN * i;
289                        let val_end = val_start + T::BYTE_LEN;
290                        self[i].copy_to_le_bytes(&mut dest[val_start..val_end]);
291                    }
292                }
293            
294                fn copy_to_be_bytes(self, dest: &mut [u8]) {
295                    assert!(dest.len() >= Self::BYTE_LEN);
296                    
297                    for i in 0..$arrlen {
298                        let val_start = T::BYTE_LEN * i;
299                        let val_end = val_start + T::BYTE_LEN;
300                        self[i].copy_to_be_bytes(&mut dest[val_start..val_end]);
301                    }
302                }
303            
304                fn into_be_bytes(self) -> Vec<u8> {
305                    let mut out_vec = vec![Default::default(); Self::BYTE_LEN];
306                    self.copy_to_be_bytes(&mut out_vec);
307                    out_vec
308                }
309            
310                fn into_le_bytes(self) -> Vec<u8> {
311                    let mut out_vec = vec![Default::default(); Self::BYTE_LEN];
312                    self.copy_to_le_bytes(&mut out_vec);
313                    out_vec
314                }
315            }
316        )+
317    };
318}
319
320#[allow(unused_variables)]
321gen_byterepr_impls_array!(
322    0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 48 64 96 128 256 512 1024 2048 4096
323);