Coverage Report

Created: 2026-09-28 07:57

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