1use core::{
4 concat,
5 num::{
6 NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroU128,
7 NonZeroU16, NonZeroU32, NonZeroU64,
8 },
9};
10
11#[rustfmt::skip]
13macro_rules! define_unaligned_newtype {
14 (
15 $(#[$attr:meta])*
16 $name:ident: $endian:ident $size:literal $prim:ty
17 ) => {
18 #[allow(non_camel_case_types)]
19 #[doc = concat!(
20 "A ",
21 endian_name!($endian),
22 "-endian unaligned `",
23 stringify!($prim),
24 "` with a guaranteed size of `",
25 stringify!($size),
26 "` and alignment of `1`.",
27 )]
28 $(#[$attr])*
29 #[repr(C, packed)]
30 pub struct $name($prim);
31 };
32}
33
34macro_rules! define_unaligned_signed_integer {
35 ($name:ident: $endian:ident $size:literal $prim:ident) => {
36 define_unaligned_newtype!(
37 #[cfg_attr(
38 feature = "zerocopy-0_8",
39 derive(
40 zerocopy_derive::FromBytes,
41 zerocopy_derive::IntoBytes,
42 zerocopy_derive::Immutable,
43 zerocopy_derive::KnownLayout,
44 zerocopy_derive::Unaligned,
45 ),
46 )]
47 $name: $endian $size $prim
48 );
49 impl_integer!($name: $endian $prim);
50 impl_signed_integer_traits!($name: $endian $prim);
51 };
52}
53
54macro_rules! define_unaligned_signed_integers {
55 ($($le:ident $be:ident: $size:literal $prim:ident),* $(,)?) => {
56 $(
57 define_unaligned_signed_integer!($le: little $size $prim);
58 define_unaligned_signed_integer!($be: big $size $prim);
59 )*
60 };
61}
62
63define_unaligned_signed_integers! {
64 i16_ule i16_ube: 2 i16,
65 i32_ule i32_ube: 4 i32,
66 i64_ule i64_ube: 8 i64,
67 i128_ule i128_ube: 16 i128,
68}
69
70macro_rules! define_unaligned_unsigned_integer {
71 ($name:ident: $endian:ident $size:literal $prim:ident) => {
72 define_unaligned_newtype!(
73 #[cfg_attr(
74 feature = "zerocopy-0_8",
75 derive(
76 zerocopy_derive::FromBytes,
77 zerocopy_derive::IntoBytes,
78 zerocopy_derive::Immutable,
79 zerocopy_derive::KnownLayout,
80 zerocopy_derive::Unaligned,
81 ),
82 )]
83 $name: $endian $size $prim
84 );
85 impl_integer!($name: $endian $prim);
86 impl_unsigned_integer_traits!($name: $endian $prim);
87 }
88}
89
90macro_rules! define_unaligned_unsigned_integers {
91 ($($le:ident $be:ident: $size:literal $prim:ident),* $(,)?) => {
92 $(
93 define_unaligned_unsigned_integer!($le: little $size $prim);
94 define_unaligned_unsigned_integer!($be: big $size $prim);
95 )*
96 };
97}
98
99define_unaligned_unsigned_integers! {
100 u16_ule u16_ube: 2 u16,
101 u32_ule u32_ube: 4 u32,
102 u64_ule u64_ube: 8 u64,
103 u128_ule u128_ube: 16 u128,
104}
105
106macro_rules! define_unaligned_float {
107 ($name:ident: $endian:ident $size:literal $prim:ty as $prim_int:ty) => {
108 define_unaligned_newtype!(
109 #[cfg_attr(
110 feature = "zerocopy-0_8",
111 derive(
112 zerocopy_derive::FromBytes,
113 zerocopy_derive::IntoBytes,
114 zerocopy_derive::Immutable,
115 zerocopy_derive::KnownLayout,
116 zerocopy_derive::Unaligned,
117 ),
118 )]
119 $name: $endian $size $prim
120 );
121 impl_float!($name: $endian $prim as $prim_int);
122 };
123}
124
125macro_rules! define_unaligned_floats {
126 ($(
127 $le:ident $be:ident:
128 $size:literal $prim:ty as $prim_int:ty
129 ),* $(,)?) => {
130 $(
131 define_unaligned_float!($le: little $size $prim as $prim_int);
132 define_unaligned_float!($be: big $size $prim as $prim_int);
133 )*
134 };
135}
136
137define_unaligned_floats! {
138 f32_ule f32_ube: 4 f32 as u32,
139 f64_ule f64_ube: 8 f64 as u64,
140}
141
142macro_rules! define_unaligned_char {
143 ($name:ident: $endian:ident) => {
144 define_unaligned_newtype!(
145 #[cfg_attr(
146 feature = "zerocopy-0_8",
147 derive(
148 zerocopy_derive::IntoBytes,
157 zerocopy_derive::Immutable,
158 zerocopy_derive::KnownLayout,
159 zerocopy_derive::Unaligned,
160 ),
161 )]
162 $name: $endian 4 u32
163 );
164 impl_char!($name: $endian);
165 };
166}
167
168define_unaligned_char!(char_ule: little);
169define_unaligned_char!(char_ube: big);
170
171macro_rules! define_unaligned_nonzero {
172 ($name:ident: $endian:ident $size:literal $prim:ty as $prim_int:ty) => {
173 define_unaligned_newtype!($name: $endian $size $prim);
174 impl_nonzero!($name: $endian $prim as $prim_int);
175
176 #[cfg(feature = "bytecheck")]
177 unsafe impl<C> bytecheck::CheckBytes<C> for $name
180 where
181 C: bytecheck::rancor::Fallible + ?Sized,
182 C::Error: bytecheck::rancor::Trace,
183 $prim: bytecheck::CheckBytes<C>,
184 {
185 #[inline]
186 unsafe fn check_bytes(
187 value: *const Self,
188 context: &mut C,
189 ) -> Result<(), C::Error> {
190 use bytecheck::rancor::ResultExt as _;
191
192 let value = unsafe {
196 value.cast::<$prim_int>().read_unaligned()
197 };
198 let ptr = (&value as *const $prim_int).cast::<$prim>();
199 unsafe {
202 <$prim>::check_bytes(ptr, context)
203 .with_trace(|| $crate::context::ValueCheckContext {
204 inner_name: core::stringify!($prim),
205 outer_name: core::stringify!($name),
206 })
207 }
208 }
209 }
210 };
211}
212
213macro_rules! define_unaligned_nonzeros {
214 ($(
215 $le:ident $be:ident:
216 $size:literal $prim:ty as $prim_int:ty
217 ),* $(,)?) => {
218 $(
219 define_unaligned_nonzero!($le: little $size $prim as $prim_int);
220 define_unaligned_nonzero!($be: big $size $prim as $prim_int);
221 )*
222 }
223}
224
225define_unaligned_nonzeros! {
226 NonZeroI16_ule NonZeroI16_ube: 2 NonZeroI16 as i16,
227 NonZeroI32_ule NonZeroI32_ube: 2 NonZeroI32 as i32,
228 NonZeroI64_ule NonZeroI64_ube: 4 NonZeroI64 as i64,
229 NonZeroI128_ule NonZeroI128_ube: 4 NonZeroI128 as i128,
230 NonZeroU16_ule NonZeroU16_ube: 8 NonZeroU16 as u16,
231 NonZeroU32_ule NonZeroU32_ube: 8 NonZeroU32 as u32,
232 NonZeroU64_ule NonZeroU64_ube: 16 NonZeroU64 as u64,
233 NonZeroU128_ule NonZeroU128_ube: 16 NonZeroU128 as u128,
234}
235
236#[cfg(test)]
237mod tests {
238 use core::mem::transmute;
239
240 use super::*;
241
242 #[test]
243 fn signed_integers() {
244 assert_size_align! {
245 i16_ube 2 1,
246 i16_ule 2 1,
247 i32_ube 4 1,
248 i32_ule 4 1,
249 i64_ube 8 1,
250 i64_ule 8 1,
251 i128_ube 16 1,
252 i128_ule 16 1,
253 }
254
255 unsafe {
256 assert_eq!(
258 [0x02, 0x01],
259 transmute::<_, [u8; 2]>(i16_ule::from_native(0x0102)),
260 );
261 assert_eq!(
262 [0x01, 0x02],
263 transmute::<_, [u8; 2]>(i16_ube::from_native(0x0102)),
264 );
265
266 assert_eq!(
268 [0x04, 0x03, 0x02, 0x01],
269 transmute::<_, [u8; 4]>(i32_ule::from_native(0x01020304)),
270 );
271 assert_eq!(
272 [0x01, 0x02, 0x03, 0x04],
273 transmute::<_, [u8; 4]>(i32_ube::from_native(0x01020304)),
274 );
275
276 assert_eq!(
278 [0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01],
279 transmute::<_, [u8; 8]>(i64_ule::from_native(
280 0x0102030405060708
281 )),
282 );
283 assert_eq!(
284 [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08],
285 transmute::<_, [u8; 8]>(i64_ube::from_native(
286 0x0102030405060708
287 )),
288 );
289
290 assert_eq!(
292 [
293 0x10, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
294 0x06, 0x05, 0x04, 0x03, 0x02, 0x01
295 ],
296 transmute::<_, [u8; 16]>(i128_ule::from_native(
297 0x0102030405060708090a0b0c0d0e0f10
298 )),
299 );
300 assert_eq!(
301 [
302 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
303 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10
304 ],
305 transmute::<_, [u8; 16]>(i128_ube::from_native(
306 0x0102030405060708090a0b0c0d0e0f10
307 )),
308 );
309 }
310 }
311
312 #[test]
313 fn unsigned_integers() {
314 assert_size_align! {
315 u16_ube 2 1,
316 u16_ule 2 1,
317 u32_ube 4 1,
318 u32_ule 4 1,
319 u64_ube 8 1,
320 u64_ule 8 1,
321 u128_ube 16 1,
322 u128_ule 16 1,
323 }
324
325 unsafe {
326 assert_eq!(
328 [0x02, 0x01],
329 transmute::<_, [u8; 2]>(u16_ule::from_native(0x0102)),
330 );
331 assert_eq!(
332 [0x01, 0x02],
333 transmute::<_, [u8; 2]>(u16_ube::from_native(0x0102)),
334 );
335
336 assert_eq!(
338 [0x04, 0x03, 0x02, 0x01],
339 transmute::<_, [u8; 4]>(u32_ule::from_native(0x01020304)),
340 );
341 assert_eq!(
342 [0x01, 0x02, 0x03, 0x04],
343 transmute::<_, [u8; 4]>(u32_ube::from_native(0x01020304)),
344 );
345
346 assert_eq!(
348 [0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01],
349 transmute::<_, [u8; 8]>(u64_ule::from_native(
350 0x0102030405060708
351 )),
352 );
353 assert_eq!(
354 [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08],
355 transmute::<_, [u8; 8]>(u64_ube::from_native(
356 0x0102030405060708
357 )),
358 );
359
360 assert_eq!(
362 [
363 0x10, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
364 0x06, 0x05, 0x04, 0x03, 0x02, 0x01
365 ],
366 transmute::<_, [u8; 16]>(u128_ule::from_native(
367 0x0102030405060708090a0b0c0d0e0f10
368 )),
369 );
370 assert_eq!(
371 [
372 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
373 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10
374 ],
375 transmute::<_, [u8; 16]>(u128_ube::from_native(
376 0x0102030405060708090a0b0c0d0e0f10
377 )),
378 );
379 }
380 }
381
382 #[test]
383 fn floats() {
384 assert_size_align! {
385 f32_ube 4 1,
386 f32_ule 4 1,
387 f64_ube 8 1,
388 f64_ule 8 1,
389 }
390
391 unsafe {
392 assert_eq!(
394 [0xdb, 0x0f, 0x49, 0x40],
395 transmute::<_, [u8; 4]>(f32_ule::from_native(
396 core::f32::consts::PI
397 )),
398 );
399 assert_eq!(
400 [0x40, 0x49, 0x0f, 0xdb],
401 transmute::<_, [u8; 4]>(f32_ube::from_native(
402 core::f32::consts::PI
403 )),
404 );
405
406 assert_eq!(
408 [0x18, 0x2d, 0x44, 0x54, 0xfb, 0x21, 0x09, 0x40],
409 transmute::<_, [u8; 8]>(f64_ule::from_native(
410 core::f64::consts::PI
411 )),
412 );
413 assert_eq!(
414 [0x40, 0x09, 0x21, 0xfb, 0x54, 0x44, 0x2d, 0x18],
415 transmute::<_, [u8; 8]>(f64_ube::from_native(
416 core::f64::consts::PI
417 )),
418 );
419
420 assert_eq!(
422 [0x89, 0xf3, 0x01, 0x00],
423 transmute::<_, [u8; 4]>(char_ule::from_native('🎉')),
424 );
425 assert_eq!(
426 [0x00, 0x01, 0xf3, 0x89],
427 transmute::<_, [u8; 4]>(char_ube::from_native('🎉')),
428 );
429 }
430 }
431
432 #[test]
433 fn signed_non_zero() {
434 assert_size_align! {
435 NonZeroI16_ule 2 1,
436 NonZeroI16_ube 2 1,
437 NonZeroI32_ule 4 1,
438 NonZeroI32_ube 4 1,
439 NonZeroI64_ule 8 1,
440 NonZeroI64_ube 8 1,
441 NonZeroI128_ule 16 1,
442 NonZeroI128_ube 16 1,
443 }
444
445 unsafe {
446 assert_eq!(
448 [0x02, 0x01],
449 transmute::<_, [u8; 2]>(NonZeroI16_ule::new_unchecked(0x0102)),
450 );
451 assert_eq!(
452 [0x01, 0x02],
453 transmute::<_, [u8; 2]>(NonZeroI16_ube::new_unchecked(0x0102)),
454 );
455
456 assert_eq!(
458 [0x04, 0x03, 0x02, 0x01],
459 transmute::<_, [u8; 4]>(NonZeroI32_ule::new_unchecked(
460 0x01020304
461 )),
462 );
463 assert_eq!(
464 [0x01, 0x02, 0x03, 0x04],
465 transmute::<_, [u8; 4]>(NonZeroI32_ube::new_unchecked(
466 0x01020304
467 )),
468 );
469
470 assert_eq!(
472 [0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01],
473 transmute::<_, [u8; 8]>(NonZeroI64_ule::new_unchecked(
474 0x0102030405060708
475 )),
476 );
477 assert_eq!(
478 [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08],
479 transmute::<_, [u8; 8]>(NonZeroI64_ube::new_unchecked(
480 0x0102030405060708
481 )),
482 );
483
484 assert_eq!(
486 [
487 0x10, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
488 0x06, 0x05, 0x04, 0x03, 0x02, 0x01
489 ],
490 transmute::<_, [u8; 16]>(NonZeroI128_ule::new_unchecked(
491 0x0102030405060708090a0b0c0d0e0f10
492 )),
493 );
494 assert_eq!(
495 [
496 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
497 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10
498 ],
499 transmute::<_, [u8; 16]>(NonZeroI128_ube::new_unchecked(
500 0x0102030405060708090a0b0c0d0e0f10
501 )),
502 );
503 }
504 }
505
506 #[test]
507 fn unsigned_non_zero() {
508 assert_size_align! {
509 NonZeroU16_ule 2 1,
510 NonZeroU16_ube 2 1,
511 NonZeroU32_ule 4 1,
512 NonZeroU32_ube 4 1,
513 NonZeroU64_ule 8 1,
514 NonZeroU64_ube 8 1,
515 NonZeroU128_ule 16 1,
516 NonZeroU128_ube 16 1,
517 }
518
519 unsafe {
520 assert_eq!(
522 [0x02, 0x01],
523 transmute::<_, [u8; 2]>(NonZeroU16_ule::new_unchecked(0x0102)),
524 );
525 assert_eq!(
526 [0x01, 0x02],
527 transmute::<_, [u8; 2]>(NonZeroU16_ube::new_unchecked(0x0102)),
528 );
529
530 assert_eq!(
532 [0x04, 0x03, 0x02, 0x01],
533 transmute::<_, [u8; 4]>(NonZeroU32_ule::new_unchecked(
534 0x01020304
535 )),
536 );
537 assert_eq!(
538 [0x01, 0x02, 0x03, 0x04],
539 transmute::<_, [u8; 4]>(NonZeroU32_ube::new_unchecked(
540 0x01020304
541 )),
542 );
543
544 assert_eq!(
546 [0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01],
547 transmute::<_, [u8; 8]>(NonZeroU64_ule::new_unchecked(
548 0x0102030405060708
549 )),
550 );
551 assert_eq!(
552 [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08],
553 transmute::<_, [u8; 8]>(NonZeroU64_ube::new_unchecked(
554 0x0102030405060708
555 )),
556 );
557
558 assert_eq!(
560 [
561 0x10, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
562 0x06, 0x05, 0x04, 0x03, 0x02, 0x01
563 ],
564 transmute::<_, [u8; 16]>(NonZeroU128_ule::new_unchecked(
565 0x0102030405060708090a0b0c0d0e0f10
566 )),
567 );
568 assert_eq!(
569 [
570 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
571 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10
572 ],
573 transmute::<_, [u8; 16]>(NonZeroU128_ube::new_unchecked(
574 0x0102030405060708090a0b0c0d0e0f10
575 )),
576 );
577 }
578 }
579}