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