Coverage Report

Created: 2026-05-16 06:09

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