3
3
extern crate alloc;
4
4
5
5
use core:: {
6
- cmp,
7
6
fmt:: Debug ,
8
- marker:: PhantomData ,
9
7
mem:: { self , ManuallyDrop } ,
10
8
ops:: { Deref , DerefMut , Index , IndexMut } ,
11
9
ptr,
@@ -24,6 +22,12 @@ struct HeaderVecHeader<H> {
24
22
len : usize ,
25
23
}
26
24
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
+
27
31
/// A vector with a header of your choosing behind a thin pointer
28
32
///
29
33
/// # Example
@@ -47,8 +51,7 @@ struct HeaderVecHeader<H> {
47
51
/// All of the data, like our header `OurHeaderType { a: 2 }`, the length of the vector: `2`,
48
52
/// and the contents of the vector `['x', 'z']` resides on the other side of the pointer.
49
53
pub struct HeaderVec < H , T > {
50
- ptr : * mut T ,
51
- _phantom : PhantomData < H > ,
54
+ ptr : * mut AlignedHeader < H , T > ,
52
55
}
53
56
54
57
impl < H , T > HeaderVec < H , T > {
@@ -58,20 +61,17 @@ impl<H, T> HeaderVec<H, T> {
58
61
59
62
pub fn with_capacity ( capacity : usize , head : H ) -> Self {
60
63
assert ! ( capacity > 0 , "HeaderVec capacity cannot be 0" ) ;
61
- // Allocate the initial memory, which is unititialized .
64
+ // Allocate the initial memory, which is uninitialized .
62
65
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 > ;
64
67
65
68
// Handle out-of-memory.
66
69
if ptr. is_null ( ) {
67
70
alloc:: alloc:: handle_alloc_error ( layout) ;
68
71
}
69
72
70
73
// Create self.
71
- let mut this = Self {
72
- ptr,
73
- _phantom : PhantomData ,
74
- } ;
74
+ let mut this = Self { ptr } ;
75
75
76
76
// Set the header.
77
77
let header = this. header_mut ( ) ;
@@ -204,10 +204,7 @@ impl<H, T> HeaderVec<H, T> {
204
204
#[ inline( always) ]
205
205
pub unsafe fn weak ( & self ) -> HeaderVecWeak < H , T > {
206
206
HeaderVecWeak {
207
- header_vec : ManuallyDrop :: new ( Self {
208
- ptr : self . ptr ,
209
- _phantom : PhantomData ,
210
- } ) ,
207
+ header_vec : ManuallyDrop :: new ( Self { ptr : self . ptr } ) ,
211
208
}
212
209
}
213
210
@@ -305,7 +302,7 @@ impl<H, T> HeaderVec<H, T> {
305
302
self . ptr as * mut u8 ,
306
303
Self :: layout ( old_capacity) ,
307
304
Self :: elems_to_mem_bytes ( new_capacity) ,
308
- ) as * mut T
305
+ ) as * mut AlignedHeader < H , T >
309
306
} ;
310
307
// Handle out-of-memory.
311
308
if ptr. is_null ( ) {
@@ -377,10 +374,10 @@ impl<H, T> HeaderVec<H, T> {
377
374
378
375
/// Gives the offset in units of T (as if the pointer started at an array of T) that the slice actually starts at.
379
376
#[ inline( always) ]
380
- fn offset ( ) -> usize {
377
+ const fn offset ( ) -> usize {
381
378
// The first location, in units of size_of::<T>(), that is after the header
382
379
// 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 > ( )
384
381
}
385
382
386
383
/// 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> {
400
397
fn layout ( capacity : usize ) -> alloc:: alloc:: Layout {
401
398
alloc:: alloc:: Layout :: from_size_align (
402
399
Self :: elems_to_mem_bytes ( capacity) ,
403
- cmp :: max ( mem:: align_of :: < H > ( ) , mem :: align_of :: < T > ( ) ) ,
400
+ mem:: align_of :: < AlignedHeader < H , T > > ( )
404
401
)
405
402
. expect ( "unable to produce memory layout with Hrc key type (is it a zero sized type? they are not permitted)" )
406
403
}
407
404
408
405
/// Gets the pointer to the start of the slice.
409
406
#[ inline( always) ]
410
407
fn start_ptr ( & self ) -> * const T {
411
- unsafe { self . ptr . add ( Self :: offset ( ) ) }
408
+ unsafe { ( self . ptr as * const T ) . add ( Self :: offset ( ) ) }
412
409
}
413
410
414
411
/// Gets the pointer to the start of the slice.
415
412
#[ inline( always) ]
416
413
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 ( ) ) }
418
415
}
419
416
420
417
#[ inline( always) ]
@@ -473,7 +470,7 @@ impl<H, T> HeaderVec<H, T> {
473
470
/// uninitialized memory behind the last element.
474
471
#[ inline( always) ]
475
472
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 }
477
474
}
478
475
479
476
/// Atomically adds an item to the end of the list without reallocation.
0 commit comments