1 // Copyright 2019 The Fuchsia Authors
3 // Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
4 // <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
5 // license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
6 // This file may not be copied, modified, or distributed except according to
13 use std
::{marker::PhantomData, mem::ManuallyDrop, option::IntoIter}
;
15 use {static_assertions::assert_impl_all, zerocopy::AsBytes}
;
19 // A struct is `AsBytes` if:
20 // - all fields are `AsBytes`
21 // - `repr(C)` or `repr(transparent)` and
22 // - no padding (size of struct equals sum of size of field types)
29 assert_impl_all
!(CZst
: AsBytes
);
39 assert_impl_all
!(C
: AsBytes
);
48 assert_impl_all
!(Transparent
: AsBytes
);
52 struct TransparentGeneric
<T
: ?Sized
> {
57 assert_impl_all
!(TransparentGeneric
<u64>: AsBytes
);
58 assert_impl_all
!(TransparentGeneric
<[u64]>: AsBytes
);
64 assert_impl_all
!(CZstPacked
: AsBytes
);
70 // NOTE: The `u16` type is not guaranteed to have alignment 2, although it
71 // does on many platforms. However, to fix this would require a custom type
72 // with a `#[repr(align(2))]` attribute, and `#[repr(packed)]` types are not
73 // allowed to transitively contain `#[repr(align(...))]` types. Thus, we
74 // have no choice but to use `u16` here. Luckily, these tests run in CI on
75 // platforms on which `u16` has alignment 2, so this isn't that big of a
80 assert_impl_all
!(CPacked
: AsBytes
);
84 // The same caveats as for CPacked apply - we're assuming u64 is at least
85 // 4-byte aligned by default. Without packed(2), this should fail, as there
86 // would be padding between a/b assuming u64 is 4+ byte aligned.
92 assert_impl_all
!(CPacked2
: AsBytes
);
96 struct CPackedGeneric
<T
, U
: ?Sized
> {
98 // Unsized types stored in `repr(packed)` structs must not be dropped
99 // because dropping them in-place might be unsound depending on the
100 // alignment of the outer struct. Sized types can be dropped by first being
101 // moved to an aligned stack variable, but this isn't possible with unsized
106 assert_impl_all
!(CPackedGeneric
<u8, AU16
>: AsBytes
);
107 assert_impl_all
!(CPackedGeneric
<u8, [AU16
]>: AsBytes
);
113 // NOTE: The `u16` type is not guaranteed to have alignment 2, although it
114 // does on many platforms. However, to fix this would require a custom type
115 // with a `#[repr(align(2))]` attribute, and `#[repr(packed)]` types are not
116 // allowed to transitively contain `#[repr(align(...))]` types. Thus, we
117 // have no choice but to use `u16` here. Luckily, these tests run in CI on
118 // platforms on which `u16` has alignment 2, so this isn't that big of a
123 assert_impl_all
!(Packed
: AsBytes
);
127 struct PackedGeneric
<T
, U
: ?Sized
> {
129 // Unsized types stored in `repr(packed)` structs must not be dropped
130 // because dropping them in-place might be unsound depending on the
131 // alignment of the outer struct. Sized types can be dropped by first being
132 // moved to an aligned stack variable, but this isn't possible with unsized
137 assert_impl_all
!(PackedGeneric
<u8, AU16
>: AsBytes
);
138 assert_impl_all
!(PackedGeneric
<u8, [AU16
]>: AsBytes
);
146 assert_impl_all
!(Unsized
: AsBytes
);
148 // Deriving `AsBytes` should work if the struct has bounded parameters.
152 struct WithParams
<'a
: 'b
, 'b
: 'a
, const N
: usize, T
: 'a
+ 'b
+ AsBytes
>(
154 PhantomData
<&'a
&'
b ()>,
159 T
: 'a
+ 'b
+ AsBytes
;
161 assert_impl_all
!(WithParams
<'
static, '
static, 42, u8>: AsBytes
);