@@ -190,11 +190,7 @@ use core::{
190
190
#[ cfg( feature = "alloc" ) ]
191
191
extern crate alloc;
192
192
#[ cfg( feature = "alloc" ) ]
193
- use {
194
- alloc:: boxed:: Box ,
195
- alloc:: vec:: Vec ,
196
- core:: { alloc:: Layout , ptr:: NonNull } ,
197
- } ;
193
+ use { alloc:: boxed:: Box , alloc:: vec:: Vec , core:: alloc:: Layout } ;
198
194
199
195
// This is a hack to allow zerocopy-derive derives to work in this crate. They
200
196
// assume that zerocopy is linked as an extern crate, so they access items from
@@ -204,6 +200,127 @@ mod zerocopy {
204
200
pub ( crate ) use crate :: * ;
205
201
}
206
202
203
+ /// The layout of a type which might be dynamically-sized.
204
+ ///
205
+ /// `DstLayout` describes the layout of sized types, slice types, and "custom
206
+ /// DSTs" - ie, those that are known by the type system to have a trailing slice
207
+ /// (as distinguished from `dyn Trait` types - such types *might* have a
208
+ /// trailing slice type, but the type system isn't aware of it).
209
+ #[ doc( hidden) ]
210
+ #[ allow( missing_debug_implementations, missing_copy_implementations) ]
211
+ pub struct DstLayout {
212
+ /// For sized types, `size_of::<T>()`. For DSTs, the size of the type when
213
+ /// the trailing slice field contains 0 elements.
214
+ _fixed_prefix_size : usize ,
215
+ /// The alignment of the type.
216
+ _align : NonZeroUsize ,
217
+ /// For sized types, `None`. For DSTs, the size of the element type of the
218
+ /// trailing slice.
219
+ _trailing_slice_elem_size : Option < usize > ,
220
+ }
221
+
222
+ impl DstLayout {
223
+ /// Constructs a `DstLayout` which describes `T`.
224
+ ///
225
+ /// # Safety
226
+ ///
227
+ /// Unsafe code may assume that `DstLayout` is the correct layout for `T`.
228
+ const fn for_type < T > ( ) -> DstLayout {
229
+ DstLayout {
230
+ _fixed_prefix_size : mem:: size_of :: < T > ( ) ,
231
+ _align : match NonZeroUsize :: new ( mem:: align_of :: < T > ( ) ) {
232
+ Some ( align) => align,
233
+ None => panic ! ( "core::mem::align_of should never return 0" ) ,
234
+ } ,
235
+ _trailing_slice_elem_size : None ,
236
+ }
237
+ }
238
+
239
+ /// Constructs a `DstLayout` which describes `[T]`.
240
+ ///
241
+ /// # Safety
242
+ ///
243
+ /// Unsafe code may assume that `DstLayout` is the correct layout for `[T]`.
244
+ const fn for_slice < T > ( ) -> DstLayout {
245
+ DstLayout {
246
+ _fixed_prefix_size : 0 ,
247
+ _align : match NonZeroUsize :: new ( mem:: align_of :: < T > ( ) ) {
248
+ Some ( align) => align,
249
+ None => panic ! ( "core::mem::align_of should never return 0" ) ,
250
+ } ,
251
+ _trailing_slice_elem_size : Some ( mem:: size_of :: < T > ( ) ) ,
252
+ }
253
+ }
254
+ }
255
+
256
+ /// A trait which carries information about a type's layout that is used by the
257
+ /// internals of this crate.
258
+ ///
259
+ /// This trait is not meant for consumption by code outsie of this crate. While
260
+ /// the normal semver stability guarantees apply with respect to which types
261
+ /// implement this trait and which trait implementations are implied by this
262
+ /// trait, no semver stability guarantees are made regarding its internals; they
263
+ /// may change at any time, and code which makes use of them may break.
264
+ ///
265
+ /// # Safety
266
+ ///
267
+ /// This trait does not convey any safety guarantees to code outside this crate.
268
+ #[ doc( hidden) ] // TODO: Remove this once KnownLayout is used by other APIs
269
+ pub unsafe trait KnownLayout : sealed:: KnownLayoutSealed {
270
+ #[ doc( hidden) ]
271
+ const LAYOUT : DstLayout ;
272
+ }
273
+
274
+ impl < T : KnownLayout > sealed:: KnownLayoutSealed for [ T ] { }
275
+ // SAFETY: Delegates safety to `DstLayout::for_slice`.
276
+ unsafe impl < T : KnownLayout > KnownLayout for [ T ] {
277
+ const LAYOUT : DstLayout = DstLayout :: for_slice :: < T > ( ) ;
278
+ }
279
+
280
+ /// Implements `KnownLayout` for a sized type.
281
+ macro_rules! impl_known_layout {
282
+ ( $( const $constvar: ident : $constty: ty, $tyvar: ident $( : ?$optbound: ident) ? => $ty: ty) ,* $( , ) ?) => {
283
+ $( impl_known_layout!( @inner const $constvar: $constty, $tyvar $( : ?$optbound) ? => $ty) ; ) *
284
+ } ;
285
+ ( $( $tyvar: ident $( : ?$optbound: ident) ? => $ty: ty) ,* $( , ) ?) => {
286
+ $( impl_known_layout!( @inner , $tyvar $( : ?$optbound) ? => $ty) ; ) *
287
+ } ;
288
+ ( $( $ty: ty) ,* ) => { $( impl_known_layout!( @inner , => $ty) ; ) * } ;
289
+ ( @inner $( const $constvar: ident : $constty: ty) ? , $( $tyvar: ident $( : ?$optbound: ident) ?) ? => $ty: ty) => {
290
+ impl <$( const $constvar : $constty, ) ? $( $tyvar $( : ?$optbound) ?) ?> sealed:: KnownLayoutSealed for $ty { }
291
+ // SAFETY: Delegates safety to `DstLayout::for_type`.
292
+ unsafe impl <$( const $constvar : $constty, ) ? $( $tyvar $( : ?$optbound) ?) ?> KnownLayout for $ty {
293
+ const LAYOUT : DstLayout = DstLayout :: for_type:: <$ty>( ) ;
294
+ }
295
+ } ;
296
+ }
297
+
298
+ #[ rustfmt:: skip]
299
+ impl_known_layout ! (
300
+ ( ) ,
301
+ u8 , i8 , u16 , i16 , u32 , i32 , u64 , i64 , u128 , i128 , usize , isize , f32 , f64 ,
302
+ bool , char ,
303
+ NonZeroU8 , NonZeroI8 , NonZeroU16 , NonZeroI16 , NonZeroU32 , NonZeroI32 ,
304
+ NonZeroU64 , NonZeroI64 , NonZeroU128 , NonZeroI128 , NonZeroUsize , NonZeroIsize
305
+ ) ;
306
+ #[ rustfmt:: skip]
307
+ impl_known_layout ! (
308
+ T => Option <T >,
309
+ T : ?Sized => PhantomData <T >,
310
+ T => Wrapping <T >,
311
+ T => MaybeUninit <T >,
312
+ ) ;
313
+ impl_known_layout ! ( const N : usize , T => [ T ; N ] ) ;
314
+
315
+ safety_comment ! {
316
+ /// SAFETY:
317
+ /// `str` and `ManuallyDrop<[T]>` have the same representations as `[u8]`
318
+ /// and `[T]` repsectively. `str` has different bit validity than `[u8]`,
319
+ /// but that doesn't affect the soundness of this impl.
320
+ unsafe_impl_known_layout!( #[ repr( [ u8 ] ) ] str ) ;
321
+ unsafe_impl_known_layout!( T : ?Sized + KnownLayout => #[ repr( T ) ] ManuallyDrop <T >) ;
322
+ }
323
+
207
324
/// Types for which a sequence of bytes all set to zero represents a valid
208
325
/// instance of the type.
209
326
///
@@ -1171,6 +1288,7 @@ mod simd {
1171
1288
use core:: arch:: $arch:: { $( $typ) ,* } ;
1172
1289
1173
1290
use crate :: * ;
1291
+ impl_known_layout!( $( $typ) ,* ) ;
1174
1292
safety_comment! {
1175
1293
/// SAFETY:
1176
1294
/// See comment on module definition for justification.
@@ -2279,7 +2397,8 @@ where
2279
2397
}
2280
2398
2281
2399
mod sealed {
2282
- pub trait Sealed { }
2400
+ pub trait ByteSliceSealed { }
2401
+ pub trait KnownLayoutSealed { }
2283
2402
}
2284
2403
2285
2404
// ByteSlice and ByteSliceMut abstract over [u8] references (&[u8], &mut [u8],
@@ -2305,7 +2424,9 @@ mod sealed {
2305
2424
///
2306
2425
/// [`Vec<u8>`]: alloc::vec::Vec
2307
2426
/// [`split_at`]: crate::ByteSlice::split_at
2308
- pub unsafe trait ByteSlice : Deref < Target = [ u8 ] > + Sized + self :: sealed:: Sealed {
2427
+ pub unsafe trait ByteSlice :
2428
+ Deref < Target = [ u8 ] > + Sized + self :: sealed:: ByteSliceSealed
2429
+ {
2309
2430
/// Gets a raw pointer to the first byte in the slice.
2310
2431
#[ inline]
2311
2432
fn as_ptr ( & self ) -> * const u8 {
@@ -2336,7 +2457,7 @@ pub unsafe trait ByteSliceMut: ByteSlice + DerefMut {
2336
2457
}
2337
2458
}
2338
2459
2339
- impl < ' a > sealed:: Sealed for & ' a [ u8 ] { }
2460
+ impl < ' a > sealed:: ByteSliceSealed for & ' a [ u8 ] { }
2340
2461
// TODO(#61): Add a "SAFETY" comment and remove this `allow`.
2341
2462
#[ allow( clippy:: undocumented_unsafe_blocks) ]
2342
2463
unsafe impl < ' a > ByteSlice for & ' a [ u8 ] {
@@ -2346,7 +2467,7 @@ unsafe impl<'a> ByteSlice for &'a [u8] {
2346
2467
}
2347
2468
}
2348
2469
2349
- impl < ' a > sealed:: Sealed for & ' a mut [ u8 ] { }
2470
+ impl < ' a > sealed:: ByteSliceSealed for & ' a mut [ u8 ] { }
2350
2471
// TODO(#61): Add a "SAFETY" comment and remove this `allow`.
2351
2472
#[ allow( clippy:: undocumented_unsafe_blocks) ]
2352
2473
unsafe impl < ' a > ByteSlice for & ' a mut [ u8 ] {
@@ -2356,7 +2477,7 @@ unsafe impl<'a> ByteSlice for &'a mut [u8] {
2356
2477
}
2357
2478
}
2358
2479
2359
- impl < ' a > sealed:: Sealed for cell:: Ref < ' a , [ u8 ] > { }
2480
+ impl < ' a > sealed:: ByteSliceSealed for cell:: Ref < ' a , [ u8 ] > { }
2360
2481
// TODO(#61): Add a "SAFETY" comment and remove this `allow`.
2361
2482
#[ allow( clippy:: undocumented_unsafe_blocks) ]
2362
2483
unsafe impl < ' a > ByteSlice for cell:: Ref < ' a , [ u8 ] > {
@@ -2366,7 +2487,7 @@ unsafe impl<'a> ByteSlice for cell::Ref<'a, [u8]> {
2366
2487
}
2367
2488
}
2368
2489
2369
- impl < ' a > sealed:: Sealed for RefMut < ' a , [ u8 ] > { }
2490
+ impl < ' a > sealed:: ByteSliceSealed for RefMut < ' a , [ u8 ] > { }
2370
2491
// TODO(#61): Add a "SAFETY" comment and remove this `allow`.
2371
2492
#[ allow( clippy:: undocumented_unsafe_blocks) ]
2372
2493
unsafe impl < ' a > ByteSlice for RefMut < ' a , [ u8 ] > {
0 commit comments