@@ -14,7 +14,7 @@ use std::{marker::PhantomData, option::IntoIter};
14
14
15
15
use {
16
16
static_assertions:: assert_impl_all,
17
- zerocopy:: { FromBytes , FromZeros , TryFromBytes } ,
17
+ zerocopy:: { FromBytes , FromZeros , KnownLayout , TryFromBytes } ,
18
18
} ;
19
19
20
20
use crate :: util:: AU16 ;
@@ -145,3 +145,74 @@ where
145
145
T : ' a + ' b + TryFromBytes ;
146
146
147
147
assert_impl_all ! ( WithParams <' static , ' static , 42 , u8 >: TryFromBytes ) ;
148
+
149
+ #[ derive( Debug , PartialEq , Eq , TryFromBytes , KnownLayout ) ]
150
+ #[ repr( C , packed) ]
151
+ struct CPacked {
152
+ a : u8 ,
153
+ // NOTE: The `u32` type is not guaranteed to have alignment 4, although it
154
+ // does on many platforms. However, to fix this would require a custom type
155
+ // with a `#[repr(align(4))]` attribute, and `#[repr(packed)]` types are not
156
+ // allowed to transitively contain `#[repr(align(...))]` types. Thus, we
157
+ // have no choice but to use `u32` here. Luckily, these tests run in CI on
158
+ // platforms on which `u32` has alignment 4, so this isn't that big of a
159
+ // deal.
160
+ b : u32 ,
161
+ }
162
+
163
+ #[ test]
164
+ fn c_packed ( ) {
165
+ let candidate = & [ 42u8 , 0xFF , 0xFF , 0xFF , 0xFF ] ;
166
+ let converted = CPacked :: try_from_ref ( candidate) ;
167
+ assert_eq ! ( converted, Some ( & CPacked { a: 42 , b: u32 :: MAX } ) ) ;
168
+ }
169
+
170
+ #[ derive( TryFromBytes , KnownLayout ) ]
171
+ #[ repr( C , packed) ]
172
+ struct CPackedUnsized {
173
+ a : u8 ,
174
+ // NOTE: The `u32` type is not guaranteed to have alignment 4, although it
175
+ // does on many platforms. However, to fix this would require a custom type
176
+ // with a `#[repr(align(4))]` attribute, and `#[repr(packed)]` types are not
177
+ // allowed to transitively contain `#[repr(align(...))]` types. Thus, we
178
+ // have no choice but to use `u32` here. Luckily, these tests run in CI on
179
+ // platforms on which `u32` has alignment 4, so this isn't that big of a
180
+ // deal.
181
+ b : [ u32 ] ,
182
+ }
183
+
184
+ #[ test]
185
+ fn c_packed_unsized ( ) {
186
+ let candidate = & [ 42u8 , 0xFF , 0xFF , 0xFF , 0xFF ] ;
187
+ let converted = CPackedUnsized :: try_from_ref ( candidate) ;
188
+ assert ! ( converted. is_some( ) ) ;
189
+ }
190
+
191
+ #[ derive( TryFromBytes ) ]
192
+ #[ repr( packed) ]
193
+ struct PackedUnsized {
194
+ a : u8 ,
195
+ // NOTE: The `u32` type is not guaranteed to have alignment 4, although it
196
+ // does on many platforms. However, to fix this would require a custom type
197
+ // with a `#[repr(align(4))]` attribute, and `#[repr(packed)]` types are not
198
+ // allowed to transitively contain `#[repr(align(...))]` types. Thus, we
199
+ // have no choice but to use `u32` here. Luckily, these tests run in CI on
200
+ // platforms on which `u32` has alignment 4, so this isn't that big of a
201
+ // deal.
202
+ b : [ u32 ] ,
203
+ }
204
+
205
+ #[ test]
206
+ fn packed_unsized ( ) {
207
+ let candidate = & [ 42u8 , 0xFF , 0xFF , 0xFF , 0xFF ] ;
208
+ let converted = CPackedUnsized :: try_from_ref ( candidate) ;
209
+ assert ! ( converted. is_some( ) ) ;
210
+
211
+ let candidate = & [ 42u8 , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF ] ;
212
+ let converted = CPackedUnsized :: try_from_ref ( candidate) ;
213
+ assert ! ( converted. is_none( ) ) ;
214
+
215
+ let candidate = & [ 42u8 , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF ] ;
216
+ let converted = CPackedUnsized :: try_from_ref ( candidate) ;
217
+ assert ! ( converted. is_some( ) ) ;
218
+ }
0 commit comments