33extern crate alloc;
44
55use core:: {
6- cmp,
76 fmt:: Debug ,
8- marker:: PhantomData ,
97 mem:: { self , ManuallyDrop } ,
108 ops:: { Deref , DerefMut , Index , IndexMut } ,
119 ptr,
@@ -24,6 +22,12 @@ struct HeaderVecHeader<H> {
2422 len : usize ,
2523}
2624
25+ // This union will be properly aligned and sized to store headers followed by T's.
26+ union AlignedHeader < H , T > {
27+ _header : ManuallyDrop < HeaderVecHeader < H > > ,
28+ _data : ManuallyDrop < [ T ; 0 ] > ,
29+ }
30+
2731/// A vector with a header of your choosing behind a thin pointer
2832///
2933/// # Example
@@ -47,8 +51,7 @@ struct HeaderVecHeader<H> {
4751/// All of the data, like our header `OurHeaderType { a: 2 }`, the length of the vector: `2`,
4852/// and the contents of the vector `['x', 'z']` resides on the other side of the pointer.
4953pub struct HeaderVec < H , T > {
50- ptr : * mut T ,
51- _phantom : PhantomData < H > ,
54+ ptr : * mut AlignedHeader < H , T > ,
5255}
5356
5457impl < H , T > HeaderVec < H , T > {
@@ -58,20 +61,17 @@ impl<H, T> HeaderVec<H, T> {
5861
5962 pub fn with_capacity ( capacity : usize , head : H ) -> Self {
6063 assert ! ( capacity > 0 , "HeaderVec capacity cannot be 0" ) ;
61- // Allocate the initial memory, which is unititialized .
64+ // Allocate the initial memory, which is uninitialized .
6265 let layout = Self :: layout ( capacity) ;
63- let ptr = unsafe { alloc:: alloc:: alloc ( layout) } as * mut T ;
66+ let ptr = unsafe { alloc:: alloc:: alloc ( layout) } as * mut AlignedHeader < H , T > ;
6467
6568 // Handle out-of-memory.
6669 if ptr. is_null ( ) {
6770 alloc:: alloc:: handle_alloc_error ( layout) ;
6871 }
6972
7073 // Create self.
71- let mut this = Self {
72- ptr,
73- _phantom : PhantomData ,
74- } ;
74+ let mut this = Self { ptr } ;
7575
7676 // Set the header.
7777 let header = this. header_mut ( ) ;
@@ -204,10 +204,7 @@ impl<H, T> HeaderVec<H, T> {
204204 #[ inline( always) ]
205205 pub unsafe fn weak ( & self ) -> HeaderVecWeak < H , T > {
206206 HeaderVecWeak {
207- header_vec : ManuallyDrop :: new ( Self {
208- ptr : self . ptr ,
209- _phantom : PhantomData ,
210- } ) ,
207+ header_vec : ManuallyDrop :: new ( Self { ptr : self . ptr } ) ,
211208 }
212209 }
213210
@@ -305,7 +302,7 @@ impl<H, T> HeaderVec<H, T> {
305302 self . ptr as * mut u8 ,
306303 Self :: layout ( old_capacity) ,
307304 Self :: elems_to_mem_bytes ( new_capacity) ,
308- ) as * mut T
305+ ) as * mut AlignedHeader < H , T >
309306 } ;
310307 // Handle out-of-memory.
311308 if ptr. is_null ( ) {
@@ -377,10 +374,10 @@ impl<H, T> HeaderVec<H, T> {
377374
378375 /// Gives the offset in units of T (as if the pointer started at an array of T) that the slice actually starts at.
379376 #[ inline( always) ]
380- fn offset ( ) -> usize {
377+ const fn offset ( ) -> usize {
381378 // The first location, in units of size_of::<T>(), that is after the header
382379 // It's the end of the header, rounded up to the nearest size_of::<T>()
383- ( mem:: size_of :: < HeaderVecHeader < H > > ( ) + mem :: size_of :: < T > ( ) - 1 ) / mem:: size_of :: < T > ( )
380+ mem:: size_of :: < AlignedHeader < H , T > > ( ) / mem:: size_of :: < T > ( )
384381 }
385382
386383 /// Compute the number of elements (in units of T) to allocate for a given capacity.
@@ -400,21 +397,21 @@ impl<H, T> HeaderVec<H, T> {
400397 fn layout ( capacity : usize ) -> alloc:: alloc:: Layout {
401398 alloc:: alloc:: Layout :: from_size_align (
402399 Self :: elems_to_mem_bytes ( capacity) ,
403- cmp :: max ( mem:: align_of :: < H > ( ) , mem :: align_of :: < T > ( ) ) ,
400+ mem:: align_of :: < AlignedHeader < H , T > > ( )
404401 )
405402 . expect ( "unable to produce memory layout with Hrc key type (is it a zero sized type? they are not permitted)" )
406403 }
407404
408405 /// Gets the pointer to the start of the slice.
409406 #[ inline( always) ]
410407 fn start_ptr ( & self ) -> * const T {
411- unsafe { self . ptr . add ( Self :: offset ( ) ) }
408+ unsafe { ( self . ptr as * const T ) . add ( Self :: offset ( ) ) }
412409 }
413410
414411 /// Gets the pointer to the start of the slice.
415412 #[ inline( always) ]
416413 fn start_ptr_mut ( & mut self ) -> * mut T {
417- unsafe { self . ptr . add ( Self :: offset ( ) ) }
414+ unsafe { ( self . ptr as * mut T ) . add ( Self :: offset ( ) ) }
418415 }
419416
420417 #[ inline( always) ]
@@ -473,7 +470,7 @@ impl<H, T> HeaderVec<H, T> {
473470 /// uninitialized memory behind the last element.
474471 #[ inline( always) ]
475472 fn end_ptr_atomic_mut ( & self ) -> * mut T {
476- unsafe { self . ptr . add ( Self :: offset ( ) ) . add ( self . len_atomic_acquire ( ) ) }
473+ unsafe { self . start_ptr ( ) . add ( self . len_atomic_acquire ( ) ) as * mut T }
477474 }
478475
479476 /// Atomically adds an item to the end of the list without reallocation.
0 commit comments