Skip to main content

zerocopy/
macros.rs

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