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)]
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/// const fn transmute_ref<'src, 'dst, Src, Dst>(src: &'src Src) -> &'dst Dst
106/// where
107///     'src: 'dst,
108///     Src: IntoBytes + Immutable,
109///     Dst: FromBytes + Immutable,
110///     size_of::<Src>() == size_of::<Dst>(),
111///     align_of::<Src>() >= align_of::<Dst>(),
112/// {
113/// # /*
114///     ...
115/// # */
116/// }
117/// ```
118///
119/// However, unlike a function, this macro can only be invoked when the types of
120/// `Src` and `Dst` are completely concrete. The types `Src` and `Dst` are
121/// inferred from the calling context; they cannot be explicitly specified in
122/// the macro invocation.
123///
124/// # Examples
125///
126/// ```
127/// # use zerocopy::transmute_ref;
128/// let one_dimensional: [u8; 8] = [0, 1, 2, 3, 4, 5, 6, 7];
129///
130/// let two_dimensional: &[[u8; 4]; 2] = transmute_ref!(&one_dimensional);
131///
132/// assert_eq!(two_dimensional, &[[0, 1, 2, 3], [4, 5, 6, 7]]);
133/// ```
134///
135/// # Use in `const` contexts
136///
137/// This macro can be invoked in `const` contexts.
138///
139/// # Alignment increase error message
140///
141/// Because of limitations on macros, the error message generated when
142/// `transmute_ref!` is used to transmute from a type of lower alignment to a
143/// type of higher alignment is somewhat confusing. For example, the following
144/// code:
145///
146/// ```compile_fail
147/// const INCREASE_ALIGNMENT: &u16 = zerocopy::transmute_ref!(&[0u8; 2]);
148/// ```
149///
150/// ...generates the following error:
151///
152/// ```text
153/// error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
154///  --> src/lib.rs:1524:34
155///   |
156/// 5 | const INCREASE_ALIGNMENT: &u16 = zerocopy::transmute_ref!(&[0u8; 2]);
157///   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
158///   |
159///   = note: source type: `AlignOf<[u8; 2]>` (8 bits)
160///   = note: target type: `MaxAlignsOf<[u8; 2], u16>` (16 bits)
161///   = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
162/// ```
163///
164/// This is saying that `max(align_of::<T>(), align_of::<U>()) !=
165/// align_of::<T>()`, which is equivalent to `align_of::<T>() <
166/// align_of::<U>()`.
167#[macro_export]
168macro_rules! transmute_ref {
169    ($e:expr) => {{
170        // NOTE: This must be a macro (rather than a function with trait bounds)
171        // because there's no way, in a generic context, to enforce that two
172        // types have the same size or alignment.
173
174        // Ensure that the source type is a reference or a mutable reference
175        // (note that mutable references are implicitly reborrowed here).
176        let e: &_ = $e;
177
178        #[allow(unused, clippy::diverging_sub_expression)]
179        if false {
180            // This branch, though never taken, ensures that the type of `e` is
181            // `&T` where `T: 't + Sized + IntoBytes + Immutable`, that the type of
182            // this macro expression is `&U` where `U: 'u + Sized + FromBytes +
183            // Immutable`, and that `'t` outlives `'u`.
184
185            struct AssertSrcIsSized<'a, T: ::core::marker::Sized>(&'a T);
186            struct AssertSrcIsIntoBytes<'a, T: ?::core::marker::Sized + $crate::IntoBytes>(&'a T);
187            struct AssertSrcIsImmutable<'a, T: ?::core::marker::Sized + $crate::Immutable>(&'a T);
188            struct AssertDstIsSized<'a, T: ::core::marker::Sized>(&'a T);
189            struct AssertDstIsFromBytes<'a, U: ?::core::marker::Sized + $crate::FromBytes>(&'a U);
190            struct AssertDstIsImmutable<'a, T: ?::core::marker::Sized + $crate::Immutable>(&'a T);
191
192            let _ = AssertSrcIsSized(e);
193            let _ = AssertSrcIsIntoBytes(e);
194            let _ = AssertSrcIsImmutable(e);
195
196            if true {
197                #[allow(unused, unreachable_code)]
198                let u = AssertDstIsSized(loop {});
199                u.0
200            } else if true {
201                #[allow(unused, unreachable_code)]
202                let u = AssertDstIsFromBytes(loop {});
203                u.0
204            } else {
205                #[allow(unused, unreachable_code)]
206                let u = AssertDstIsImmutable(loop {});
207                u.0
208            }
209        } else if false {
210            // This branch, though never taken, ensures that `size_of::<T>() ==
211            // size_of::<U>()` and that that `align_of::<T>() >=
212            // align_of::<U>()`.
213
214            // `t` is inferred to have type `T` because it's assigned to `e` (of
215            // type `&T`) as `&t`.
216            let mut t = loop {};
217            e = &t;
218
219            // `u` is inferred to have type `U` because it's used as `&u` as the
220            // value returned from this branch.
221            let u;
222
223            $crate::assert_size_eq!(t, u);
224            $crate::assert_align_gt_eq!(t, u);
225
226            &u
227        } else {
228            // SAFETY: For source type `Src` and destination type `Dst`:
229            // - We know that `Src: IntoBytes + Immutable` and `Dst: FromBytes +
230            //   Immutable` thanks to the uses of `AssertSrcIsIntoBytes`,
231            //   `AssertSrcIsImmutable`, `AssertDstIsFromBytes`, and
232            //   `AssertDstIsImmutable` above.
233            // - We know that `size_of::<Src>() == size_of::<Dst>()` thanks to
234            //   the use of `assert_size_eq!` above.
235            // - We know that `align_of::<Src>() >= align_of::<Dst>()` thanks to
236            //   the use of `assert_align_gt_eq!` above.
237            let u = unsafe { $crate::util::macro_util::transmute_ref(e) };
238            $crate::util::macro_util::must_use(u)
239        }
240    }}
241}
242
243/// Safely transmutes a mutable reference of one type to a mutable reference of
244/// another type of the same size and compatible alignment.
245///
246/// This macro behaves like an invocation of this function:
247///
248/// ```ignore
249/// const fn transmute_mut<'src, 'dst, Src, Dst>(src: &'src mut Src) -> &'dst mut Dst
250/// where
251///     'src: 'dst,
252///     Src: FromBytes + IntoBytes + Immutable,
253///     Dst: FromBytes + IntoBytes + Immutable,
254///     size_of::<Src>() == size_of::<Dst>(),
255///     align_of::<Src>() >= align_of::<Dst>(),
256/// {
257/// # /*
258///     ...
259/// # */
260/// }
261/// ```
262///
263/// However, unlike a function, this macro can only be invoked when the types of
264/// `Src` and `Dst` are completely concrete. The types `Src` and `Dst` are
265/// inferred from the calling context; they cannot be explicitly specified in
266/// the macro invocation.
267///
268/// # Examples
269///
270/// ```
271/// # use zerocopy::transmute_mut;
272/// let mut one_dimensional: [u8; 8] = [0, 1, 2, 3, 4, 5, 6, 7];
273///
274/// let two_dimensional: &mut [[u8; 4]; 2] = transmute_mut!(&mut one_dimensional);
275///
276/// assert_eq!(two_dimensional, &[[0, 1, 2, 3], [4, 5, 6, 7]]);
277///
278/// two_dimensional.reverse();
279///
280/// assert_eq!(one_dimensional, [4, 5, 6, 7, 0, 1, 2, 3]);
281/// ```
282///
283/// # Use in `const` contexts
284///
285/// This macro can be invoked in `const` contexts.
286///
287/// # Alignment increase error message
288///
289/// Because of limitations on macros, the error message generated when
290/// `transmute_mut!` is used to transmute from a type of lower alignment to a
291/// type of higher alignment is somewhat confusing. For example, the following
292/// code:
293///
294/// ```compile_fail
295/// const INCREASE_ALIGNMENT: &mut u16 = zerocopy::transmute_mut!(&mut [0u8; 2]);
296/// ```
297///
298/// ...generates the following error:
299///
300/// ```text
301/// error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
302///  --> src/lib.rs:1524:34
303///   |
304/// 5 | const INCREASE_ALIGNMENT: &mut u16 = zerocopy::transmute_mut!(&mut [0u8; 2]);
305///   |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
306///   |
307///   = note: source type: `AlignOf<[u8; 2]>` (8 bits)
308///   = note: target type: `MaxAlignsOf<[u8; 2], u16>` (16 bits)
309///   = note: this error originates in the macro `$crate::assert_align_gt_eq` which comes from the expansion of the macro `transmute_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
310/// ```
311///
312/// This is saying that `max(align_of::<T>(), align_of::<U>()) !=
313/// align_of::<T>()`, which is equivalent to `align_of::<T>() <
314/// align_of::<U>()`.
315#[macro_export]
316macro_rules! transmute_mut {
317    ($e:expr) => {{
318        // NOTE: This must be a macro (rather than a function with trait bounds)
319        // because there's no way, in a generic context, to enforce that two
320        // types have the same size or alignment.
321
322        // Ensure that the source type is a mutable reference.
323        let e: &mut _ = $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            // `&mut T` where `T: 't + Sized + FromBytes + IntoBytes + Immutable`
329            // and that the type of this macro expression is `&mut U` where `U:
330            // 'u + Sized + FromBytes + IntoBytes + Immutable`.
331
332            // We use immutable references here rather than mutable so that, if
333            // this macro is used in a const context (in which, as of this
334            // writing, mutable references are banned), the error message
335            // appears to originate in the user's code rather than in the
336            // internals of this macro.
337            struct AssertSrcIsSized<'a, T: ::core::marker::Sized>(&'a T);
338            struct AssertSrcIsFromBytes<'a, T: ?::core::marker::Sized + $crate::FromBytes>(&'a T);
339            struct AssertSrcIsIntoBytes<'a, T: ?::core::marker::Sized + $crate::IntoBytes>(&'a T);
340            struct AssertDstIsSized<'a, T: ::core::marker::Sized>(&'a T);
341            struct AssertDstIsFromBytes<'a, T: ?::core::marker::Sized + $crate::FromBytes>(&'a T);
342            struct AssertDstIsIntoBytes<'a, T: ?::core::marker::Sized + $crate::IntoBytes>(&'a T);
343
344            if true {
345                let _ = AssertSrcIsSized(&*e);
346            } else if true {
347                let _ = AssertSrcIsFromBytes(&*e);
348            } else {
349                let _ = AssertSrcIsIntoBytes(&*e);
350            }
351
352            if true {
353                #[allow(unused, unreachable_code)]
354                let u = AssertDstIsSized(loop {});
355                &mut *u.0
356            } else if true {
357                #[allow(unused, unreachable_code)]
358                let u = AssertDstIsFromBytes(loop {});
359                &mut *u.0
360            } else {
361                #[allow(unused, unreachable_code)]
362                let u = AssertDstIsIntoBytes(loop {});
363                &mut *u.0
364            }
365        } else if false {
366            // This branch, though never taken, ensures that `size_of::<T>() ==
367            // size_of::<U>()` and that that `align_of::<T>() >=
368            // align_of::<U>()`.
369
370            // `t` is inferred to have type `T` because it's assigned to `e` (of
371            // type `&mut T`) as `&mut t`.
372            let mut t = loop {};
373            e = &mut t;
374
375            // `u` is inferred to have type `U` because it's used as `&mut u` as
376            // the value returned from this branch.
377            let u;
378
379            $crate::assert_size_eq!(t, u);
380            $crate::assert_align_gt_eq!(t, u);
381
382            &mut u
383        } else {
384            // SAFETY: For source type `Src` and destination type `Dst`:
385            // - We know that `size_of::<Src>() == size_of::<Dst>()` thanks to
386            //   the use of `assert_size_eq!` above.
387            // - We know that `align_of::<Src>() >= align_of::<Dst>()` thanks to
388            //   the use of `assert_align_gt_eq!` above.
389            let u = unsafe { $crate::util::macro_util::transmute_mut(e) };
390            $crate::util::macro_util::must_use(u)
391        }
392    }}
393}
394
395/// Conditionally transmutes a value of one type to a value of another type of
396/// the same size.
397///
398/// This macro behaves like an invocation of this function:
399///
400/// ```ignore
401/// fn try_transmute<Src, Dst>(src: Src) -> Result<Dst, ValidityError<Src, Dst>>
402/// where
403///     Src: IntoBytes,
404///     Dst: TryFromBytes,
405///     size_of::<Src>() == size_of::<Dst>(),
406/// {
407/// # /*
408///     ...
409/// # */
410/// }
411/// ```
412///
413/// However, unlike a function, this macro can only be invoked when the types of
414/// `Src` and `Dst` are completely concrete. The types `Src` and `Dst` are
415/// inferred from the calling context; they cannot be explicitly specified in
416/// the macro invocation.
417///
418/// Note that the `Src` produced by the expression `$e` will *not* be dropped.
419/// Semantically, its bits will be copied into a new value of type `Dst`, the
420/// original `Src` will be forgotten, and the value of type `Dst` will be
421/// returned.
422///
423/// # Examples
424///
425/// ```
426/// # use zerocopy::*;
427/// // 0u8 → bool = false
428/// assert_eq!(try_transmute!(0u8), Ok(false));
429///
430/// // 1u8 → bool = true
431///  assert_eq!(try_transmute!(1u8), Ok(true));
432///
433/// // 2u8 → bool = error
434/// assert!(matches!(
435///     try_transmute!(2u8),
436///     Result::<bool, _>::Err(ValidityError { .. })
437/// ));
438/// ```
439#[macro_export]
440macro_rules! try_transmute {
441    ($e:expr) => {{
442        // NOTE: This must be a macro (rather than a function with trait bounds)
443        // because there's no way, in a generic context, to enforce that two
444        // types have the same size. `core::mem::transmute` uses compiler magic
445        // to enforce this so long as the types are concrete.
446
447        let e = $e;
448        if false {
449            // Check that the sizes of the source and destination types are
450            // equal.
451
452            // SAFETY: This code is never executed.
453            Ok(unsafe {
454                // Clippy: We can't annotate the types; this macro is designed
455                // to infer the types from the calling context.
456                #[allow(clippy::missing_transmute_annotations)]
457                $crate::util::macro_util::core_reexport::mem::transmute(e)
458            })
459        } else {
460            $crate::util::macro_util::try_transmute::<_, _>(e)
461        }
462    }}
463}
464
465/// Conditionally transmutes a mutable or immutable reference of one type to an
466/// immutable reference of another type of the same size and compatible
467/// alignment.
468///
469/// This macro behaves like an invocation of this function:
470///
471/// ```ignore
472/// fn try_transmute_ref<Src, Dst>(src: &Src) -> Result<&Dst, ValidityError<&Src, Dst>>
473/// where
474///     Src: IntoBytes + Immutable,
475///     Dst: TryFromBytes + Immutable,
476///     size_of::<Src>() == size_of::<Dst>(),
477///     align_of::<Src>() >= align_of::<Dst>(),
478/// {
479/// # /*
480///     ...
481/// # */
482/// }
483/// ```
484///
485/// However, unlike a function, this macro can only be invoked when the types of
486/// `Src` and `Dst` are completely concrete. The types `Src` and `Dst` are
487/// inferred from the calling context; they cannot be explicitly specified in
488/// the macro invocation.
489///
490/// # Examples
491///
492/// ```
493/// # use zerocopy::*;
494/// // 0u8 → bool = false
495/// assert_eq!(try_transmute_ref!(&0u8), Ok(&false));
496///
497/// // 1u8 → bool = true
498///  assert_eq!(try_transmute_ref!(&1u8), Ok(&true));
499///
500/// // 2u8 → bool = error
501/// assert!(matches!(
502///     try_transmute_ref!(&2u8),
503///     Result::<&bool, _>::Err(ValidityError { .. })
504/// ));
505/// ```
506///
507/// # Alignment increase error message
508///
509/// Because of limitations on macros, the error message generated when
510/// `try_transmute_ref!` is used to transmute from a type of lower alignment to
511/// a type of higher alignment is somewhat confusing. For example, the following
512/// code:
513///
514/// ```compile_fail
515/// let increase_alignment: Result<&u16, _> = zerocopy::try_transmute_ref!(&[0u8; 2]);
516/// ```
517///
518/// ...generates the following error:
519///
520/// ```text
521/// error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
522///  --> example.rs:1:47
523///   |
524/// 1 |     let increase_alignment: Result<&u16, _> = zerocopy::try_transmute_ref!(&[0u8; 2]);
525///   |                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
526///   |
527///   = note: source type: `AlignOf<[u8; 2]>` (8 bits)
528///   = note: target type: `MaxAlignsOf<[u8; 2], u16>` (16 bits)
529///   = 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)/// ```
530/// ```
531///
532/// This is saying that `max(align_of::<T>(), align_of::<U>()) !=
533/// align_of::<T>()`, which is equivalent to `align_of::<T>() <
534/// align_of::<U>()`.
535#[macro_export]
536macro_rules! try_transmute_ref {
537    ($e:expr) => {{
538        // NOTE: This must be a macro (rather than a function with trait bounds)
539        // because there's no way, in a generic context, to enforce that two
540        // types have the same size. `core::mem::transmute` uses compiler magic
541        // to enforce this so long as the types are concrete.
542
543        // Ensure that the source type is a reference or a mutable reference
544        // (note that mutable references are implicitly reborrowed here).
545        let e: &_ = $e;
546
547        #[allow(unreachable_code, unused, clippy::diverging_sub_expression)]
548        if false {
549            // This branch, though never taken, ensures that `size_of::<T>() ==
550            // size_of::<U>()` and that that `align_of::<T>() >=
551            // align_of::<U>()`.
552
553            // `t` is inferred to have type `T` because it's assigned to `e` (of
554            // type `&T`) as `&t`.
555            let mut t = loop {};
556            e = &t;
557
558            // `u` is inferred to have type `U` because it's used as `Ok(&u)` as
559            // the value returned from this branch.
560            let u;
561
562            $crate::assert_size_eq!(t, u);
563            $crate::assert_align_gt_eq!(t, u);
564
565            Ok(&u)
566        } else {
567            $crate::util::macro_util::try_transmute_ref::<_, _>(e)
568        }
569    }}
570}
571
572/// Conditionally transmutes a mutable reference of one type to a mutable
573/// reference of another type of the same size and compatible alignment.
574///
575/// This macro behaves like an invocation of this function:
576///
577/// ```ignore
578/// fn try_transmute_mut<Src, Dst>(src: &mut Src) -> Result<&mut Dst, ValidityError<&mut Src, Dst>>
579/// where
580///     Src: IntoBytes,
581///     Dst: TryFromBytes,
582///     size_of::<Src>() == size_of::<Dst>(),
583///     align_of::<Src>() >= align_of::<Dst>(),
584/// {
585/// # /*
586///     ...
587/// # */
588/// }
589/// ```
590///
591/// However, unlike a function, this macro can only be invoked when the types of
592/// `Src` and `Dst` are completely concrete. The types `Src` and `Dst` are
593/// inferred from the calling context; they cannot be explicitly specified in
594/// the macro invocation.
595///
596/// # Examples
597///
598/// ```
599/// # use zerocopy::*;
600/// // 0u8 → bool = false
601/// let src = &mut 0u8;
602/// assert_eq!(try_transmute_mut!(src), Ok(&mut false));
603///
604/// // 1u8 → bool = true
605/// let src = &mut 1u8;
606///  assert_eq!(try_transmute_mut!(src), Ok(&mut true));
607///
608/// // 2u8 → bool = error
609/// let src = &mut 2u8;
610/// assert!(matches!(
611///     try_transmute_mut!(src),
612///     Result::<&mut bool, _>::Err(ValidityError { .. })
613/// ));
614/// ```
615///
616/// # Alignment increase error message
617///
618/// Because of limitations on macros, the error message generated when
619/// `try_transmute_ref!` is used to transmute from a type of lower alignment to
620/// a type of higher alignment is somewhat confusing. For example, the following
621/// code:
622///
623/// ```compile_fail
624/// let src = &mut [0u8; 2];
625/// let increase_alignment: Result<&mut u16, _> = zerocopy::try_transmute_mut!(src);
626/// ```
627///
628/// ...generates the following error:
629///
630/// ```text
631/// error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
632///  --> example.rs:2:51
633///   |
634/// 2 |     let increase_alignment: Result<&mut u16, _> = zerocopy::try_transmute_mut!(src);
635///   |                                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
636///   |
637///   = note: source type: `AlignOf<[u8; 2]>` (8 bits)
638///   = note: target type: `MaxAlignsOf<[u8; 2], u16>` (16 bits)
639///   = 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)
640/// ```
641///
642/// This is saying that `max(align_of::<T>(), align_of::<U>()) !=
643/// align_of::<T>()`, which is equivalent to `align_of::<T>() <
644/// align_of::<U>()`.
645#[macro_export]
646macro_rules! try_transmute_mut {
647    ($e:expr) => {{
648        // NOTE: This must be a macro (rather than a function with trait bounds)
649        // because there's no way, in a generic context, to enforce that two
650        // types have the same size. `core::mem::transmute` uses compiler magic
651        // to enforce this so long as the types are concrete.
652
653        // Ensure that the source type is a mutable reference.
654        let e: &mut _ = $e;
655
656        #[allow(unreachable_code, unused, clippy::diverging_sub_expression)]
657        if false {
658            // This branch, though never taken, ensures that `size_of::<T>() ==
659            // size_of::<U>()` and that that `align_of::<T>() >=
660            // align_of::<U>()`.
661
662            // `t` is inferred to have type `T` because it's assigned to `e` (of
663            // type `&mut T`) as `&mut t`.
664            let mut t = loop {};
665            e = &mut t;
666
667            // `u` is inferred to have type `U` because it's used as `Ok(&mut
668            // u)` as the value returned from this branch.
669            let u;
670
671            $crate::assert_size_eq!(t, u);
672            $crate::assert_align_gt_eq!(t, u);
673
674            Ok(&mut u)
675        } else {
676            $crate::util::macro_util::try_transmute_mut::<_, _>(e)
677        }
678    }}
679}
680
681/// Includes a file and safely transmutes it to a value of an arbitrary type.
682///
683/// The file will be included as a byte array, `[u8; N]`, which will be
684/// transmuted to another type, `T`. `T` is inferred from the calling context,
685/// and must implement [`FromBytes`].
686///
687/// The file is located relative to the current file (similarly to how modules
688/// are found). The provided path is interpreted in a platform-specific way at
689/// compile time. So, for instance, an invocation with a Windows path containing
690/// backslashes `\` would not compile correctly on Unix.
691///
692/// `include_value!` is ignorant of byte order. For byte order-aware types, see
693/// the [`byteorder`] module.
694///
695/// [`FromBytes`]: crate::FromBytes
696/// [`byteorder`]: crate::byteorder
697///
698/// # Examples
699///
700/// Assume there are two files in the same directory with the following
701/// contents:
702///
703/// File `data` (no trailing newline):
704///
705/// ```text
706/// abcd
707/// ```
708///
709/// File `main.rs`:
710///
711/// ```rust
712/// use zerocopy::include_value;
713/// # macro_rules! include_value {
714/// # ($file:expr) => { zerocopy::include_value!(concat!("../testdata/include_value/", $file)) };
715/// # }
716///
717/// fn main() {
718///     let as_u32: u32 = include_value!("data");
719///     assert_eq!(as_u32, u32::from_ne_bytes([b'a', b'b', b'c', b'd']));
720///     let as_i32: i32 = include_value!("data");
721///     assert_eq!(as_i32, i32::from_ne_bytes([b'a', b'b', b'c', b'd']));
722/// }
723/// ```
724///
725/// # Use in `const` contexts
726///
727/// This macro can be invoked in `const` contexts.
728#[doc(alias("include_bytes", "include_data", "include_type"))]
729#[macro_export]
730macro_rules! include_value {
731    ($file:expr $(,)?) => {
732        $crate::transmute!(*::core::include_bytes!($file))
733    };
734}
735
736#[cfg(test)]
737mod tests {
738    use crate::util::testutil::*;
739    use crate::*;
740
741    #[test]
742    fn test_transmute() {
743        // Test that memory is transmuted as expected.
744        let array_of_u8s = [0u8, 1, 2, 3, 4, 5, 6, 7];
745        let array_of_arrays = [[0, 1], [2, 3], [4, 5], [6, 7]];
746        let x: [[u8; 2]; 4] = transmute!(array_of_u8s);
747        assert_eq!(x, array_of_arrays);
748        let x: [u8; 8] = transmute!(array_of_arrays);
749        assert_eq!(x, array_of_u8s);
750
751        // Test that the source expression's value is forgotten rather than
752        // dropped.
753        #[derive(IntoBytes)]
754        #[repr(transparent)]
755        struct PanicOnDrop(());
756        impl Drop for PanicOnDrop {
757            fn drop(&mut self) {
758                panic!("PanicOnDrop::drop");
759            }
760        }
761        #[allow(clippy::let_unit_value)]
762        let _: () = transmute!(PanicOnDrop(()));
763
764        // Test that `transmute!` is legal in a const context.
765        const ARRAY_OF_U8S: [u8; 8] = [0u8, 1, 2, 3, 4, 5, 6, 7];
766        const ARRAY_OF_ARRAYS: [[u8; 2]; 4] = [[0, 1], [2, 3], [4, 5], [6, 7]];
767        const X: [[u8; 2]; 4] = transmute!(ARRAY_OF_U8S);
768        assert_eq!(X, ARRAY_OF_ARRAYS);
769
770        // Test that `transmute!` works with `!Immutable` types.
771        let x: usize = transmute!(UnsafeCell::new(1usize));
772        assert_eq!(x, 1);
773        let x: UnsafeCell<usize> = transmute!(1usize);
774        assert_eq!(x.into_inner(), 1);
775        let x: UnsafeCell<isize> = transmute!(UnsafeCell::new(1usize));
776        assert_eq!(x.into_inner(), 1);
777    }
778
779    #[test]
780    fn test_transmute_ref() {
781        // Test that memory is transmuted as expected.
782        let array_of_u8s = [0u8, 1, 2, 3, 4, 5, 6, 7];
783        let array_of_arrays = [[0, 1], [2, 3], [4, 5], [6, 7]];
784        let x: &[[u8; 2]; 4] = transmute_ref!(&array_of_u8s);
785        assert_eq!(*x, array_of_arrays);
786        let x: &[u8; 8] = transmute_ref!(&array_of_arrays);
787        assert_eq!(*x, array_of_u8s);
788
789        // Test that `transmute_ref!` is legal in a const context.
790        const ARRAY_OF_U8S: [u8; 8] = [0u8, 1, 2, 3, 4, 5, 6, 7];
791        const ARRAY_OF_ARRAYS: [[u8; 2]; 4] = [[0, 1], [2, 3], [4, 5], [6, 7]];
792        #[allow(clippy::redundant_static_lifetimes)]
793        const X: &'static [[u8; 2]; 4] = transmute_ref!(&ARRAY_OF_U8S);
794        assert_eq!(*X, ARRAY_OF_ARRAYS);
795
796        // Test that it's legal to transmute a reference while shrinking the
797        // lifetime (note that `X` has the lifetime `'static`).
798        let x: &[u8; 8] = transmute_ref!(X);
799        assert_eq!(*x, ARRAY_OF_U8S);
800
801        // Test that `transmute_ref!` supports decreasing alignment.
802        let u = AU64(0);
803        let array = [0, 0, 0, 0, 0, 0, 0, 0];
804        let x: &[u8; 8] = transmute_ref!(&u);
805        assert_eq!(*x, array);
806
807        // Test that a mutable reference can be turned into an immutable one.
808        let mut x = 0u8;
809        #[allow(clippy::useless_transmute)]
810        let y: &u8 = transmute_ref!(&mut x);
811        assert_eq!(*y, 0);
812    }
813
814    #[test]
815    fn test_try_transmute() {
816        // Test that memory is transmuted with `try_transmute` as expected.
817        let array_of_bools = [false, true, false, true, false, true, false, true];
818        let array_of_arrays = [[0, 1], [0, 1], [0, 1], [0, 1]];
819        let x: Result<[[u8; 2]; 4], _> = try_transmute!(array_of_bools);
820        assert_eq!(x, Ok(array_of_arrays));
821        let x: Result<[bool; 8], _> = try_transmute!(array_of_arrays);
822        assert_eq!(x, Ok(array_of_bools));
823
824        // Test that `try_transmute!` works with `!Immutable` types.
825        let x: Result<usize, _> = try_transmute!(UnsafeCell::new(1usize));
826        assert_eq!(x.unwrap(), 1);
827        let x: Result<UnsafeCell<usize>, _> = try_transmute!(1usize);
828        assert_eq!(x.unwrap().into_inner(), 1);
829        let x: Result<UnsafeCell<isize>, _> = try_transmute!(UnsafeCell::new(1usize));
830        assert_eq!(x.unwrap().into_inner(), 1);
831
832        #[derive(FromBytes, IntoBytes, Debug, PartialEq)]
833        #[repr(transparent)]
834        struct PanicOnDrop<T>(T);
835
836        impl<T> Drop for PanicOnDrop<T> {
837            fn drop(&mut self) {
838                panic!("PanicOnDrop dropped");
839            }
840        }
841
842        // Since `try_transmute!` semantically moves its argument on failure,
843        // the `PanicOnDrop` is not dropped, and thus this shouldn't panic.
844        let x: Result<usize, _> = try_transmute!(PanicOnDrop(1usize));
845        assert_eq!(x, Ok(1));
846
847        // Since `try_transmute!` semantically returns ownership of its argument
848        // on failure, the `PanicOnDrop` is returned rather than dropped, and
849        // thus this shouldn't panic.
850        let y: Result<bool, _> = try_transmute!(PanicOnDrop(2u8));
851        // We have to use `map_err` instead of comparing against
852        // `Err(PanicOnDrop(2u8))` because the latter would create and then drop
853        // its `PanicOnDrop` temporary, which would cause a panic.
854        assert_eq!(y.as_ref().map_err(|p| &p.src.0), Err::<&bool, _>(&2u8));
855        mem::forget(y);
856    }
857
858    #[test]
859    fn test_try_transmute_ref() {
860        // Test that memory is transmuted with `try_transmute_ref` as expected.
861        let array_of_bools = &[false, true, false, true, false, true, false, true];
862        let array_of_arrays = &[[0, 1], [0, 1], [0, 1], [0, 1]];
863        let x: Result<&[[u8; 2]; 4], _> = try_transmute_ref!(array_of_bools);
864        assert_eq!(x, Ok(array_of_arrays));
865        let x: Result<&[bool; 8], _> = try_transmute_ref!(array_of_arrays);
866        assert_eq!(x, Ok(array_of_bools));
867
868        // Test that it's legal to transmute a reference while shrinking the
869        // lifetime.
870        {
871            let x: Result<&[[u8; 2]; 4], _> = try_transmute_ref!(array_of_bools);
872            assert_eq!(x, Ok(array_of_arrays));
873        }
874
875        // Test that `try_transmute_ref!` supports decreasing alignment.
876        let u = AU64(0);
877        let array = [0u8, 0, 0, 0, 0, 0, 0, 0];
878        let x: Result<&[u8; 8], _> = try_transmute_ref!(&u);
879        assert_eq!(x, Ok(&array));
880
881        // Test that a mutable reference can be turned into an immutable one.
882        let mut x = 0u8;
883        #[allow(clippy::useless_transmute)]
884        let y: Result<&u8, _> = try_transmute_ref!(&mut x);
885        assert_eq!(y, Ok(&0));
886    }
887
888    #[test]
889    fn test_try_transmute_mut() {
890        // Test that memory is transmuted with `try_transmute_mut` as expected.
891        let array_of_bools = &mut [false, true, false, true, false, true, false, true];
892        let array_of_arrays = &mut [[0u8, 1], [0, 1], [0, 1], [0, 1]];
893        let x: Result<&mut [[u8; 2]; 4], _> = try_transmute_mut!(array_of_bools);
894        assert_eq!(x, Ok(array_of_arrays));
895
896        let array_of_bools = &mut [false, true, false, true, false, true, false, true];
897        let array_of_arrays = &mut [[0u8, 1], [0, 1], [0, 1], [0, 1]];
898        let x: Result<&mut [bool; 8], _> = try_transmute_mut!(array_of_arrays);
899        assert_eq!(x, Ok(array_of_bools));
900
901        // Test that it's legal to transmute a reference while shrinking the
902        // lifetime.
903        let array_of_bools = &mut [false, true, false, true, false, true, false, true];
904        let array_of_arrays = &mut [[0u8, 1], [0, 1], [0, 1], [0, 1]];
905        {
906            let x: Result<&mut [[u8; 2]; 4], _> = try_transmute_mut!(array_of_bools);
907            assert_eq!(x, Ok(array_of_arrays));
908        }
909
910        // Test that `try_transmute_mut!` supports decreasing alignment.
911        let u = &mut AU64(0);
912        let array = &mut [0u8, 0, 0, 0, 0, 0, 0, 0];
913        let x: Result<&mut [u8; 8], _> = try_transmute_mut!(u);
914        assert_eq!(x, Ok(array));
915
916        // Test that a mutable reference can be turned into an immutable one.
917        let mut x = 0u8;
918        #[allow(clippy::useless_transmute)]
919        let y: Result<&mut u8, _> = try_transmute_mut!(&mut x);
920        assert_eq!(y, Ok(&mut 0));
921    }
922
923    #[test]
924    fn test_transmute_mut() {
925        // Test that memory is transmuted as expected.
926        let mut array_of_u8s = [0u8, 1, 2, 3, 4, 5, 6, 7];
927        let mut array_of_arrays = [[0, 1], [2, 3], [4, 5], [6, 7]];
928        let x: &mut [[u8; 2]; 4] = transmute_mut!(&mut array_of_u8s);
929        assert_eq!(*x, array_of_arrays);
930        let x: &mut [u8; 8] = transmute_mut!(&mut array_of_arrays);
931        assert_eq!(*x, array_of_u8s);
932
933        {
934            // Test that it's legal to transmute a reference while shrinking the
935            // lifetime.
936            let x: &mut [u8; 8] = transmute_mut!(&mut array_of_arrays);
937            assert_eq!(*x, array_of_u8s);
938        }
939        // Test that `transmute_mut!` supports decreasing alignment.
940        let mut u = AU64(0);
941        let array = [0, 0, 0, 0, 0, 0, 0, 0];
942        let x: &[u8; 8] = transmute_mut!(&mut u);
943        assert_eq!(*x, array);
944
945        // Test that a mutable reference can be turned into an immutable one.
946        let mut x = 0u8;
947        #[allow(clippy::useless_transmute)]
948        let y: &u8 = transmute_mut!(&mut x);
949        assert_eq!(*y, 0);
950    }
951
952    #[test]
953    fn test_macros_evaluate_args_once() {
954        let mut ctr = 0;
955        #[allow(clippy::useless_transmute)]
956        let _: usize = transmute!({
957            ctr += 1;
958            0usize
959        });
960        assert_eq!(ctr, 1);
961
962        let mut ctr = 0;
963        let _: &usize = transmute_ref!({
964            ctr += 1;
965            &0usize
966        });
967        assert_eq!(ctr, 1);
968
969        let mut ctr: usize = 0;
970        let _: &mut usize = transmute_mut!({
971            ctr += 1;
972            &mut ctr
973        });
974        assert_eq!(ctr, 1);
975
976        let mut ctr = 0;
977        #[allow(clippy::useless_transmute)]
978        let _: usize = try_transmute!({
979            ctr += 1;
980            0usize
981        })
982        .unwrap();
983        assert_eq!(ctr, 1);
984    }
985
986    #[test]
987    fn test_include_value() {
988        const AS_U32: u32 = include_value!("../testdata/include_value/data");
989        assert_eq!(AS_U32, u32::from_ne_bytes([b'a', b'b', b'c', b'd']));
990        const AS_I32: i32 = include_value!("../testdata/include_value/data");
991        assert_eq!(AS_I32, i32::from_ne_bytes([b'a', b'b', b'c', b'd']));
992    }
993}