• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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]
53 macro_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]
168 macro_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,
253 ///     Dst: FromBytes + IntoBytes,
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]
316 macro_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` and that
329             // the type of this macro expression is `&mut U` where `U: 'u +
330             // Sized + FromBytes + IntoBytes`.
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]
440 macro_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]
536 macro_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: FromBytes + IntoBytes,
581 ///     Dst: TryFromBytes + IntoBytes,
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]
646 macro_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]
730 macro_rules! include_value {
731     ($file:expr $(,)?) => {
732         $crate::transmute!(*::core::include_bytes!($file))
733     };
734 }
735 
736 #[doc(hidden)]
737 #[macro_export]
738 macro_rules! cryptocorrosion_derive_traits {
739     (
740         #[repr($repr:ident)]
741         $(#[$attr:meta])*
742         $vis:vis struct $name:ident $(<$($tyvar:ident),*>)?
743         $(
744             (
745                 $($tuple_field_vis:vis $tuple_field_ty:ty),*
746             );
747         )?
748 
749         $(
750             {
751                 $($field_vis:vis $field_name:ident: $field_ty:ty,)*
752             }
753         )?
754     ) => {
755         $crate::cryptocorrosion_derive_traits!(@assert_allowed_struct_repr #[repr($repr)]);
756 
757         $(#[$attr])*
758         #[repr($repr)]
759         $vis struct $name $(<$($tyvar),*>)?
760         $(
761             (
762                 $($tuple_field_vis $tuple_field_ty),*
763             );
764         )?
765 
766         $(
767             {
768                 $($field_vis $field_name: $field_ty,)*
769             }
770         )?
771 
772         // SAFETY: See inline.
773         unsafe impl $(<$($tyvar),*>)? $crate::TryFromBytes for $name$(<$($tyvar),*>)?
774         where
775             $(
776                 $($tuple_field_ty: $crate::FromBytes,)*
777             )?
778 
779             $(
780                 $($field_ty: $crate::FromBytes,)*
781             )?
782         {
783             fn is_bit_valid<A>(_c: $crate::Maybe<'_, Self, A>) -> bool
784             where
785                 A: $crate::pointer::invariant::Reference
786             {
787                 // SAFETY: This macro only accepts `#[repr(C)]` and
788                 // `#[repr(transparent)]` structs, and this `impl` block
789                 // requires all field types to be `FromBytes`. Thus, all
790                 // initialized byte sequences constitutes valid instances of
791                 // `Self`.
792                 true
793             }
794 
795             fn only_derive_is_allowed_to_implement_this_trait() {}
796         }
797 
798         // SAFETY: This macro only accepts `#[repr(C)]` and
799         // `#[repr(transparent)]` structs, and this `impl` block requires all
800         // field types to be `FromBytes`, which is a sub-trait of `FromZeros`.
801         unsafe impl $(<$($tyvar),*>)? $crate::FromZeros for $name$(<$($tyvar),*>)?
802         where
803             $(
804                 $($tuple_field_ty: $crate::FromBytes,)*
805             )?
806 
807             $(
808                 $($field_ty: $crate::FromBytes,)*
809             )?
810         {
811             fn only_derive_is_allowed_to_implement_this_trait() {}
812         }
813 
814         // SAFETY: This macro only accepts `#[repr(C)]` and
815         // `#[repr(transparent)]` structs, and this `impl` block requires all
816         // field types to be `FromBytes`.
817         unsafe impl $(<$($tyvar),*>)? $crate::FromBytes for $name$(<$($tyvar),*>)?
818         where
819             $(
820                 $($tuple_field_ty: $crate::FromBytes,)*
821             )?
822 
823             $(
824                 $($field_ty: $crate::FromBytes,)*
825             )?
826         {
827             fn only_derive_is_allowed_to_implement_this_trait() {}
828         }
829 
830         // SAFETY: This macro only accepts `#[repr(C)]` and
831         // `#[repr(transparent)]` structs, this `impl` block requires all field
832         // types to be `IntoBytes`, and a padding check is used to ensures that
833         // there are no padding bytes.
834         unsafe impl $(<$($tyvar),*>)? $crate::IntoBytes for $name$(<$($tyvar),*>)?
835         where
836             $(
837                 $($tuple_field_ty: $crate::IntoBytes,)*
838             )?
839 
840             $(
841                 $($field_ty: $crate::IntoBytes,)*
842             )?
843 
844             (): $crate::util::macro_util::PaddingFree<
845                 Self,
846                 {
847                     $crate::cryptocorrosion_derive_traits!(
848                         @struct_padding_check #[repr($repr)]
849                         $(($($tuple_field_ty),*))?
850                         $({$($field_ty),*})?
851                     )
852                 },
853             >,
854         {
855             fn only_derive_is_allowed_to_implement_this_trait() {}
856         }
857 
858         // SAFETY: This macro only accepts `#[repr(C)]` and
859         // `#[repr(transparent)]` structs, and this `impl` block requires all
860         // field types to be `Immutable`.
861         unsafe impl $(<$($tyvar),*>)? $crate::Immutable for $name$(<$($tyvar),*>)?
862         where
863             $(
864                 $($tuple_field_ty: $crate::Immutable,)*
865             )?
866 
867             $(
868                 $($field_ty: $crate::Immutable,)*
869             )?
870         {
871             fn only_derive_is_allowed_to_implement_this_trait() {}
872         }
873     };
874     (@assert_allowed_struct_repr #[repr(transparent)]) => {};
875     (@assert_allowed_struct_repr #[repr(C)]) => {};
876     (@assert_allowed_struct_repr #[$_attr:meta]) => {
877         compile_error!("repr must be `#[repr(transparent)]` or `#[repr(C)]`");
878     };
879     (
880         @struct_padding_check #[repr(transparent)]
881         $(($($tuple_field_ty:ty),*))?
882         $({$($field_ty:ty),*})?
883     ) => {
884         // SAFETY: `#[repr(transparent)]` structs cannot have the same layout as
885         // their single non-zero-sized field, and so cannot have any padding
886         // outside of that field.
887         false
888     };
889     (
890         @struct_padding_check #[repr(C)]
891         $(($($tuple_field_ty:ty),*))?
892         $({$($field_ty:ty),*})?
893     ) => {
894         $crate::struct_has_padding!(
895             Self,
896             [
897                 $($($tuple_field_ty),*)?
898                 $($($field_ty),*)?
899             ]
900         )
901     };
902     (
903         #[repr(C)]
904         $(#[$attr:meta])*
905         $vis:vis union $name:ident {
906             $(
907                 $field_name:ident: $field_ty:ty,
908             )*
909         }
910     ) => {
911         $(#[$attr])*
912         #[repr(C)]
913         $vis union $name {
914             $(
915                 $field_name: $field_ty,
916             )*
917         }
918 
919         // SAFETY: See inline.
920         unsafe impl $crate::TryFromBytes for $name
921         where
922             $(
923                 $field_ty: $crate::FromBytes,
924             )*
925         {
926             fn is_bit_valid<A>(_c: $crate::Maybe<'_, Self, A>) -> bool
927             where
928                 A: $crate::pointer::invariant::Reference
929             {
930                 // SAFETY: This macro only accepts `#[repr(C)]` unions, and this
931                 // `impl` block requires all field types to be `FromBytes`.
932                 // Thus, all initialized byte sequences constitutes valid
933                 // instances of `Self`.
934                 true
935             }
936 
937             fn only_derive_is_allowed_to_implement_this_trait() {}
938         }
939 
940         // SAFETY: This macro only accepts `#[repr(C)]` unions, and this `impl`
941         // block requires all field types to be `FromBytes`, which is a
942         // sub-trait of `FromZeros`.
943         unsafe impl $crate::FromZeros for $name
944         where
945             $(
946                 $field_ty: $crate::FromBytes,
947             )*
948         {
949             fn only_derive_is_allowed_to_implement_this_trait() {}
950         }
951 
952         // SAFETY: This macro only accepts `#[repr(C)]` unions, and this `impl`
953         // block requires all field types to be `FromBytes`.
954         unsafe impl $crate::FromBytes for $name
955         where
956             $(
957                 $field_ty: $crate::FromBytes,
958             )*
959         {
960             fn only_derive_is_allowed_to_implement_this_trait() {}
961         }
962 
963         // SAFETY: This macro only accepts `#[repr(C)]` unions, this `impl`
964         // block requires all field types to be `IntoBytes`, and a padding check
965         // is used to ensures that there are no padding bytes before or after
966         // any field.
967         unsafe impl $crate::IntoBytes for $name
968         where
969             $(
970                 $field_ty: $crate::IntoBytes,
971             )*
972             (): $crate::util::macro_util::PaddingFree<
973                 Self,
974                 {
975                     $crate::union_has_padding!(
976                         Self,
977                         [$($field_ty),*]
978                     )
979                 },
980             >,
981         {
982             fn only_derive_is_allowed_to_implement_this_trait() {}
983         }
984 
985         // SAFETY: This macro only accepts `#[repr(C)]` unions, and this `impl`
986         // block requires all field types to be `Immutable`.
987         unsafe impl $crate::Immutable for $name
988         where
989             $(
990                 $field_ty: $crate::Immutable,
991             )*
992         {
993             fn only_derive_is_allowed_to_implement_this_trait() {}
994         }
995     };
996 }
997 
998 #[cfg(test)]
999 mod tests {
1000     use crate::util::testutil::*;
1001     use crate::*;
1002 
1003     #[test]
test_transmute()1004     fn test_transmute() {
1005         // Test that memory is transmuted as expected.
1006         let array_of_u8s = [0u8, 1, 2, 3, 4, 5, 6, 7];
1007         let array_of_arrays = [[0, 1], [2, 3], [4, 5], [6, 7]];
1008         let x: [[u8; 2]; 4] = transmute!(array_of_u8s);
1009         assert_eq!(x, array_of_arrays);
1010         let x: [u8; 8] = transmute!(array_of_arrays);
1011         assert_eq!(x, array_of_u8s);
1012 
1013         // Test that the source expression's value is forgotten rather than
1014         // dropped.
1015         #[derive(IntoBytes)]
1016         #[repr(transparent)]
1017         struct PanicOnDrop(());
1018         impl Drop for PanicOnDrop {
1019             fn drop(&mut self) {
1020                 panic!("PanicOnDrop::drop");
1021             }
1022         }
1023         #[allow(clippy::let_unit_value)]
1024         let _: () = transmute!(PanicOnDrop(()));
1025 
1026         // Test that `transmute!` is legal in a const context.
1027         const ARRAY_OF_U8S: [u8; 8] = [0u8, 1, 2, 3, 4, 5, 6, 7];
1028         const ARRAY_OF_ARRAYS: [[u8; 2]; 4] = [[0, 1], [2, 3], [4, 5], [6, 7]];
1029         const X: [[u8; 2]; 4] = transmute!(ARRAY_OF_U8S);
1030         assert_eq!(X, ARRAY_OF_ARRAYS);
1031 
1032         // Test that `transmute!` works with `!Immutable` types.
1033         let x: usize = transmute!(UnsafeCell::new(1usize));
1034         assert_eq!(x, 1);
1035         let x: UnsafeCell<usize> = transmute!(1usize);
1036         assert_eq!(x.into_inner(), 1);
1037         let x: UnsafeCell<isize> = transmute!(UnsafeCell::new(1usize));
1038         assert_eq!(x.into_inner(), 1);
1039     }
1040 
1041     #[test]
test_transmute_ref()1042     fn test_transmute_ref() {
1043         // Test that memory is transmuted as expected.
1044         let array_of_u8s = [0u8, 1, 2, 3, 4, 5, 6, 7];
1045         let array_of_arrays = [[0, 1], [2, 3], [4, 5], [6, 7]];
1046         let x: &[[u8; 2]; 4] = transmute_ref!(&array_of_u8s);
1047         assert_eq!(*x, array_of_arrays);
1048         let x: &[u8; 8] = transmute_ref!(&array_of_arrays);
1049         assert_eq!(*x, array_of_u8s);
1050 
1051         // Test that `transmute_ref!` is legal in a const context.
1052         const ARRAY_OF_U8S: [u8; 8] = [0u8, 1, 2, 3, 4, 5, 6, 7];
1053         const ARRAY_OF_ARRAYS: [[u8; 2]; 4] = [[0, 1], [2, 3], [4, 5], [6, 7]];
1054         #[allow(clippy::redundant_static_lifetimes)]
1055         const X: &'static [[u8; 2]; 4] = transmute_ref!(&ARRAY_OF_U8S);
1056         assert_eq!(*X, ARRAY_OF_ARRAYS);
1057 
1058         // Test that it's legal to transmute a reference while shrinking the
1059         // lifetime (note that `X` has the lifetime `'static`).
1060         let x: &[u8; 8] = transmute_ref!(X);
1061         assert_eq!(*x, ARRAY_OF_U8S);
1062 
1063         // Test that `transmute_ref!` supports decreasing alignment.
1064         let u = AU64(0);
1065         let array = [0, 0, 0, 0, 0, 0, 0, 0];
1066         let x: &[u8; 8] = transmute_ref!(&u);
1067         assert_eq!(*x, array);
1068 
1069         // Test that a mutable reference can be turned into an immutable one.
1070         let mut x = 0u8;
1071         #[allow(clippy::useless_transmute)]
1072         let y: &u8 = transmute_ref!(&mut x);
1073         assert_eq!(*y, 0);
1074     }
1075 
1076     #[test]
test_try_transmute()1077     fn test_try_transmute() {
1078         // Test that memory is transmuted with `try_transmute` as expected.
1079         let array_of_bools = [false, true, false, true, false, true, false, true];
1080         let array_of_arrays = [[0, 1], [0, 1], [0, 1], [0, 1]];
1081         let x: Result<[[u8; 2]; 4], _> = try_transmute!(array_of_bools);
1082         assert_eq!(x, Ok(array_of_arrays));
1083         let x: Result<[bool; 8], _> = try_transmute!(array_of_arrays);
1084         assert_eq!(x, Ok(array_of_bools));
1085 
1086         // Test that `try_transmute!` works with `!Immutable` types.
1087         let x: Result<usize, _> = try_transmute!(UnsafeCell::new(1usize));
1088         assert_eq!(x.unwrap(), 1);
1089         let x: Result<UnsafeCell<usize>, _> = try_transmute!(1usize);
1090         assert_eq!(x.unwrap().into_inner(), 1);
1091         let x: Result<UnsafeCell<isize>, _> = try_transmute!(UnsafeCell::new(1usize));
1092         assert_eq!(x.unwrap().into_inner(), 1);
1093 
1094         #[derive(FromBytes, IntoBytes, Debug, PartialEq)]
1095         #[repr(transparent)]
1096         struct PanicOnDrop<T>(T);
1097 
1098         impl<T> Drop for PanicOnDrop<T> {
1099             fn drop(&mut self) {
1100                 panic!("PanicOnDrop dropped");
1101             }
1102         }
1103 
1104         // Since `try_transmute!` semantically moves its argument on failure,
1105         // the `PanicOnDrop` is not dropped, and thus this shouldn't panic.
1106         let x: Result<usize, _> = try_transmute!(PanicOnDrop(1usize));
1107         assert_eq!(x, Ok(1));
1108 
1109         // Since `try_transmute!` semantically returns ownership of its argument
1110         // on failure, the `PanicOnDrop` is returned rather than dropped, and
1111         // thus this shouldn't panic.
1112         let y: Result<bool, _> = try_transmute!(PanicOnDrop(2u8));
1113         // We have to use `map_err` instead of comparing against
1114         // `Err(PanicOnDrop(2u8))` because the latter would create and then drop
1115         // its `PanicOnDrop` temporary, which would cause a panic.
1116         assert_eq!(y.as_ref().map_err(|p| &p.src.0), Err::<&bool, _>(&2u8));
1117         mem::forget(y);
1118     }
1119 
1120     #[test]
test_try_transmute_ref()1121     fn test_try_transmute_ref() {
1122         // Test that memory is transmuted with `try_transmute_ref` as expected.
1123         let array_of_bools = &[false, true, false, true, false, true, false, true];
1124         let array_of_arrays = &[[0, 1], [0, 1], [0, 1], [0, 1]];
1125         let x: Result<&[[u8; 2]; 4], _> = try_transmute_ref!(array_of_bools);
1126         assert_eq!(x, Ok(array_of_arrays));
1127         let x: Result<&[bool; 8], _> = try_transmute_ref!(array_of_arrays);
1128         assert_eq!(x, Ok(array_of_bools));
1129 
1130         // Test that it's legal to transmute a reference while shrinking the
1131         // lifetime.
1132         {
1133             let x: Result<&[[u8; 2]; 4], _> = try_transmute_ref!(array_of_bools);
1134             assert_eq!(x, Ok(array_of_arrays));
1135         }
1136 
1137         // Test that `try_transmute_ref!` supports decreasing alignment.
1138         let u = AU64(0);
1139         let array = [0u8, 0, 0, 0, 0, 0, 0, 0];
1140         let x: Result<&[u8; 8], _> = try_transmute_ref!(&u);
1141         assert_eq!(x, Ok(&array));
1142 
1143         // Test that a mutable reference can be turned into an immutable one.
1144         let mut x = 0u8;
1145         #[allow(clippy::useless_transmute)]
1146         let y: Result<&u8, _> = try_transmute_ref!(&mut x);
1147         assert_eq!(y, Ok(&0));
1148     }
1149 
1150     #[test]
test_try_transmute_mut()1151     fn test_try_transmute_mut() {
1152         // Test that memory is transmuted with `try_transmute_mut` as expected.
1153         let array_of_u8s = &mut [0u8, 1, 0, 1, 0, 1, 0, 1];
1154         let array_of_arrays = &mut [[0u8, 1], [0, 1], [0, 1], [0, 1]];
1155         let x: Result<&mut [[u8; 2]; 4], _> = try_transmute_mut!(array_of_u8s);
1156         assert_eq!(x, Ok(array_of_arrays));
1157 
1158         let array_of_bools = &mut [false, true, false, true, false, true, false, true];
1159         let array_of_arrays = &mut [[0u8, 1], [0, 1], [0, 1], [0, 1]];
1160         let x: Result<&mut [bool; 8], _> = try_transmute_mut!(array_of_arrays);
1161         assert_eq!(x, Ok(array_of_bools));
1162 
1163         // Test that it's legal to transmute a reference while shrinking the
1164         // lifetime.
1165         let array_of_bools = &mut [false, true, false, true, false, true, false, true];
1166         let array_of_arrays = &mut [[0u8, 1], [0, 1], [0, 1], [0, 1]];
1167         {
1168             let x: Result<&mut [bool; 8], _> = try_transmute_mut!(array_of_arrays);
1169             assert_eq!(x, Ok(array_of_bools));
1170         }
1171 
1172         // Test that `try_transmute_mut!` supports decreasing alignment.
1173         let u = &mut AU64(0);
1174         let array = &mut [0u8, 0, 0, 0, 0, 0, 0, 0];
1175         let x: Result<&mut [u8; 8], _> = try_transmute_mut!(u);
1176         assert_eq!(x, Ok(array));
1177 
1178         // Test that a mutable reference can be turned into an immutable one.
1179         let mut x = 0u8;
1180         #[allow(clippy::useless_transmute)]
1181         let y: Result<&mut u8, _> = try_transmute_mut!(&mut x);
1182         assert_eq!(y, Ok(&mut 0));
1183     }
1184 
1185     #[test]
test_transmute_mut()1186     fn test_transmute_mut() {
1187         // Test that memory is transmuted as expected.
1188         let mut array_of_u8s = [0u8, 1, 2, 3, 4, 5, 6, 7];
1189         let mut array_of_arrays = [[0, 1], [2, 3], [4, 5], [6, 7]];
1190         let x: &mut [[u8; 2]; 4] = transmute_mut!(&mut array_of_u8s);
1191         assert_eq!(*x, array_of_arrays);
1192         let x: &mut [u8; 8] = transmute_mut!(&mut array_of_arrays);
1193         assert_eq!(*x, array_of_u8s);
1194 
1195         {
1196             // Test that it's legal to transmute a reference while shrinking the
1197             // lifetime.
1198             let x: &mut [u8; 8] = transmute_mut!(&mut array_of_arrays);
1199             assert_eq!(*x, array_of_u8s);
1200         }
1201         // Test that `transmute_mut!` supports decreasing alignment.
1202         let mut u = AU64(0);
1203         let array = [0, 0, 0, 0, 0, 0, 0, 0];
1204         let x: &[u8; 8] = transmute_mut!(&mut u);
1205         assert_eq!(*x, array);
1206 
1207         // Test that a mutable reference can be turned into an immutable one.
1208         let mut x = 0u8;
1209         #[allow(clippy::useless_transmute)]
1210         let y: &u8 = transmute_mut!(&mut x);
1211         assert_eq!(*y, 0);
1212     }
1213 
1214     #[test]
test_macros_evaluate_args_once()1215     fn test_macros_evaluate_args_once() {
1216         let mut ctr = 0;
1217         #[allow(clippy::useless_transmute)]
1218         let _: usize = transmute!({
1219             ctr += 1;
1220             0usize
1221         });
1222         assert_eq!(ctr, 1);
1223 
1224         let mut ctr = 0;
1225         let _: &usize = transmute_ref!({
1226             ctr += 1;
1227             &0usize
1228         });
1229         assert_eq!(ctr, 1);
1230 
1231         let mut ctr: usize = 0;
1232         let _: &mut usize = transmute_mut!({
1233             ctr += 1;
1234             &mut ctr
1235         });
1236         assert_eq!(ctr, 1);
1237 
1238         let mut ctr = 0;
1239         #[allow(clippy::useless_transmute)]
1240         let _: usize = try_transmute!({
1241             ctr += 1;
1242             0usize
1243         })
1244         .unwrap();
1245         assert_eq!(ctr, 1);
1246     }
1247 
1248     #[test]
test_include_value()1249     fn test_include_value() {
1250         const AS_U32: u32 = include_value!("../testdata/include_value/data");
1251         assert_eq!(AS_U32, u32::from_ne_bytes([b'a', b'b', b'c', b'd']));
1252         const AS_I32: i32 = include_value!("../testdata/include_value/data");
1253         assert_eq!(AS_I32, i32::from_ne_bytes([b'a', b'b', b'c', b'd']));
1254     }
1255 
1256     #[test]
1257     #[allow(non_camel_case_types, unreachable_pub, dead_code)]
test_cryptocorrosion_derive_traits()1258     fn test_cryptocorrosion_derive_traits() {
1259         // Test the set of invocations added in
1260         // https://github.com/cryptocorrosion/cryptocorrosion/pull/85
1261 
1262         fn assert_impls<T: FromBytes + IntoBytes + Immutable>() {}
1263 
1264         cryptocorrosion_derive_traits! {
1265             #[repr(C)]
1266             #[derive(Clone, Copy)]
1267             pub union vec128_storage {
1268                 d: [u32; 4],
1269                 q: [u64; 2],
1270             }
1271         }
1272 
1273         assert_impls::<vec128_storage>();
1274 
1275         cryptocorrosion_derive_traits! {
1276             #[repr(transparent)]
1277             #[derive(Copy, Clone, Debug, PartialEq)]
1278             pub struct u32x4_generic([u32; 4]);
1279         }
1280 
1281         assert_impls::<u32x4_generic>();
1282 
1283         cryptocorrosion_derive_traits! {
1284             #[repr(transparent)]
1285             #[derive(Copy, Clone, Debug, PartialEq)]
1286             pub struct u64x2_generic([u64; 2]);
1287         }
1288 
1289         assert_impls::<u64x2_generic>();
1290 
1291         cryptocorrosion_derive_traits! {
1292             #[repr(transparent)]
1293             #[derive(Copy, Clone, Debug, PartialEq)]
1294             pub struct u128x1_generic([u128; 1]);
1295         }
1296 
1297         assert_impls::<u128x1_generic>();
1298 
1299         cryptocorrosion_derive_traits! {
1300             #[repr(transparent)]
1301             #[derive(Copy, Clone, Default)]
1302             #[allow(non_camel_case_types)]
1303             pub struct x2<W, G>(pub [W; 2], PhantomData<G>);
1304         }
1305 
1306         enum NotZerocopy {}
1307         assert_impls::<x2<(), NotZerocopy>>();
1308 
1309         cryptocorrosion_derive_traits! {
1310             #[repr(transparent)]
1311             #[derive(Copy, Clone, Default)]
1312             #[allow(non_camel_case_types)]
1313             pub struct x4<W>(pub [W; 4]);
1314         }
1315 
1316         assert_impls::<x4<()>>();
1317 
1318         #[cfg(feature = "simd")]
1319         #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
1320         {
1321             #[cfg(target_arch = "x86")]
1322             use core::arch::x86::{__m128i, __m256i};
1323             #[cfg(target_arch = "x86_64")]
1324             use core::arch::x86_64::{__m128i, __m256i};
1325 
1326             cryptocorrosion_derive_traits! {
1327                 #[repr(C)]
1328                 #[derive(Copy, Clone)]
1329                 pub struct X4(__m128i, __m128i, __m128i, __m128i);
1330             }
1331 
1332             assert_impls::<X4>();
1333 
1334             cryptocorrosion_derive_traits! {
1335                 #[repr(C)]
1336                 /// Generic wrapper for unparameterized storage of any of the possible impls.
1337                 /// Converting into and out of this type should be essentially free, although it may be more
1338                 /// aligned than a particular impl requires.
1339                 #[allow(non_camel_case_types)]
1340                 #[derive(Copy, Clone)]
1341                 pub union vec128_storage {
1342                     u32x4: [u32; 4],
1343                     u64x2: [u64; 2],
1344                     u128x1: [u128; 1],
1345                     sse2: __m128i,
1346                 }
1347             }
1348 
1349             assert_impls::<vec128_storage>();
1350 
1351             cryptocorrosion_derive_traits! {
1352                 #[repr(transparent)]
1353                 #[allow(non_camel_case_types)]
1354                 #[derive(Copy, Clone)]
1355                 pub struct vec<S3, S4, NI> {
1356                     x: __m128i,
1357                     s3: PhantomData<S3>,
1358                     s4: PhantomData<S4>,
1359                     ni: PhantomData<NI>,
1360                 }
1361             }
1362 
1363             assert_impls::<vec<NotZerocopy, NotZerocopy, NotZerocopy>>();
1364 
1365             cryptocorrosion_derive_traits! {
1366                 #[repr(transparent)]
1367                 #[derive(Copy, Clone)]
1368                 pub struct u32x4x2_avx2<NI> {
1369                     x: __m256i,
1370                     ni: PhantomData<NI>,
1371                 }
1372             }
1373 
1374             assert_impls::<u32x4x2_avx2<NotZerocopy>>();
1375         }
1376 
1377         // Make sure that our derive works for `#[repr(C)]` structs even though
1378         // cryptocorrosion doesn't currently have any.
1379         cryptocorrosion_derive_traits! {
1380             #[repr(C)]
1381             #[derive(Copy, Clone, Debug, PartialEq)]
1382             pub struct ReprC(u8, u8, u16);
1383         }
1384     }
1385 }
1386