zerocopy/
macros.rs

1// Copyright 2024 The Fuchsia Authors
2//
3// Licensed under the 2-Clause BSD License <LICENSE-BSD or
4// https://opensource.org/license/bsd-2-clause>, Apache License, Version 2.0
5// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
6// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
7// This file may not be copied, modified, or distributed except according to
8// those terms.
9
10/// Safely transmutes a value of one type to a value of another type of the same
11/// size.
12///
13/// This macro behaves like an invocation of this function:
14///
15/// ```ignore
16/// const fn transmute<Src, Dst>(src: Src) -> Dst
17/// where
18///     Src: IntoBytes,
19///     Dst: FromBytes,
20///     size_of::<Src>() == size_of::<Dst>(),
21/// {
22/// # /*
23///     ...
24/// # */
25/// }
26/// ```
27///
28/// However, unlike a function, this macro can only be invoked when the types of
29/// `Src` and `Dst` are completely concrete. The types `Src` and `Dst` are
30/// inferred from the calling context; they cannot be explicitly specified in
31/// the macro invocation.
32///
33/// Note that the `Src` produced by the expression `$e` will *not* be dropped.
34/// Semantically, its bits will be copied into a new value of type `Dst`, the
35/// original `Src` will be forgotten, and the value of type `Dst` will be
36/// returned.
37///
38/// # `#![allow(shrink)]`
39///
40/// If `#![allow(shrink)]` is provided, `transmute!` additionally supports
41/// transmutations that shrink the size of the value; e.g.:
42///
43/// ```
44/// # use zerocopy::transmute;
45/// let u: u32 = transmute!(#![allow(shrink)] 0u64);
46/// assert_eq!(u, 0u32);
47/// ```
48///
49/// # Examples
50///
51/// ```
52/// # use zerocopy::transmute;
53/// let one_dimensional: [u8; 8] = [0, 1, 2, 3, 4, 5, 6, 7];
54///
55/// let two_dimensional: [[u8; 4]; 2] = transmute!(one_dimensional);
56///
57/// assert_eq!(two_dimensional, [[0, 1, 2, 3], [4, 5, 6, 7]]);
58/// ```
59///
60/// # Use in `const` contexts
61///
62/// This macro can be invoked in `const` contexts.
63#[macro_export]
64macro_rules! transmute {
65    // NOTE: This must be a macro (rather than a function with trait bounds)
66    // because there's no way, in a generic context, to enforce that two types
67    // have the same size. `core::mem::transmute` uses compiler magic to enforce
68    // this so long as the types are concrete.
69    (#![allow(shrink)] $e:expr) => {{
70        let mut e = $e;
71        if false {
72            // This branch, though never taken, ensures that the type of `e` is
73            // `IntoBytes` and that the type of the  outer macro invocation
74            // expression is `FromBytes`.
75
76            fn transmute<Src, Dst>(src: Src) -> Dst
77            where
78                Src: $crate::IntoBytes,
79                Dst: $crate::FromBytes,
80            {
81                let _ = src;
82                loop {}
83            }
84            loop {}
85            #[allow(unreachable_code)]
86            transmute(e)
87        } else {
88            use $crate::util::macro_util::core_reexport::mem::ManuallyDrop;
89
90            // NOTE: `repr(packed)` is important! It ensures that the size of
91            // `Transmute` won't be rounded up to accommodate `Src`'s or `Dst`'s
92            // alignment, which would break the size comparison logic below.
93            //
94            // As an example of why this is problematic, consider `Src = [u8;
95            // 5]`, `Dst = u32`. The total size of `Transmute<Src, Dst>` would
96            // be 8, and so we would reject a `[u8; 5]` to `u32` transmute as
97            // being size-increasing, which it isn't.
98            #[repr(C, packed)]
99            union Transmute<Src, Dst> {
100                src: ManuallyDrop<Src>,
101                dst: ManuallyDrop<Dst>,
102            }
103
104            // SAFETY: `Transmute` is a `reper(C)` union whose `src` field has
105            // type `ManuallyDrop<Src>`. Thus, the `src` field starts at byte
106            // offset 0 within `Transmute` [1]. `ManuallyDrop<T>` has the same
107            // layout and bit validity as `T`, so it is sound to transmute `Src`
108            // to `Transmute`.
109            //
110            // [1] https://doc.rust-lang.org/1.85.0/reference/type-layout.html#reprc-unions
111            //
112            // [2] Per https://doc.rust-lang.org/1.85.0/std/mem/struct.ManuallyDrop.html:
113            //
114            //   `ManuallyDrop<T>` is guaranteed to have the same layout and bit
115            //   validity as `T`
116            let u: Transmute<_, _> = unsafe {
117                // Clippy: We can't annotate the types; this macro is designed
118                // to infer the types from the calling context.
119                #[allow(clippy::missing_transmute_annotations)]
120                $crate::util::macro_util::core_reexport::mem::transmute(e)
121            };
122
123            if false {
124                // SAFETY: This code is never executed.
125                e = ManuallyDrop::into_inner(unsafe { u.src });
126                // Suppress the `unused_assignments` lint on the previous line.
127                let _ = e;
128                loop {}
129            } else {
130                // SAFETY: Per the safety comment on `let u` above, the `dst`
131                // field in `Transmute` starts at byte offset 0, and has the
132                // same layout and bit validity as `Dst`.
133                //
134                // Transmuting `Src` to `Transmute<Src, Dst>` above using
135                // `core::mem::transmute` ensures that `size_of::<Src>() ==
136                // size_of::<Transmute<Src, Dst>>()`. A `#[repr(C, packed)]`
137                // union has the maximum size of all of its fields [1], so this
138                // is equivalent to `size_of::<Src>() >= size_of::<Dst>()`.
139                //
140                // The outer `if`'s `false` branch ensures that `Src: IntoBytes`
141                // and `Dst: FromBytes`. This, combined with the size bound,
142                // ensures that this transmute is sound.
143                //
144                // [1] Per https://doc.rust-lang.org/1.85.0/reference/type-layout.html#reprc-unions:
145                //
146                //   The union will have a size of the maximum size of all of
147                //   its fields rounded to its alignment
148                let dst = unsafe { u.dst };
149                $crate::util::macro_util::must_use(ManuallyDrop::into_inner(dst))
150            }
151        }
152    }};
153    ($e:expr) => {{
154        let e = $e;
155        if false {
156            // This branch, though never taken, ensures that the type of `e` is
157            // `IntoBytes` and that the type of the  outer macro invocation
158            // expression is `FromBytes`.
159
160            fn transmute<Src, Dst>(src: Src) -> Dst
161            where
162                Src: $crate::IntoBytes,
163                Dst: $crate::FromBytes,
164            {
165                let _ = src;
166                loop {}
167            }
168            loop {}
169            #[allow(unreachable_code)]
170            transmute(e)
171        } else {
172            // SAFETY: `core::mem::transmute` ensures that the type of `e` and
173            // the type of this macro invocation expression have the same size.
174            // We know this transmute is safe thanks to the `IntoBytes` and
175            // `FromBytes` bounds enforced by the `false` branch.
176            let u = unsafe {
177                // Clippy: We can't annotate the types; this macro is designed
178                // to infer the types from the calling context.
179                #[allow(clippy::missing_transmute_annotations, unnecessary_transmutes)]
180                $crate::util::macro_util::core_reexport::mem::transmute(e)
181            };
182            $crate::util::macro_util::must_use(u)
183        }
184    }};
185}
186
187/// Safely transmutes a mutable or immutable reference of one type to an
188/// immutable reference of another type of the same size and compatible
189/// alignment.
190///
191/// This macro behaves like an invocation of this function:
192///
193/// ```ignore
194/// fn transmute_ref<'src, 'dst, Src, Dst>(src: &'src Src) -> &'dst Dst
195/// where
196///     'src: 'dst,
197///     Src: IntoBytes + Immutable + ?Sized,
198///     Dst: FromBytes + Immutable + ?Sized,
199///     align_of::<Src>() >= align_of::<Dst>(),
200///     size_compatible::<Src, Dst>(),
201/// {
202/// # /*
203///     ...
204/// # */
205/// }
206/// ```
207///
208/// The types `Src` and `Dst` are inferred from the calling context; they cannot
209/// be explicitly specified in the macro invocation.
210///
211/// # Size compatibility
212///
213/// `transmute_ref!` supports transmuting between `Sized` types or between
214/// unsized (i.e., `?Sized`) types. It supports any transmutation that preserves
215/// the number of bytes of the referent, even if doing so requires updating the
216/// metadata stored in an unsized "fat" reference:
217///
218/// ```
219/// # use zerocopy::transmute_ref;
220/// # use core::mem::size_of_val; // Not in the prelude on our MSRV
221/// let src: &[[u8; 2]] = &[[0, 1], [2, 3]][..];
222/// let dst: &[u8] = transmute_ref!(src);
223///
224/// assert_eq!(src.len(), 2);
225/// assert_eq!(dst.len(), 4);
226/// assert_eq!(dst, [0, 1, 2, 3]);
227/// assert_eq!(size_of_val(src), size_of_val(dst));
228/// ```
229///
230/// # Errors
231///
232/// Violations of the alignment and size compatibility checks are detected
233/// *after* the compiler performs monomorphization. This has two important
234/// consequences.
235///
236/// First, it means that generic code will *never* fail these conditions:
237///
238/// ```
239/// # use zerocopy::{transmute_ref, FromBytes, IntoBytes, Immutable};
240/// fn transmute_ref<Src, Dst>(src: &Src) -> &Dst
241/// where
242///     Src: IntoBytes + Immutable,
243///     Dst: FromBytes + Immutable,
244/// {
245///     transmute_ref!(src)
246/// }
247/// ```
248///
249/// Instead, failures will only be detected once generic code is instantiated
250/// with concrete types:
251///
252/// ```compile_fail,E0080
253/// # use zerocopy::{transmute_ref, FromBytes, IntoBytes, Immutable};
254/// #
255/// # fn transmute_ref<Src, Dst>(src: &Src) -> &Dst
256/// # where
257/// #     Src: IntoBytes + Immutable,
258/// #     Dst: FromBytes + Immutable,
259/// # {
260/// #     transmute_ref!(src)
261/// # }
262/// let src: &u16 = &0;
263/// let dst: &u8 = transmute_ref(src);
264/// ```
265///
266/// Second, the fact that violations are detected after monomorphization means
267/// that `cargo check` will usually not detect errors, even when types are
268/// concrete. Instead, `cargo build` must be used to detect such errors.
269///
270/// # Examples
271///
272/// Transmuting between `Sized` types:
273///
274/// ```
275/// # use zerocopy::transmute_ref;
276/// let one_dimensional: [u8; 8] = [0, 1, 2, 3, 4, 5, 6, 7];
277///
278/// let two_dimensional: &[[u8; 4]; 2] = transmute_ref!(&one_dimensional);
279///
280/// assert_eq!(two_dimensional, &[[0, 1, 2, 3], [4, 5, 6, 7]]);
281/// ```
282///
283/// Transmuting between unsized types:
284///
285/// ```
286/// # use {zerocopy::*, zerocopy_derive::*};
287/// # type u16 = zerocopy::byteorder::native_endian::U16;
288/// # type u32 = zerocopy::byteorder::native_endian::U32;
289/// #[derive(KnownLayout, FromBytes, IntoBytes, Immutable)]
290/// #[repr(C)]
291/// struct SliceDst<T, U> {
292///     t: T,
293///     u: [U],
294/// }
295///
296/// type Src = SliceDst<u32, u16>;
297/// type Dst = SliceDst<u16, u8>;
298///
299/// let src = Src::ref_from_bytes(&[0, 1, 2, 3, 4, 5, 6, 7]).unwrap();
300/// let dst: &Dst = transmute_ref!(src);
301///
302/// assert_eq!(src.t.as_bytes(), [0, 1, 2, 3]);
303/// assert_eq!(src.u.len(), 2);
304/// assert_eq!(src.u.as_bytes(), [4, 5, 6, 7]);
305///
306/// assert_eq!(dst.t.as_bytes(), [0, 1]);
307/// assert_eq!(dst.u, [2, 3, 4, 5, 6, 7]);
308/// ```
309///
310/// # Use in `const` contexts
311///
312/// This macro can be invoked in `const` contexts only when `Src: Sized` and
313/// `Dst: Sized`.
314#[macro_export]
315macro_rules! transmute_ref {
316    ($e:expr) => {{
317        // NOTE: This must be a macro (rather than a function with trait bounds)
318        // because there's no way, in a generic context, to enforce that two
319        // types have the same size or alignment.
320
321        // Ensure that the source type is a reference or a mutable reference
322        // (note that mutable references are implicitly reborrowed here).
323        let e: &_ = $e;
324
325        #[allow(unused, clippy::diverging_sub_expression)]
326        if false {
327            // This branch, though never taken, ensures that the type of `e` is
328            // `&T` where `T: IntoBytes + Immutable`, and that the type of this
329            // macro expression is `&U` where `U: FromBytes + Immutable`.
330
331            struct AssertSrcIsIntoBytes<'a, T: ?::core::marker::Sized + $crate::IntoBytes>(&'a T);
332            struct AssertSrcIsImmutable<'a, T: ?::core::marker::Sized + $crate::Immutable>(&'a T);
333            struct AssertDstIsFromBytes<'a, U: ?::core::marker::Sized + $crate::FromBytes>(&'a U);
334            struct AssertDstIsImmutable<'a, T: ?::core::marker::Sized + $crate::Immutable>(&'a T);
335
336            let _ = AssertSrcIsIntoBytes(e);
337            let _ = AssertSrcIsImmutable(e);
338
339            if true {
340                #[allow(unused, unreachable_code)]
341                let u = AssertDstIsFromBytes(loop {});
342                u.0
343            } else {
344                #[allow(unused, unreachable_code)]
345                let u = AssertDstIsImmutable(loop {});
346                u.0
347            }
348        } else {
349            use $crate::util::macro_util::TransmuteRefDst;
350            let t = $crate::util::macro_util::Wrap::new(e);
351            // SAFETY: The `if false` branch ensures that:
352            // - `Src: IntoBytes + Immutable`
353            // - `Dst: FromBytes + Immutable`
354            unsafe {
355                t.transmute_ref()
356            }
357        }
358    }}
359}
360
361/// Safely transmutes a mutable reference of one type to a mutable reference of
362/// another type of the same size and compatible alignment.
363///
364/// This macro behaves like an invocation of this function:
365///
366/// ```ignore
367/// const fn transmute_mut<'src, 'dst, Src, Dst>(src: &'src mut Src) -> &'dst mut Dst
368/// where
369///     'src: 'dst,
370///     Src: FromBytes + IntoBytes,
371///     Dst: FromBytes + IntoBytes,
372///     align_of::<Src>() >= align_of::<Dst>(),
373///     size_compatible::<Src, Dst>(),
374/// {
375/// # /*
376///     ...
377/// # */
378/// }
379/// ```
380///
381/// The types `Src` and `Dst` are inferred from the calling context; they cannot
382/// be explicitly specified in the macro invocation.
383///
384/// # Size compatibility
385///
386/// `transmute_mut!` supports transmuting between `Sized` types or between
387/// unsized (i.e., `?Sized`) types. It supports any transmutation that preserves
388/// the number of bytes of the referent, even if doing so requires updating the
389/// metadata stored in an unsized "fat" reference:
390///
391/// ```
392/// # use zerocopy::transmute_mut;
393/// # use core::mem::size_of_val; // Not in the prelude on our MSRV
394/// let src: &mut [[u8; 2]] = &mut [[0, 1], [2, 3]][..];
395/// let dst: &mut [u8] = transmute_mut!(src);
396///
397/// assert_eq!(dst.len(), 4);
398/// assert_eq!(dst, [0, 1, 2, 3]);
399/// let dst_size = size_of_val(dst);
400/// assert_eq!(src.len(), 2);
401/// assert_eq!(size_of_val(src), dst_size);
402/// ```
403///
404/// # Errors
405///
406/// Violations of the alignment and size compatibility checks are detected
407/// *after* the compiler performs monomorphization. This has two important
408/// consequences.
409///
410/// First, it means that generic code will *never* fail these conditions:
411///
412/// ```
413/// # use zerocopy::{transmute_mut, FromBytes, IntoBytes, Immutable};
414/// fn transmute_mut<Src, Dst>(src: &mut Src) -> &mut Dst
415/// where
416///     Src: FromBytes + IntoBytes,
417///     Dst: FromBytes + IntoBytes,
418/// {
419///     transmute_mut!(src)
420/// }
421/// ```
422///
423/// Instead, failures will only be detected once generic code is instantiated
424/// with concrete types:
425///
426/// ```compile_fail,E0080
427/// # use zerocopy::{transmute_mut, FromBytes, IntoBytes, Immutable};
428/// #
429/// # fn transmute_mut<Src, Dst>(src: &mut Src) -> &mut Dst
430/// # where
431/// #     Src: FromBytes + IntoBytes,
432/// #     Dst: FromBytes + IntoBytes,
433/// # {
434/// #     transmute_mut!(src)
435/// # }
436/// let src: &mut u16 = &mut 0;
437/// let dst: &mut u8 = transmute_mut(src);
438/// ```
439///
440/// Second, the fact that violations are detected after monomorphization means
441/// that `cargo check` will usually not detect errors, even when types are
442/// concrete. Instead, `cargo build` must be used to detect such errors.
443///
444///
445/// # Examples
446///
447/// Transmuting between `Sized` types:
448///
449/// ```
450/// # use zerocopy::transmute_mut;
451/// let mut one_dimensional: [u8; 8] = [0, 1, 2, 3, 4, 5, 6, 7];
452///
453/// let two_dimensional: &mut [[u8; 4]; 2] = transmute_mut!(&mut one_dimensional);
454///
455/// assert_eq!(two_dimensional, &[[0, 1, 2, 3], [4, 5, 6, 7]]);
456///
457/// two_dimensional.reverse();
458///
459/// assert_eq!(one_dimensional, [4, 5, 6, 7, 0, 1, 2, 3]);
460/// ```
461///
462/// Transmuting between unsized types:
463///
464/// ```
465/// # use {zerocopy::*, zerocopy_derive::*};
466/// # type u16 = zerocopy::byteorder::native_endian::U16;
467/// # type u32 = zerocopy::byteorder::native_endian::U32;
468/// #[derive(KnownLayout, FromBytes, IntoBytes, Immutable)]
469/// #[repr(C)]
470/// struct SliceDst<T, U> {
471///     t: T,
472///     u: [U],
473/// }
474///
475/// type Src = SliceDst<u32, u16>;
476/// type Dst = SliceDst<u16, u8>;
477///
478/// let mut bytes = [0, 1, 2, 3, 4, 5, 6, 7];
479/// let src = Src::mut_from_bytes(&mut bytes[..]).unwrap();
480/// let dst: &mut Dst = transmute_mut!(src);
481///
482/// assert_eq!(dst.t.as_bytes(), [0, 1]);
483/// assert_eq!(dst.u, [2, 3, 4, 5, 6, 7]);
484///
485/// assert_eq!(src.t.as_bytes(), [0, 1, 2, 3]);
486/// assert_eq!(src.u.len(), 2);
487/// assert_eq!(src.u.as_bytes(), [4, 5, 6, 7]);
488///
489/// ```
490#[macro_export]
491macro_rules! transmute_mut {
492    ($e:expr) => {{
493        // NOTE: This must be a macro (rather than a function with trait bounds)
494        // because, for backwards-compatibility on v0.8.x, we use the autoref
495        // specialization trick to dispatch to different `transmute_mut`
496        // implementations: one which doesn't require `Src: KnownLayout + Dst:
497        // KnownLayout` when `Src: Sized + Dst: Sized`, and one which requires
498        // `KnownLayout` bounds otherwise.
499
500        // Ensure that the source type is a mutable reference.
501        let e: &mut _ = $e;
502
503        #[allow(unused)]
504        use $crate::util::macro_util::TransmuteMutDst as _;
505        let t = $crate::util::macro_util::Wrap::new(e);
506        t.transmute_mut()
507    }}
508}
509
510/// Conditionally transmutes a value of one type to a value of another type of
511/// the same size.
512///
513/// This macro behaves like an invocation of this function:
514///
515/// ```ignore
516/// fn try_transmute<Src, Dst>(src: Src) -> Result<Dst, ValidityError<Src, Dst>>
517/// where
518///     Src: IntoBytes,
519///     Dst: TryFromBytes,
520///     size_of::<Src>() == size_of::<Dst>(),
521/// {
522/// # /*
523///     ...
524/// # */
525/// }
526/// ```
527///
528/// However, unlike a function, this macro can only be invoked when the types of
529/// `Src` and `Dst` are completely concrete. The types `Src` and `Dst` are
530/// inferred from the calling context; they cannot be explicitly specified in
531/// the macro invocation.
532///
533/// Note that the `Src` produced by the expression `$e` will *not* be dropped.
534/// Semantically, its bits will be copied into a new value of type `Dst`, the
535/// original `Src` will be forgotten, and the value of type `Dst` will be
536/// returned.
537///
538/// # Examples
539///
540/// ```
541/// # use zerocopy::*;
542/// // 0u8 → bool = false
543/// assert_eq!(try_transmute!(0u8), Ok(false));
544///
545/// // 1u8 → bool = true
546///  assert_eq!(try_transmute!(1u8), Ok(true));
547///
548/// // 2u8 → bool = error
549/// assert!(matches!(
550///     try_transmute!(2u8),
551///     Result::<bool, _>::Err(ValidityError { .. })
552/// ));
553/// ```
554#[macro_export]
555macro_rules! try_transmute {
556    ($e:expr) => {{
557        // NOTE: This must be a macro (rather than a function with trait bounds)
558        // because there's no way, in a generic context, to enforce that two
559        // types have the same size. `core::mem::transmute` uses compiler magic
560        // to enforce this so long as the types are concrete.
561
562        let e = $e;
563        if false {
564            // Check that the sizes of the source and destination types are
565            // equal.
566
567            // SAFETY: This code is never executed.
568            Ok(unsafe {
569                // Clippy: We can't annotate the types; this macro is designed
570                // to infer the types from the calling context.
571                #[allow(clippy::missing_transmute_annotations)]
572                $crate::util::macro_util::core_reexport::mem::transmute(e)
573            })
574        } else {
575            $crate::util::macro_util::try_transmute::<_, _>(e)
576        }
577    }}
578}
579
580/// Conditionally transmutes a mutable or immutable reference of one type to an
581/// immutable reference of another type of the same size and compatible
582/// alignment.
583///
584/// This macro behaves like an invocation of this function:
585///
586/// ```ignore
587/// fn try_transmute_ref<Src, Dst>(src: &Src) -> Result<&Dst, ValidityError<&Src, Dst>>
588/// where
589///     Src: IntoBytes + Immutable,
590///     Dst: TryFromBytes + Immutable,
591///     size_of::<Src>() == size_of::<Dst>(),
592///     align_of::<Src>() >= align_of::<Dst>(),
593/// {
594/// # /*
595///     ...
596/// # */
597/// }
598/// ```
599///
600/// However, unlike a function, this macro can only be invoked when the types of
601/// `Src` and `Dst` are completely concrete. The types `Src` and `Dst` are
602/// inferred from the calling context; they cannot be explicitly specified in
603/// the macro invocation.
604///
605/// # Examples
606///
607/// ```
608/// # use zerocopy::*;
609/// // 0u8 → bool = false
610/// assert_eq!(try_transmute_ref!(&0u8), Ok(&false));
611///
612/// // 1u8 → bool = true
613///  assert_eq!(try_transmute_ref!(&1u8), Ok(&true));
614///
615/// // 2u8 → bool = error
616/// assert!(matches!(
617///     try_transmute_ref!(&2u8),
618///     Result::<&bool, _>::Err(ValidityError { .. })
619/// ));
620/// ```
621///
622/// # Alignment increase error message
623///
624/// Because of limitations on macros, the error message generated when
625/// `try_transmute_ref!` is used to transmute from a type of lower alignment to
626/// a type of higher alignment is somewhat confusing. For example, the following
627/// code:
628///
629/// ```compile_fail
630/// let increase_alignment: Result<&u16, _> = zerocopy::try_transmute_ref!(&[0u8; 2]);
631/// ```
632///
633/// ...generates the following error:
634///
635/// ```text
636/// error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
637///  --> example.rs:1:47
638///   |
639/// 1 |     let increase_alignment: Result<&u16, _> = zerocopy::try_transmute_ref!(&[0u8; 2]);
640///   |                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
641///   |
642///   = note: source type: `AlignOf<[u8; 2]>` (8 bits)
643///   = note: target type: `MaxAlignsOf<[u8; 2], u16>` (16 bits)
644///   = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `zerocopy::try_transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)/// ```
645/// ```
646///
647/// This is saying that `max(align_of::<T>(), align_of::<U>()) !=
648/// align_of::<T>()`, which is equivalent to `align_of::<T>() <
649/// align_of::<U>()`.
650#[macro_export]
651macro_rules! try_transmute_ref {
652    ($e:expr) => {{
653        // NOTE: This must be a macro (rather than a function with trait bounds)
654        // because there's no way, in a generic context, to enforce that two
655        // types have the same size. `core::mem::transmute` uses compiler magic
656        // to enforce this so long as the types are concrete.
657
658        // Ensure that the source type is a reference or a mutable reference
659        // (note that mutable references are implicitly reborrowed here).
660        let e: &_ = $e;
661
662        #[allow(unreachable_code, unused, clippy::diverging_sub_expression)]
663        if false {
664            // This branch, though never taken, ensures that `size_of::<T>() ==
665            // size_of::<U>()` and that that `align_of::<T>() >=
666            // align_of::<U>()`.
667
668            // `t` is inferred to have type `T` because it's assigned to `e` (of
669            // type `&T`) as `&t`.
670            let mut t = loop {};
671            e = &t;
672
673            // `u` is inferred to have type `U` because it's used as `Ok(&u)` as
674            // the value returned from this branch.
675            let u;
676
677            $crate::assert_size_eq!(t, u);
678            $crate::assert_align_gt_eq!(t, u);
679
680            Ok(&u)
681        } else {
682            $crate::util::macro_util::try_transmute_ref::<_, _>(e)
683        }
684    }}
685}
686
687/// Conditionally transmutes a mutable reference of one type to a mutable
688/// reference of another type of the same size and compatible alignment.
689///
690/// This macro behaves like an invocation of this function:
691///
692/// ```ignore
693/// fn try_transmute_mut<Src, Dst>(src: &mut Src) -> Result<&mut Dst, ValidityError<&mut Src, Dst>>
694/// where
695///     Src: FromBytes + IntoBytes,
696///     Dst: TryFromBytes + IntoBytes,
697///     size_of::<Src>() == size_of::<Dst>(),
698///     align_of::<Src>() >= align_of::<Dst>(),
699/// {
700/// # /*
701///     ...
702/// # */
703/// }
704/// ```
705///
706/// However, unlike a function, this macro can only be invoked when the types of
707/// `Src` and `Dst` are completely concrete. The types `Src` and `Dst` are
708/// inferred from the calling context; they cannot be explicitly specified in
709/// the macro invocation.
710///
711/// # Examples
712///
713/// ```
714/// # use zerocopy::*;
715/// // 0u8 → bool = false
716/// let src = &mut 0u8;
717/// assert_eq!(try_transmute_mut!(src), Ok(&mut false));
718///
719/// // 1u8 → bool = true
720/// let src = &mut 1u8;
721///  assert_eq!(try_transmute_mut!(src), Ok(&mut true));
722///
723/// // 2u8 → bool = error
724/// let src = &mut 2u8;
725/// assert!(matches!(
726///     try_transmute_mut!(src),
727///     Result::<&mut bool, _>::Err(ValidityError { .. })
728/// ));
729/// ```
730///
731/// # Alignment increase error message
732///
733/// Because of limitations on macros, the error message generated when
734/// `try_transmute_ref!` is used to transmute from a type of lower alignment to
735/// a type of higher alignment is somewhat confusing. For example, the following
736/// code:
737///
738/// ```compile_fail
739/// let src = &mut [0u8; 2];
740/// let increase_alignment: Result<&mut u16, _> = zerocopy::try_transmute_mut!(src);
741/// ```
742///
743/// ...generates the following error:
744///
745/// ```text
746/// error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
747///  --> example.rs:2:51
748///   |
749/// 2 |     let increase_alignment: Result<&mut u16, _> = zerocopy::try_transmute_mut!(src);
750///   |                                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
751///   |
752///   = note: source type: `AlignOf<[u8; 2]>` (8 bits)
753///   = note: target type: `MaxAlignsOf<[u8; 2], u16>` (16 bits)
754///   = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `zerocopy::try_transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
755/// ```
756///
757/// This is saying that `max(align_of::<T>(), align_of::<U>()) !=
758/// align_of::<T>()`, which is equivalent to `align_of::<T>() <
759/// align_of::<U>()`.
760#[macro_export]
761macro_rules! try_transmute_mut {
762    ($e:expr) => {{
763        // NOTE: This must be a macro (rather than a function with trait bounds)
764        // because there's no way, in a generic context, to enforce that two
765        // types have the same size. `core::mem::transmute` uses compiler magic
766        // to enforce this so long as the types are concrete.
767
768        // Ensure that the source type is a mutable reference.
769        let e: &mut _ = $e;
770
771        #[allow(unreachable_code, unused, clippy::diverging_sub_expression)]
772        if false {
773            // This branch, though never taken, ensures that `size_of::<T>() ==
774            // size_of::<U>()` and that that `align_of::<T>() >=
775            // align_of::<U>()`.
776
777            // `t` is inferred to have type `T` because it's assigned to `e` (of
778            // type `&mut T`) as `&mut t`.
779            let mut t = loop {};
780            e = &mut t;
781
782            // `u` is inferred to have type `U` because it's used as `Ok(&mut
783            // u)` as the value returned from this branch.
784            let u;
785
786            $crate::assert_size_eq!(t, u);
787            $crate::assert_align_gt_eq!(t, u);
788
789            Ok(&mut u)
790        } else {
791            $crate::util::macro_util::try_transmute_mut::<_, _>(e)
792        }
793    }}
794}
795
796/// Includes a file and safely transmutes it to a value of an arbitrary type.
797///
798/// The file will be included as a byte array, `[u8; N]`, which will be
799/// transmuted to another type, `T`. `T` is inferred from the calling context,
800/// and must implement [`FromBytes`].
801///
802/// The file is located relative to the current file (similarly to how modules
803/// are found). The provided path is interpreted in a platform-specific way at
804/// compile time. So, for instance, an invocation with a Windows path containing
805/// backslashes `\` would not compile correctly on Unix.
806///
807/// `include_value!` is ignorant of byte order. For byte order-aware types, see
808/// the [`byteorder`] module.
809///
810/// [`FromBytes`]: crate::FromBytes
811/// [`byteorder`]: crate::byteorder
812///
813/// # Examples
814///
815/// Assume there are two files in the same directory with the following
816/// contents:
817///
818/// File `data` (no trailing newline):
819///
820/// ```text
821/// abcd
822/// ```
823///
824/// File `main.rs`:
825///
826/// ```rust
827/// use zerocopy::include_value;
828/// # macro_rules! include_value {
829/// # ($file:expr) => { zerocopy::include_value!(concat!("../testdata/include_value/", $file)) };
830/// # }
831///
832/// fn main() {
833///     let as_u32: u32 = include_value!("data");
834///     assert_eq!(as_u32, u32::from_ne_bytes([b'a', b'b', b'c', b'd']));
835///     let as_i32: i32 = include_value!("data");
836///     assert_eq!(as_i32, i32::from_ne_bytes([b'a', b'b', b'c', b'd']));
837/// }
838/// ```
839///
840/// # Use in `const` contexts
841///
842/// This macro can be invoked in `const` contexts.
843#[doc(alias("include_bytes", "include_data", "include_type"))]
844#[macro_export]
845macro_rules! include_value {
846    ($file:expr $(,)?) => {
847        $crate::transmute!(*::core::include_bytes!($file))
848    };
849}
850
851#[doc(hidden)]
852#[macro_export]
853macro_rules! cryptocorrosion_derive_traits {
854    (
855        #[repr($repr:ident)]
856        $(#[$attr:meta])*
857        $vis:vis struct $name:ident $(<$($tyvar:ident),*>)?
858        $(
859            (
860                $($tuple_field_vis:vis $tuple_field_ty:ty),*
861            );
862        )?
863
864        $(
865            {
866                $($field_vis:vis $field_name:ident: $field_ty:ty,)*
867            }
868        )?
869    ) => {
870        $crate::cryptocorrosion_derive_traits!(@assert_allowed_struct_repr #[repr($repr)]);
871
872        $(#[$attr])*
873        #[repr($repr)]
874        $vis struct $name $(<$($tyvar),*>)?
875        $(
876            (
877                $($tuple_field_vis $tuple_field_ty),*
878            );
879        )?
880
881        $(
882            {
883                $($field_vis $field_name: $field_ty,)*
884            }
885        )?
886
887        // SAFETY: See inline.
888        unsafe impl $(<$($tyvar),*>)? $crate::TryFromBytes for $name$(<$($tyvar),*>)?
889        where
890            $(
891                $($tuple_field_ty: $crate::FromBytes,)*
892            )?
893
894            $(
895                $($field_ty: $crate::FromBytes,)*
896            )?
897        {
898            fn is_bit_valid<A>(_c: $crate::Maybe<'_, Self, A>) -> bool
899            where
900                A: $crate::pointer::invariant::Reference
901            {
902                // SAFETY: This macro only accepts `#[repr(C)]` and
903                // `#[repr(transparent)]` structs, and this `impl` block
904                // requires all field types to be `FromBytes`. Thus, all
905                // initialized byte sequences constitutes valid instances of
906                // `Self`.
907                true
908            }
909
910            fn only_derive_is_allowed_to_implement_this_trait() {}
911        }
912
913        // SAFETY: This macro only accepts `#[repr(C)]` and
914        // `#[repr(transparent)]` structs, and this `impl` block requires all
915        // field types to be `FromBytes`, which is a sub-trait of `FromZeros`.
916        unsafe impl $(<$($tyvar),*>)? $crate::FromZeros for $name$(<$($tyvar),*>)?
917        where
918            $(
919                $($tuple_field_ty: $crate::FromBytes,)*
920            )?
921
922            $(
923                $($field_ty: $crate::FromBytes,)*
924            )?
925        {
926            fn only_derive_is_allowed_to_implement_this_trait() {}
927        }
928
929        // SAFETY: This macro only accepts `#[repr(C)]` and
930        // `#[repr(transparent)]` structs, and this `impl` block requires all
931        // field types to be `FromBytes`.
932        unsafe impl $(<$($tyvar),*>)? $crate::FromBytes for $name$(<$($tyvar),*>)?
933        where
934            $(
935                $($tuple_field_ty: $crate::FromBytes,)*
936            )?
937
938            $(
939                $($field_ty: $crate::FromBytes,)*
940            )?
941        {
942            fn only_derive_is_allowed_to_implement_this_trait() {}
943        }
944
945        // SAFETY: This macro only accepts `#[repr(C)]` and
946        // `#[repr(transparent)]` structs, this `impl` block requires all field
947        // types to be `IntoBytes`, and a padding check is used to ensures that
948        // there are no padding bytes.
949        unsafe impl $(<$($tyvar),*>)? $crate::IntoBytes for $name$(<$($tyvar),*>)?
950        where
951            $(
952                $($tuple_field_ty: $crate::IntoBytes,)*
953            )?
954
955            $(
956                $($field_ty: $crate::IntoBytes,)*
957            )?
958
959            (): $crate::util::macro_util::PaddingFree<
960                Self,
961                {
962                    $crate::cryptocorrosion_derive_traits!(
963                        @struct_padding_check #[repr($repr)]
964                        $(($($tuple_field_ty),*))?
965                        $({$($field_ty),*})?
966                    )
967                },
968            >,
969        {
970            fn only_derive_is_allowed_to_implement_this_trait() {}
971        }
972
973        // SAFETY: This macro only accepts `#[repr(C)]` and
974        // `#[repr(transparent)]` structs, and this `impl` block requires all
975        // field types to be `Immutable`.
976        unsafe impl $(<$($tyvar),*>)? $crate::Immutable for $name$(<$($tyvar),*>)?
977        where
978            $(
979                $($tuple_field_ty: $crate::Immutable,)*
980            )?
981
982            $(
983                $($field_ty: $crate::Immutable,)*
984            )?
985        {
986            fn only_derive_is_allowed_to_implement_this_trait() {}
987        }
988    };
989    (@assert_allowed_struct_repr #[repr(transparent)]) => {};
990    (@assert_allowed_struct_repr #[repr(C)]) => {};
991    (@assert_allowed_struct_repr #[$_attr:meta]) => {
992        compile_error!("repr must be `#[repr(transparent)]` or `#[repr(C)]`");
993    };
994    (
995        @struct_padding_check #[repr(transparent)]
996        $(($($tuple_field_ty:ty),*))?
997        $({$($field_ty:ty),*})?
998    ) => {
999        // SAFETY: `#[repr(transparent)]` structs cannot have the same layout as
1000        // their single non-zero-sized field, and so cannot have any padding
1001        // outside of that field.
1002        false
1003    };
1004    (
1005        @struct_padding_check #[repr(C)]
1006        $(($($tuple_field_ty:ty),*))?
1007        $({$($field_ty:ty),*})?
1008    ) => {
1009        $crate::struct_has_padding!(
1010            Self,
1011            [
1012                $($($tuple_field_ty),*)?
1013                $($($field_ty),*)?
1014            ]
1015        )
1016    };
1017    (
1018        #[repr(C)]
1019        $(#[$attr:meta])*
1020        $vis:vis union $name:ident {
1021            $(
1022                $field_name:ident: $field_ty:ty,
1023            )*
1024        }
1025    ) => {
1026        $(#[$attr])*
1027        #[repr(C)]
1028        $vis union $name {
1029            $(
1030                $field_name: $field_ty,
1031            )*
1032        }
1033
1034        // SAFETY: See inline.
1035        unsafe impl $crate::TryFromBytes for $name
1036        where
1037            $(
1038                $field_ty: $crate::FromBytes,
1039            )*
1040        {
1041            fn is_bit_valid<A>(_c: $crate::Maybe<'_, Self, A>) -> bool
1042            where
1043                A: $crate::pointer::invariant::Reference
1044            {
1045                // SAFETY: This macro only accepts `#[repr(C)]` unions, and this
1046                // `impl` block requires all field types to be `FromBytes`.
1047                // Thus, all initialized byte sequences constitutes valid
1048                // instances of `Self`.
1049                true
1050            }
1051
1052            fn only_derive_is_allowed_to_implement_this_trait() {}
1053        }
1054
1055        // SAFETY: This macro only accepts `#[repr(C)]` unions, and this `impl`
1056        // block requires all field types to be `FromBytes`, which is a
1057        // sub-trait of `FromZeros`.
1058        unsafe impl $crate::FromZeros for $name
1059        where
1060            $(
1061                $field_ty: $crate::FromBytes,
1062            )*
1063        {
1064            fn only_derive_is_allowed_to_implement_this_trait() {}
1065        }
1066
1067        // SAFETY: This macro only accepts `#[repr(C)]` unions, and this `impl`
1068        // block requires all field types to be `FromBytes`.
1069        unsafe impl $crate::FromBytes for $name
1070        where
1071            $(
1072                $field_ty: $crate::FromBytes,
1073            )*
1074        {
1075            fn only_derive_is_allowed_to_implement_this_trait() {}
1076        }
1077
1078        // SAFETY: This macro only accepts `#[repr(C)]` unions, this `impl`
1079        // block requires all field types to be `IntoBytes`, and a padding check
1080        // is used to ensures that there are no padding bytes before or after
1081        // any field.
1082        unsafe impl $crate::IntoBytes for $name
1083        where
1084            $(
1085                $field_ty: $crate::IntoBytes,
1086            )*
1087            (): $crate::util::macro_util::PaddingFree<
1088                Self,
1089                {
1090                    $crate::union_has_padding!(
1091                        Self,
1092                        [$($field_ty),*]
1093                    )
1094                },
1095            >,
1096        {
1097            fn only_derive_is_allowed_to_implement_this_trait() {}
1098        }
1099
1100        // SAFETY: This macro only accepts `#[repr(C)]` unions, and this `impl`
1101        // block requires all field types to be `Immutable`.
1102        unsafe impl $crate::Immutable for $name
1103        where
1104            $(
1105                $field_ty: $crate::Immutable,
1106            )*
1107        {
1108            fn only_derive_is_allowed_to_implement_this_trait() {}
1109        }
1110    };
1111}
1112
1113#[cfg(test)]
1114mod tests {
1115    use crate::{
1116        byteorder::native_endian::{U16, U32},
1117        util::testutil::*,
1118        *,
1119    };
1120
1121    #[derive(KnownLayout, Immutable, FromBytes, IntoBytes, PartialEq, Debug)]
1122    #[repr(C)]
1123    struct SliceDst<T, U> {
1124        a: T,
1125        b: [U],
1126    }
1127
1128    #[test]
1129    fn test_transmute() {
1130        // Test that memory is transmuted as expected.
1131        let array_of_u8s = [0u8, 1, 2, 3, 4, 5, 6, 7];
1132        let array_of_arrays = [[0, 1], [2, 3], [4, 5], [6, 7]];
1133        let x: [[u8; 2]; 4] = transmute!(array_of_u8s);
1134        assert_eq!(x, array_of_arrays);
1135        let x: [u8; 8] = transmute!(array_of_arrays);
1136        assert_eq!(x, array_of_u8s);
1137
1138        // Test that memory is transmuted as expected when shrinking.
1139        let x: [[u8; 2]; 3] = transmute!(#![allow(shrink)] array_of_u8s);
1140        assert_eq!(x, [[0u8, 1], [2, 3], [4, 5]]);
1141
1142        // Test that the source expression's value is forgotten rather than
1143        // dropped.
1144        #[derive(IntoBytes)]
1145        #[repr(transparent)]
1146        struct PanicOnDrop(());
1147        impl Drop for PanicOnDrop {
1148            fn drop(&mut self) {
1149                panic!("PanicOnDrop::drop");
1150            }
1151        }
1152        #[allow(clippy::let_unit_value)]
1153        let _: () = transmute!(PanicOnDrop(()));
1154        #[allow(clippy::let_unit_value)]
1155        let _: () = transmute!(#![allow(shrink)] PanicOnDrop(()));
1156
1157        // Test that `transmute!` is legal in a const context.
1158        const ARRAY_OF_U8S: [u8; 8] = [0u8, 1, 2, 3, 4, 5, 6, 7];
1159        const ARRAY_OF_ARRAYS: [[u8; 2]; 4] = [[0, 1], [2, 3], [4, 5], [6, 7]];
1160        const X: [[u8; 2]; 4] = transmute!(ARRAY_OF_U8S);
1161        assert_eq!(X, ARRAY_OF_ARRAYS);
1162        const X_SHRINK: [[u8; 2]; 3] = transmute!(#![allow(shrink)] ARRAY_OF_U8S);
1163        assert_eq!(X_SHRINK, [[0u8, 1], [2, 3], [4, 5]]);
1164
1165        // Test that `transmute!` works with `!Immutable` types.
1166        let x: usize = transmute!(UnsafeCell::new(1usize));
1167        assert_eq!(x, 1);
1168        let x: UnsafeCell<usize> = transmute!(1usize);
1169        assert_eq!(x.into_inner(), 1);
1170        let x: UnsafeCell<isize> = transmute!(UnsafeCell::new(1usize));
1171        assert_eq!(x.into_inner(), 1);
1172    }
1173
1174    // A `Sized` type which doesn't implement `KnownLayout` (it is "not
1175    // `KnownLayout`", or `Nkl`).
1176    //
1177    // This permits us to test that `transmute_ref!` and `transmute_mut!` work
1178    // for types which are `Sized + !KnownLayout`. When we added support for
1179    // slice DSTs in #1924, this new support relied on `KnownLayout`, but we
1180    // need to make sure to remain backwards-compatible with code which uses
1181    // these macros with types which are `!KnownLayout`.
1182    #[derive(FromBytes, IntoBytes, Immutable, PartialEq, Eq, Debug)]
1183    #[repr(transparent)]
1184    struct Nkl<T>(T);
1185
1186    #[test]
1187    fn test_transmute_ref() {
1188        // Test that memory is transmuted as expected.
1189        let array_of_u8s = [0u8, 1, 2, 3, 4, 5, 6, 7];
1190        let array_of_arrays = [[0, 1], [2, 3], [4, 5], [6, 7]];
1191        let x: &[[u8; 2]; 4] = transmute_ref!(&array_of_u8s);
1192        assert_eq!(*x, array_of_arrays);
1193        let x: &[u8; 8] = transmute_ref!(&array_of_arrays);
1194        assert_eq!(*x, array_of_u8s);
1195
1196        // Test that `transmute_ref!` is legal in a const context.
1197        const ARRAY_OF_U8S: [u8; 8] = [0u8, 1, 2, 3, 4, 5, 6, 7];
1198        const ARRAY_OF_ARRAYS: [[u8; 2]; 4] = [[0, 1], [2, 3], [4, 5], [6, 7]];
1199        #[allow(clippy::redundant_static_lifetimes)]
1200        const X: &'static [[u8; 2]; 4] = transmute_ref!(&ARRAY_OF_U8S);
1201        assert_eq!(*X, ARRAY_OF_ARRAYS);
1202
1203        // Before 1.61.0, we can't define the `const fn transmute_ref` function
1204        // that we do on and after 1.61.0.
1205        #[cfg(not(zerocopy_generic_bounds_in_const_fn_1_61_0))]
1206        {
1207            // Test that `transmute_ref!` supports non-`KnownLayout` `Sized` types.
1208            const ARRAY_OF_NKL_U8S: Nkl<[u8; 8]> = Nkl([0u8, 1, 2, 3, 4, 5, 6, 7]);
1209            const ARRAY_OF_NKL_ARRAYS: Nkl<[[u8; 2]; 4]> = Nkl([[0, 1], [2, 3], [4, 5], [6, 7]]);
1210            const X_NKL: &Nkl<[[u8; 2]; 4]> = transmute_ref!(&ARRAY_OF_NKL_U8S);
1211            assert_eq!(*X_NKL, ARRAY_OF_NKL_ARRAYS);
1212        }
1213
1214        #[cfg(zerocopy_generic_bounds_in_const_fn_1_61_0)]
1215        {
1216            // Call through a generic function to make sure our autoref
1217            // specialization trick works even when types are generic.
1218            const fn transmute_ref<T, U>(t: &T) -> &U
1219            where
1220                T: IntoBytes + Immutable,
1221                U: FromBytes + Immutable,
1222            {
1223                transmute_ref!(t)
1224            }
1225
1226            // Test that `transmute_ref!` supports non-`KnownLayout` `Sized` types.
1227            const ARRAY_OF_NKL_U8S: Nkl<[u8; 8]> = Nkl([0u8, 1, 2, 3, 4, 5, 6, 7]);
1228            const ARRAY_OF_NKL_ARRAYS: Nkl<[[u8; 2]; 4]> = Nkl([[0, 1], [2, 3], [4, 5], [6, 7]]);
1229            const X_NKL: &Nkl<[[u8; 2]; 4]> = transmute_ref(&ARRAY_OF_NKL_U8S);
1230            assert_eq!(*X_NKL, ARRAY_OF_NKL_ARRAYS);
1231        }
1232
1233        // Test that `transmute_ref!` works on slice DSTs in and that memory is
1234        // transmuted as expected.
1235        let slice_dst_of_u8s =
1236            SliceDst::<U16, [u8; 2]>::ref_from_bytes(&[0, 1, 2, 3, 4, 5][..]).unwrap();
1237        let slice_dst_of_u16s =
1238            SliceDst::<U16, U16>::ref_from_bytes(&[0, 1, 2, 3, 4, 5][..]).unwrap();
1239        let x: &SliceDst<U16, U16> = transmute_ref!(slice_dst_of_u8s);
1240        assert_eq!(x, slice_dst_of_u16s);
1241
1242        let slice_dst_of_u8s =
1243            SliceDst::<U16, u8>::ref_from_bytes(&[0, 1, 2, 3, 4, 5][..]).unwrap();
1244        let x: &[u8] = transmute_ref!(slice_dst_of_u8s);
1245        assert_eq!(x, [0, 1, 2, 3, 4, 5]);
1246
1247        let x: &[u8] = transmute_ref!(slice_dst_of_u16s);
1248        assert_eq!(x, [0, 1, 2, 3, 4, 5]);
1249
1250        let x: &[U16] = transmute_ref!(slice_dst_of_u16s);
1251        let slice_of_u16s: &[U16] = <[U16]>::ref_from_bytes(&[0, 1, 2, 3, 4, 5][..]).unwrap();
1252        assert_eq!(x, slice_of_u16s);
1253
1254        // Test that transmuting from a type with larger trailing slice offset
1255        // and larger trailing slice element works.
1256        let bytes = &[0, 1, 2, 3, 4, 5, 6, 7][..];
1257        let slice_dst_big = SliceDst::<U32, U16>::ref_from_bytes(bytes).unwrap();
1258        let slice_dst_small = SliceDst::<U16, u8>::ref_from_bytes(bytes).unwrap();
1259        let x: &SliceDst<U16, u8> = transmute_ref!(slice_dst_big);
1260        assert_eq!(x, slice_dst_small);
1261
1262        // Test that it's legal to transmute a reference while shrinking the
1263        // lifetime (note that `X` has the lifetime `'static`).
1264        let x: &[u8; 8] = transmute_ref!(X);
1265        assert_eq!(*x, ARRAY_OF_U8S);
1266
1267        // Test that `transmute_ref!` supports decreasing alignment.
1268        let u = AU64(0);
1269        let array = [0, 0, 0, 0, 0, 0, 0, 0];
1270        let x: &[u8; 8] = transmute_ref!(&u);
1271        assert_eq!(*x, array);
1272
1273        // Test that a mutable reference can be turned into an immutable one.
1274        let mut x = 0u8;
1275        #[allow(clippy::useless_transmute)]
1276        let y: &u8 = transmute_ref!(&mut x);
1277        assert_eq!(*y, 0);
1278    }
1279
1280    #[test]
1281    fn test_try_transmute() {
1282        // Test that memory is transmuted with `try_transmute` as expected.
1283        let array_of_bools = [false, true, false, true, false, true, false, true];
1284        let array_of_arrays = [[0, 1], [0, 1], [0, 1], [0, 1]];
1285        let x: Result<[[u8; 2]; 4], _> = try_transmute!(array_of_bools);
1286        assert_eq!(x, Ok(array_of_arrays));
1287        let x: Result<[bool; 8], _> = try_transmute!(array_of_arrays);
1288        assert_eq!(x, Ok(array_of_bools));
1289
1290        // Test that `try_transmute!` works with `!Immutable` types.
1291        let x: Result<usize, _> = try_transmute!(UnsafeCell::new(1usize));
1292        assert_eq!(x.unwrap(), 1);
1293        let x: Result<UnsafeCell<usize>, _> = try_transmute!(1usize);
1294        assert_eq!(x.unwrap().into_inner(), 1);
1295        let x: Result<UnsafeCell<isize>, _> = try_transmute!(UnsafeCell::new(1usize));
1296        assert_eq!(x.unwrap().into_inner(), 1);
1297
1298        #[derive(FromBytes, IntoBytes, Debug, PartialEq)]
1299        #[repr(transparent)]
1300        struct PanicOnDrop<T>(T);
1301
1302        impl<T> Drop for PanicOnDrop<T> {
1303            fn drop(&mut self) {
1304                panic!("PanicOnDrop dropped");
1305            }
1306        }
1307
1308        // Since `try_transmute!` semantically moves its argument on failure,
1309        // the `PanicOnDrop` is not dropped, and thus this shouldn't panic.
1310        let x: Result<usize, _> = try_transmute!(PanicOnDrop(1usize));
1311        assert_eq!(x, Ok(1));
1312
1313        // Since `try_transmute!` semantically returns ownership of its argument
1314        // on failure, the `PanicOnDrop` is returned rather than dropped, and
1315        // thus this shouldn't panic.
1316        let y: Result<bool, _> = try_transmute!(PanicOnDrop(2u8));
1317        // We have to use `map_err` instead of comparing against
1318        // `Err(PanicOnDrop(2u8))` because the latter would create and then drop
1319        // its `PanicOnDrop` temporary, which would cause a panic.
1320        assert_eq!(y.as_ref().map_err(|p| &p.src.0), Err::<&bool, _>(&2u8));
1321        mem::forget(y);
1322    }
1323
1324    #[test]
1325    fn test_try_transmute_ref() {
1326        // Test that memory is transmuted with `try_transmute_ref` as expected.
1327        let array_of_bools = &[false, true, false, true, false, true, false, true];
1328        let array_of_arrays = &[[0, 1], [0, 1], [0, 1], [0, 1]];
1329        let x: Result<&[[u8; 2]; 4], _> = try_transmute_ref!(array_of_bools);
1330        assert_eq!(x, Ok(array_of_arrays));
1331        let x: Result<&[bool; 8], _> = try_transmute_ref!(array_of_arrays);
1332        assert_eq!(x, Ok(array_of_bools));
1333
1334        // Test that it's legal to transmute a reference while shrinking the
1335        // lifetime.
1336        {
1337            let x: Result<&[[u8; 2]; 4], _> = try_transmute_ref!(array_of_bools);
1338            assert_eq!(x, Ok(array_of_arrays));
1339        }
1340
1341        // Test that `try_transmute_ref!` supports decreasing alignment.
1342        let u = AU64(0);
1343        let array = [0u8, 0, 0, 0, 0, 0, 0, 0];
1344        let x: Result<&[u8; 8], _> = try_transmute_ref!(&u);
1345        assert_eq!(x, Ok(&array));
1346
1347        // Test that a mutable reference can be turned into an immutable one.
1348        let mut x = 0u8;
1349        #[allow(clippy::useless_transmute)]
1350        let y: Result<&u8, _> = try_transmute_ref!(&mut x);
1351        assert_eq!(y, Ok(&0));
1352    }
1353
1354    #[test]
1355    fn test_try_transmute_mut() {
1356        // Test that memory is transmuted with `try_transmute_mut` as expected.
1357        let array_of_u8s = &mut [0u8, 1, 0, 1, 0, 1, 0, 1];
1358        let array_of_arrays = &mut [[0u8, 1], [0, 1], [0, 1], [0, 1]];
1359        let x: Result<&mut [[u8; 2]; 4], _> = try_transmute_mut!(array_of_u8s);
1360        assert_eq!(x, Ok(array_of_arrays));
1361
1362        let array_of_bools = &mut [false, true, false, true, false, true, false, true];
1363        let array_of_arrays = &mut [[0u8, 1], [0, 1], [0, 1], [0, 1]];
1364        let x: Result<&mut [bool; 8], _> = try_transmute_mut!(array_of_arrays);
1365        assert_eq!(x, Ok(array_of_bools));
1366
1367        // Test that it's legal to transmute a reference while shrinking the
1368        // lifetime.
1369        let array_of_bools = &mut [false, true, false, true, false, true, false, true];
1370        let array_of_arrays = &mut [[0u8, 1], [0, 1], [0, 1], [0, 1]];
1371        {
1372            let x: Result<&mut [bool; 8], _> = try_transmute_mut!(array_of_arrays);
1373            assert_eq!(x, Ok(array_of_bools));
1374        }
1375
1376        // Test that `try_transmute_mut!` supports decreasing alignment.
1377        let u = &mut AU64(0);
1378        let array = &mut [0u8, 0, 0, 0, 0, 0, 0, 0];
1379        let x: Result<&mut [u8; 8], _> = try_transmute_mut!(u);
1380        assert_eq!(x, Ok(array));
1381
1382        // Test that a mutable reference can be turned into an immutable one.
1383        let mut x = 0u8;
1384        #[allow(clippy::useless_transmute)]
1385        let y: Result<&mut u8, _> = try_transmute_mut!(&mut x);
1386        assert_eq!(y, Ok(&mut 0));
1387    }
1388
1389    #[test]
1390    fn test_transmute_mut() {
1391        // Test that memory is transmuted as expected.
1392        let mut array_of_u8s = [0u8, 1, 2, 3, 4, 5, 6, 7];
1393        let mut array_of_arrays = [[0, 1], [2, 3], [4, 5], [6, 7]];
1394        let x: &mut [[u8; 2]; 4] = transmute_mut!(&mut array_of_u8s);
1395        assert_eq!(*x, array_of_arrays);
1396        let x: &mut [u8; 8] = transmute_mut!(&mut array_of_arrays);
1397        assert_eq!(*x, array_of_u8s);
1398
1399        {
1400            // Test that it's legal to transmute a reference while shrinking the
1401            // lifetime.
1402            let x: &mut [u8; 8] = transmute_mut!(&mut array_of_arrays);
1403            assert_eq!(*x, array_of_u8s);
1404        }
1405
1406        // Test that `transmute_mut!` supports non-`KnownLayout` types.
1407        let mut array_of_u8s = Nkl([0u8, 1, 2, 3, 4, 5, 6, 7]);
1408        let mut array_of_arrays = Nkl([[0, 1], [2, 3], [4, 5], [6, 7]]);
1409        let x: &mut Nkl<[[u8; 2]; 4]> = transmute_mut!(&mut array_of_u8s);
1410        assert_eq!(*x, array_of_arrays);
1411        let x: &mut Nkl<[u8; 8]> = transmute_mut!(&mut array_of_arrays);
1412        assert_eq!(*x, array_of_u8s);
1413
1414        // Test that `transmute_mut!` supports decreasing alignment.
1415        let mut u = AU64(0);
1416        let array = [0, 0, 0, 0, 0, 0, 0, 0];
1417        let x: &[u8; 8] = transmute_mut!(&mut u);
1418        assert_eq!(*x, array);
1419
1420        // Test that a mutable reference can be turned into an immutable one.
1421        let mut x = 0u8;
1422        #[allow(clippy::useless_transmute)]
1423        let y: &u8 = transmute_mut!(&mut x);
1424        assert_eq!(*y, 0);
1425
1426        // Test that `transmute_mut!` works on slice DSTs in and that memory is
1427        // transmuted as expected.
1428        let mut bytes = [0, 1, 2, 3, 4, 5, 6];
1429        let slice_dst_of_u8s = SliceDst::<u8, [u8; 2]>::mut_from_bytes(&mut bytes[..]).unwrap();
1430        let mut bytes = [0, 1, 2, 3, 4, 5, 6];
1431        let slice_dst_of_u16s = SliceDst::<u8, U16>::mut_from_bytes(&mut bytes[..]).unwrap();
1432        let x: &mut SliceDst<u8, U16> = transmute_mut!(slice_dst_of_u8s);
1433        assert_eq!(x, slice_dst_of_u16s);
1434
1435        // Test that `transmute_mut!` works on slices that memory is transmuted
1436        // as expected.
1437        let array_of_u16s: &mut [u16] = &mut [0u16, 1, 2];
1438        let array_of_i16s: &mut [i16] = &mut [0i16, 1, 2];
1439        let x: &mut [i16] = transmute_mut!(array_of_u16s);
1440        assert_eq!(x, array_of_i16s);
1441
1442        // Test that transmuting from a type with larger trailing slice offset
1443        // and larger trailing slice element works.
1444        let mut bytes = [0, 1, 2, 3, 4, 5, 6, 7];
1445        let slice_dst_big = SliceDst::<U32, U16>::mut_from_bytes(&mut bytes[..]).unwrap();
1446        let mut bytes = [0, 1, 2, 3, 4, 5, 6, 7];
1447        let slice_dst_small = SliceDst::<U16, u8>::mut_from_bytes(&mut bytes[..]).unwrap();
1448        let x: &mut SliceDst<U16, u8> = transmute_mut!(slice_dst_big);
1449        assert_eq!(x, slice_dst_small);
1450    }
1451
1452    #[test]
1453    fn test_macros_evaluate_args_once() {
1454        let mut ctr = 0;
1455        #[allow(clippy::useless_transmute)]
1456        let _: usize = transmute!({
1457            ctr += 1;
1458            0usize
1459        });
1460        assert_eq!(ctr, 1);
1461
1462        let mut ctr = 0;
1463        let _: &usize = transmute_ref!({
1464            ctr += 1;
1465            &0usize
1466        });
1467        assert_eq!(ctr, 1);
1468
1469        let mut ctr: usize = 0;
1470        let _: &mut usize = transmute_mut!({
1471            ctr += 1;
1472            &mut ctr
1473        });
1474        assert_eq!(ctr, 1);
1475
1476        let mut ctr = 0;
1477        #[allow(clippy::useless_transmute)]
1478        let _: usize = try_transmute!({
1479            ctr += 1;
1480            0usize
1481        })
1482        .unwrap();
1483        assert_eq!(ctr, 1);
1484    }
1485
1486    #[test]
1487    fn test_include_value() {
1488        const AS_U32: u32 = include_value!("../testdata/include_value/data");
1489        assert_eq!(AS_U32, u32::from_ne_bytes([b'a', b'b', b'c', b'd']));
1490        const AS_I32: i32 = include_value!("../testdata/include_value/data");
1491        assert_eq!(AS_I32, i32::from_ne_bytes([b'a', b'b', b'c', b'd']));
1492    }
1493
1494    #[test]
1495    #[allow(non_camel_case_types, unreachable_pub, dead_code)]
1496    fn test_cryptocorrosion_derive_traits() {
1497        // Test the set of invocations added in
1498        // https://github.com/cryptocorrosion/cryptocorrosion/pull/85
1499
1500        fn assert_impls<T: FromBytes + IntoBytes + Immutable>() {}
1501
1502        cryptocorrosion_derive_traits! {
1503            #[repr(C)]
1504            #[derive(Clone, Copy)]
1505            pub union vec128_storage {
1506                d: [u32; 4],
1507                q: [u64; 2],
1508            }
1509        }
1510
1511        assert_impls::<vec128_storage>();
1512
1513        cryptocorrosion_derive_traits! {
1514            #[repr(transparent)]
1515            #[derive(Copy, Clone, Debug, PartialEq)]
1516            pub struct u32x4_generic([u32; 4]);
1517        }
1518
1519        assert_impls::<u32x4_generic>();
1520
1521        cryptocorrosion_derive_traits! {
1522            #[repr(transparent)]
1523            #[derive(Copy, Clone, Debug, PartialEq)]
1524            pub struct u64x2_generic([u64; 2]);
1525        }
1526
1527        assert_impls::<u64x2_generic>();
1528
1529        cryptocorrosion_derive_traits! {
1530            #[repr(transparent)]
1531            #[derive(Copy, Clone, Debug, PartialEq)]
1532            pub struct u128x1_generic([u128; 1]);
1533        }
1534
1535        assert_impls::<u128x1_generic>();
1536
1537        cryptocorrosion_derive_traits! {
1538            #[repr(transparent)]
1539            #[derive(Copy, Clone, Default)]
1540            #[allow(non_camel_case_types)]
1541            pub struct x2<W, G>(pub [W; 2], PhantomData<G>);
1542        }
1543
1544        enum NotZerocopy {}
1545        assert_impls::<x2<(), NotZerocopy>>();
1546
1547        cryptocorrosion_derive_traits! {
1548            #[repr(transparent)]
1549            #[derive(Copy, Clone, Default)]
1550            #[allow(non_camel_case_types)]
1551            pub struct x4<W>(pub [W; 4]);
1552        }
1553
1554        assert_impls::<x4<()>>();
1555
1556        #[cfg(feature = "simd")]
1557        #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
1558        {
1559            #[cfg(target_arch = "x86")]
1560            use core::arch::x86::{__m128i, __m256i};
1561            #[cfg(target_arch = "x86_64")]
1562            use core::arch::x86_64::{__m128i, __m256i};
1563
1564            cryptocorrosion_derive_traits! {
1565                #[repr(C)]
1566                #[derive(Copy, Clone)]
1567                pub struct X4(__m128i, __m128i, __m128i, __m128i);
1568            }
1569
1570            assert_impls::<X4>();
1571
1572            cryptocorrosion_derive_traits! {
1573                #[repr(C)]
1574                /// Generic wrapper for unparameterized storage of any of the possible impls.
1575                /// Converting into and out of this type should be essentially free, although it may be more
1576                /// aligned than a particular impl requires.
1577                #[allow(non_camel_case_types)]
1578                #[derive(Copy, Clone)]
1579                pub union vec128_storage {
1580                    u32x4: [u32; 4],
1581                    u64x2: [u64; 2],
1582                    u128x1: [u128; 1],
1583                    sse2: __m128i,
1584                }
1585            }
1586
1587            assert_impls::<vec128_storage>();
1588
1589            cryptocorrosion_derive_traits! {
1590                #[repr(transparent)]
1591                #[allow(non_camel_case_types)]
1592                #[derive(Copy, Clone)]
1593                pub struct vec<S3, S4, NI> {
1594                    x: __m128i,
1595                    s3: PhantomData<S3>,
1596                    s4: PhantomData<S4>,
1597                    ni: PhantomData<NI>,
1598                }
1599            }
1600
1601            assert_impls::<vec<NotZerocopy, NotZerocopy, NotZerocopy>>();
1602
1603            cryptocorrosion_derive_traits! {
1604                #[repr(transparent)]
1605                #[derive(Copy, Clone)]
1606                pub struct u32x4x2_avx2<NI> {
1607                    x: __m256i,
1608                    ni: PhantomData<NI>,
1609                }
1610            }
1611
1612            assert_impls::<u32x4x2_avx2<NotZerocopy>>();
1613        }
1614
1615        // Make sure that our derive works for `#[repr(C)]` structs even though
1616        // cryptocorrosion doesn't currently have any.
1617        cryptocorrosion_derive_traits! {
1618            #[repr(C)]
1619            #[derive(Copy, Clone, Debug, PartialEq)]
1620            pub struct ReprC(u8, u8, u16);
1621        }
1622    }
1623}