1 #![allow(dead_code)]
2
3 use bytemuck::{
4 AnyBitPattern, CheckedBitPattern, Contiguous, NoUninit, Pod,
5 TransparentWrapper, Zeroable,
6 };
7 use std::marker::{PhantomData, PhantomPinned};
8
9 #[derive(Copy, Clone, Pod, Zeroable)]
10 #[repr(C)]
11 struct Test {
12 a: u16,
13 b: u16,
14 }
15
16 #[derive(Pod, Zeroable)]
17 #[repr(C, packed)]
18 struct GenericPackedStruct<T: Pod> {
19 a: u32,
20 b: T,
21 c: u32,
22 }
23
24 impl<T: Pod> Clone for GenericPackedStruct<T> {
clone(&self) -> Self25 fn clone(&self) -> Self {
26 *self
27 }
28 }
29
30 impl<T: Pod> Copy for GenericPackedStruct<T> {}
31
32 #[derive(Pod, Zeroable)]
33 #[repr(C, packed(1))]
34 struct GenericPackedStructExplicitPackedAlignment<T: Pod> {
35 a: u32,
36 b: T,
37 c: u32,
38 }
39
40 impl<T: Pod> Clone for GenericPackedStructExplicitPackedAlignment<T> {
clone(&self) -> Self41 fn clone(&self) -> Self {
42 *self
43 }
44 }
45
46 impl<T: Pod> Copy for GenericPackedStructExplicitPackedAlignment<T> {}
47
48 #[derive(Zeroable)]
49 struct ZeroGeneric<T: bytemuck::Zeroable> {
50 a: T,
51 }
52
53 #[derive(TransparentWrapper)]
54 #[repr(transparent)]
55 struct TransparentSingle {
56 a: u16,
57 }
58
59 #[derive(TransparentWrapper)]
60 #[repr(transparent)]
61 #[transparent(u16)]
62 struct TransparentWithZeroSized<T> {
63 a: u16,
64 b: PhantomData<T>,
65 }
66
67 struct MyZst<T>(PhantomData<T>, [u8; 0], PhantomPinned);
68 unsafe impl<T> Zeroable for MyZst<T> {}
69
70 #[derive(TransparentWrapper)]
71 #[repr(transparent)]
72 #[transparent(u16)]
73 struct TransparentTupleWithCustomZeroSized<T>(u16, MyZst<T>);
74
75 #[repr(u8)]
76 #[derive(Clone, Copy, Contiguous)]
77 enum ContiguousWithValues {
78 A = 0,
79 B = 1,
80 C = 2,
81 D = 3,
82 E = 4,
83 }
84
85 #[repr(i8)]
86 #[derive(Clone, Copy, Contiguous)]
87 enum ContiguousWithImplicitValues {
88 A = -10,
89 B,
90 C,
91 D,
92 E,
93 }
94
95 #[derive(Copy, Clone, NoUninit)]
96 #[repr(C)]
97 struct NoUninitTest {
98 a: u16,
99 b: u16,
100 }
101
102 #[derive(Copy, Clone, AnyBitPattern)]
103 #[repr(C)]
104 union UnionTestAnyBitPattern {
105 a: u8,
106 b: u16,
107 }
108
109 #[repr(u8)]
110 #[derive(Debug, Clone, Copy, NoUninit, CheckedBitPattern, PartialEq, Eq)]
111 enum CheckedBitPatternEnumWithValues {
112 A = 0,
113 B = 1,
114 C = 2,
115 D = 3,
116 E = 4,
117 }
118
119 #[repr(i8)]
120 #[derive(Clone, Copy, NoUninit, CheckedBitPattern)]
121 enum CheckedBitPatternEnumWithImplicitValues {
122 A = -10,
123 B,
124 C,
125 D,
126 E,
127 }
128
129 #[repr(u8)]
130 #[derive(Debug, Clone, Copy, NoUninit, CheckedBitPattern, PartialEq, Eq)]
131 enum CheckedBitPatternEnumNonContiguous {
132 A = 1,
133 B = 8,
134 C = 2,
135 D = 3,
136 E = 56,
137 }
138
139 #[repr(u8)]
140 #[derive(Debug, Clone, Copy, NoUninit, CheckedBitPattern, PartialEq, Eq)]
141 enum CheckedBitPatternEnumByteLit {
142 A = b'A',
143 B = b'B',
144 C = b'C',
145 D = b'D',
146 E = b'E',
147 }
148
149 #[derive(Debug, Copy, Clone, NoUninit, CheckedBitPattern, PartialEq, Eq)]
150 #[repr(C)]
151 struct CheckedBitPatternStruct {
152 a: u8,
153 b: CheckedBitPatternEnumNonContiguous,
154 }
155
156 #[derive(Debug, Copy, Clone, AnyBitPattern, PartialEq, Eq)]
157 #[repr(C)]
158 struct AnyBitPatternTest<A: AnyBitPattern, B: AnyBitPattern> {
159 a: A,
160 b: B,
161 }
162
163 #[test]
fails_cast_contiguous()164 fn fails_cast_contiguous() {
165 let can_cast = CheckedBitPatternEnumWithValues::is_valid_bit_pattern(&5);
166 assert!(!can_cast);
167 }
168
169 #[test]
passes_cast_contiguous()170 fn passes_cast_contiguous() {
171 let res =
172 bytemuck::checked::from_bytes::<CheckedBitPatternEnumWithValues>(&[2u8]);
173 assert_eq!(*res, CheckedBitPatternEnumWithValues::C);
174 }
175
176 #[test]
fails_cast_noncontiguous()177 fn fails_cast_noncontiguous() {
178 let can_cast = CheckedBitPatternEnumNonContiguous::is_valid_bit_pattern(&4);
179 assert!(!can_cast);
180 }
181
182 #[test]
passes_cast_noncontiguous()183 fn passes_cast_noncontiguous() {
184 let res =
185 bytemuck::checked::from_bytes::<CheckedBitPatternEnumNonContiguous>(&[
186 56u8,
187 ]);
188 assert_eq!(*res, CheckedBitPatternEnumNonContiguous::E);
189 }
190
191 #[test]
fails_cast_bytelit()192 fn fails_cast_bytelit() {
193 let can_cast = CheckedBitPatternEnumByteLit::is_valid_bit_pattern(&b'a');
194 assert!(!can_cast);
195 }
196
197 #[test]
passes_cast_bytelit()198 fn passes_cast_bytelit() {
199 let res =
200 bytemuck::checked::cast_slice::<u8, CheckedBitPatternEnumByteLit>(b"CAB");
201 assert_eq!(
202 res,
203 [
204 CheckedBitPatternEnumByteLit::C,
205 CheckedBitPatternEnumByteLit::A,
206 CheckedBitPatternEnumByteLit::B
207 ]
208 );
209 }
210
211 #[test]
fails_cast_struct()212 fn fails_cast_struct() {
213 let pod = [0u8, 24u8];
214 let res = bytemuck::checked::try_from_bytes::<CheckedBitPatternStruct>(&pod);
215 assert!(res.is_err());
216 }
217
218 #[test]
passes_cast_struct()219 fn passes_cast_struct() {
220 let pod = [0u8, 8u8];
221 let res = bytemuck::checked::from_bytes::<CheckedBitPatternStruct>(&pod);
222 assert_eq!(
223 *res,
224 CheckedBitPatternStruct { a: 0, b: CheckedBitPatternEnumNonContiguous::B }
225 );
226 }
227
228 #[test]
anybitpattern_implies_zeroable()229 fn anybitpattern_implies_zeroable() {
230 let test = AnyBitPatternTest::<isize, usize>::zeroed();
231 assert_eq!(test, AnyBitPatternTest { a: 0isize, b: 0usize });
232 }
233
234 #[test]
checkedbitpattern_try_pod_read_unaligned()235 fn checkedbitpattern_try_pod_read_unaligned() {
236 let pod = [0u8];
237 let res = bytemuck::checked::try_pod_read_unaligned::<
238 CheckedBitPatternEnumWithValues,
239 >(&pod);
240 assert!(res.is_ok());
241
242 let pod = [5u8];
243 let res = bytemuck::checked::try_pod_read_unaligned::<
244 CheckedBitPatternEnumWithValues,
245 >(&pod);
246 assert!(res.is_err());
247 }
248
249 #[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
250 #[repr(C, align(16))]
251 struct Issue127 {}
252