Coverage Report

Created: 2025-07-18 06:16

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