diff options
Diffstat (limited to 'src/derive_util.rs')
-rw-r--r-- | src/derive_util.rs | 127 |
1 files changed, 0 insertions, 127 deletions
diff --git a/src/derive_util.rs b/src/derive_util.rs deleted file mode 100644 index edf88e3..0000000 --- a/src/derive_util.rs +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright 2022 The Fuchsia Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -//! Utilities used by `zerocopy-derive`. -//! -//! These are defined in `zerocopy` rather than in code generated by -//! `zerocopy-derive` so that they can be compiled once rather than recompiled -//! for every pair of type and trait (in other words, if they were defined in -//! generated code, then deriving `AsBytes` and `FromBytes` on three different -//! types would result in the code in question being emitted and compiled six -//! different times). - -#![allow(missing_debug_implementations)] - -use core::marker::PhantomData; - -/// A compile-time check that should be one particular value. -pub trait ShouldBe<const VALUE: bool> {} - -/// A struct for checking whether `T` contains padding. -pub struct HasPadding<T: ?Sized, const VALUE: bool>(PhantomData<T>); - -impl<T: ?Sized, const VALUE: bool> ShouldBe<VALUE> for HasPadding<T, VALUE> {} - -/// Does the struct type `$t` have padding? -/// -/// `$ts` is the list of the type of every field in `$t`. `$t` must be a -/// struct type, or else `struct_has_padding!`'s result may be meaningless. -/// -/// Note that `struct_has_padding!`'s results are independent of `repr` since -/// they only consider the size of the type and the sizes of the fields. -/// Whatever the repr, the size of the type already takes into account any -/// padding that the compiler has decided to add. Structs with well-defined -/// representations (such as `repr(C)`) can use this macro to check for padding. -/// Note that while this may yield some consistent value for some `repr(Rust)` -/// structs, it is not guaranteed across platforms or compilations. -#[doc(hidden)] // `#[macro_export]` bypasses this module's `#[doc(hidden)]`. -#[macro_export] -macro_rules! struct_has_padding { - ($t:ty, $($ts:ty),*) => { - core::mem::size_of::<$t>() > 0 $(+ core::mem::size_of::<$ts>())* - }; -} - -/// Does the union type `$t` have padding? -/// -/// `$ts` is the list of the type of every field in `$t`. `$t` must be a -/// union type, or else `union_has_padding!`'s result may be meaningless. -/// -/// Note that `union_has_padding!`'s results are independent of `repr` since -/// they only consider the size of the type and the sizes of the fields. -/// Whatever the repr, the size of the type already takes into account any -/// padding that the compiler has decided to add. Unions with well-defined -/// representations (such as `repr(C)`) can use this macro to check for padding. -/// Note that while this may yield some consistent value for some `repr(Rust)` -/// unions, it is not guaranteed across platforms or compilations. -#[doc(hidden)] // `#[macro_export]` bypasses this module's `#[doc(hidden)]`. -#[macro_export] -macro_rules! union_has_padding { - ($t:ty, $($ts:ty),*) => { - false $(|| core::mem::size_of::<$t>() != core::mem::size_of::<$ts>())* - }; -} - -#[cfg(test)] -mod tests { - use crate::util::testutil::*; - - #[test] - fn test_struct_has_padding() { - // Test that, for each provided repr, `struct_has_padding!` reports the - // expected value. - macro_rules! test { - (#[$cfg:meta] ($($ts:ty),*) => $expect:expr) => {{ - #[$cfg] - struct Test($($ts),*); - assert_eq!(struct_has_padding!(Test, $($ts),*), $expect); - }}; - (#[$cfg:meta] $(#[$cfgs:meta])* ($($ts:ty),*) => $expect:expr) => { - test!(#[$cfg] ($($ts),*) => $expect); - test!($(#[$cfgs])* ($($ts),*) => $expect); - }; - } - - test!(#[repr(C)] #[repr(transparent)] #[repr(packed)] () => false); - test!(#[repr(C)] #[repr(transparent)] #[repr(packed)] (u8) => false); - test!(#[repr(C)] #[repr(transparent)] #[repr(packed)] (u8, ()) => false); - test!(#[repr(C)] #[repr(packed)] (u8, u8) => false); - - test!(#[repr(C)] (u8, AU64) => true); - // Rust won't let you put `#[repr(packed)]` on a type which contains a - // `#[repr(align(n > 1))]` type (`AU64`), so we have to use `u64` here. - // It's not ideal, but it definitely has align > 1 on /some/ of our CI - // targets, and this isn't a particularly complex macro we're testing - // anyway. - test!(#[repr(packed)] (u8, u64) => false); - } - - #[test] - fn test_union_has_padding() { - // Test that, for each provided repr, `union_has_padding!` reports the - // expected value. - macro_rules! test { - (#[$cfg:meta] {$($fs:ident: $ts:ty),*} => $expect:expr) => {{ - #[$cfg] - #[allow(unused)] // fields are never read - union Test{ $($fs: $ts),* } - assert_eq!(union_has_padding!(Test, $($ts),*), $expect); - }}; - (#[$cfg:meta] $(#[$cfgs:meta])* {$($fs:ident: $ts:ty),*} => $expect:expr) => { - test!(#[$cfg] {$($fs: $ts),*} => $expect); - test!($(#[$cfgs])* {$($fs: $ts),*} => $expect); - }; - } - - test!(#[repr(C)] #[repr(packed)] {a: u8} => false); - test!(#[repr(C)] #[repr(packed)] {a: u8, b: u8} => false); - - // Rust won't let you put `#[repr(packed)]` on a type which contains a - // `#[repr(align(n > 1))]` type (`AU64`), so we have to use `u64` here. - // It's not ideal, but it definitely has align > 1 on /some/ of our CI - // targets, and this isn't a particularly complex macro we're testing - // anyway. - test!(#[repr(C)] #[repr(packed)] {a: u8, b: u64} => true); - } -} |