1use std::num::*;
2use std::mem::{
3 MaybeUninit,
4 transmute_copy,
5};
6use bytemuck::Pod;
7
8pub trait ByteRepr: Sized + Pod + Clone {
10 const BYTE_LEN: usize;
12
13 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 fn from_le_bytes(b: &[u8]) -> Self;
26
27 fn copy_to_le_bytes(self, dest: &mut [u8]);
30
31 fn into_le_bytes(self) -> Vec<u8>;
33
34 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 fn from_be_bytes(b: &[u8]) -> Self;
47
48 fn copy_to_be_bytes(self, dest: &mut [u8]);
51
52 fn into_be_bytes(self) -> Vec<u8>;
54
55 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 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 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 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
95pub 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);