]> git.proxmox.com Git - rustc.git/blob - vendor/zerocopy-derive/tests/struct_as_bytes.rs
New upstream version 1.76.0+dfsg1
[rustc.git] / vendor / zerocopy-derive / tests / struct_as_bytes.rs
1 // Copyright 2019 The Fuchsia Authors
2 //
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
7 // those terms.
8
9 #![allow(warnings)]
10
11 mod util;
12
13 use std::{marker::PhantomData, mem::ManuallyDrop, option::IntoIter};
14
15 use {static_assertions::assert_impl_all, zerocopy::AsBytes};
16
17 use self::util::AU16;
18
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)
23 // - `repr(packed)`
24
25 #[derive(AsBytes)]
26 #[repr(C)]
27 struct CZst;
28
29 assert_impl_all!(CZst: AsBytes);
30
31 #[derive(AsBytes)]
32 #[repr(C)]
33 struct C {
34 a: u8,
35 b: u8,
36 c: AU16,
37 }
38
39 assert_impl_all!(C: AsBytes);
40
41 #[derive(AsBytes)]
42 #[repr(transparent)]
43 struct Transparent {
44 a: u8,
45 b: CZst,
46 }
47
48 assert_impl_all!(Transparent: AsBytes);
49
50 #[derive(AsBytes)]
51 #[repr(transparent)]
52 struct TransparentGeneric<T: ?Sized> {
53 a: CZst,
54 b: T,
55 }
56
57 assert_impl_all!(TransparentGeneric<u64>: AsBytes);
58 assert_impl_all!(TransparentGeneric<[u64]>: AsBytes);
59
60 #[derive(AsBytes)]
61 #[repr(C, packed)]
62 struct CZstPacked;
63
64 assert_impl_all!(CZstPacked: AsBytes);
65
66 #[derive(AsBytes)]
67 #[repr(C, packed)]
68 struct CPacked {
69 a: u8,
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
76 // deal.
77 b: u16,
78 }
79
80 assert_impl_all!(CPacked: AsBytes);
81
82 #[derive(AsBytes)]
83 #[repr(C, packed(2))]
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.
87 struct CPacked2 {
88 a: u16,
89 b: u64,
90 }
91
92 assert_impl_all!(CPacked2: AsBytes);
93
94 #[derive(AsBytes)]
95 #[repr(C, packed)]
96 struct CPackedGeneric<T, U: ?Sized> {
97 t: T,
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
102 // types.
103 u: ManuallyDrop<U>,
104 }
105
106 assert_impl_all!(CPackedGeneric<u8, AU16>: AsBytes);
107 assert_impl_all!(CPackedGeneric<u8, [AU16]>: AsBytes);
108
109 #[derive(AsBytes)]
110 #[repr(packed)]
111 struct Packed {
112 a: u8,
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
119 // deal.
120 b: u16,
121 }
122
123 assert_impl_all!(Packed: AsBytes);
124
125 #[derive(AsBytes)]
126 #[repr(packed)]
127 struct PackedGeneric<T, U: ?Sized> {
128 t: T,
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
133 // types.
134 u: ManuallyDrop<U>,
135 }
136
137 assert_impl_all!(PackedGeneric<u8, AU16>: AsBytes);
138 assert_impl_all!(PackedGeneric<u8, [AU16]>: AsBytes);
139
140 #[derive(AsBytes)]
141 #[repr(transparent)]
142 struct Unsized {
143 a: [u8],
144 }
145
146 assert_impl_all!(Unsized: AsBytes);
147
148 // Deriving `AsBytes` should work if the struct has bounded parameters.
149
150 #[derive(AsBytes)]
151 #[repr(transparent)]
152 struct WithParams<'a: 'b, 'b: 'a, const N: usize, T: 'a + 'b + AsBytes>(
153 [T; N],
154 PhantomData<&'a &'b ()>,
155 )
156 where
157 'a: 'b,
158 'b: 'a,
159 T: 'a + 'b + AsBytes;
160
161 assert_impl_all!(WithParams<'static, 'static, 42, u8>: AsBytes);