@@ -33,11 +33,33 @@ enum AllocInit {
33
33
Zeroed ,
34
34
}
35
35
36
+ pub trait CapacityHolder : Copy {
37
+ fn as_usize < T > ( self ) -> usize {
38
+ if T :: IS_ZST {
39
+ usize:: MAX
40
+ } else {
41
+ Self :: as_usize_raw ( self )
42
+ }
43
+ }
44
+ fn as_usize_raw ( c : Self ) -> usize ;
45
+ }
46
+
47
+ #[ derive( Copy , Clone ) ]
48
+ pub struct FixedCapacity < const N : usize > ;
49
+ impl < const N : usize > CapacityHolder for FixedCapacity < N > {
50
+ fn as_usize_raw ( _: Self ) -> usize { N }
51
+ }
52
+
36
53
#[ repr( transparent) ]
54
+ #[ derive( Copy , Clone ) ]
37
55
#[ cfg_attr( target_pointer_width = "16" , rustc_layout_scalar_valid_range_end( 0x7fff ) ) ]
38
56
#[ cfg_attr( target_pointer_width = "32" , rustc_layout_scalar_valid_range_end( 0x7fff_ffff ) ) ]
39
57
#[ cfg_attr( target_pointer_width = "64" , rustc_layout_scalar_valid_range_end( 0x7fff_ffff_ffff_ffff ) ) ]
40
- struct Cap ( usize ) ;
58
+ pub ( crate ) struct Cap ( usize ) ;
59
+
60
+ impl CapacityHolder for Cap {
61
+ fn as_usize_raw ( c : Self ) -> usize { c. 0 }
62
+ }
41
63
42
64
impl Cap {
43
65
const ZERO : Cap = unsafe { Cap ( 0 ) } ;
@@ -66,14 +88,9 @@ impl Cap {
66
88
/// `usize::MAX`. This means that you need to be careful when round-tripping this type with a
67
89
/// `Box<[T]>`, since `capacity()` won't yield the length.
68
90
#[ allow( missing_debug_implementations) ]
69
- pub ( crate ) struct RawVec < T , A : Allocator = Global > {
91
+ pub ( crate ) struct RawVec < T , A : Allocator = Global , C : CapacityHolder = Cap > {
70
92
ptr : Unique < T > ,
71
- /// Never used for ZSTs; it's `capacity()`'s responsibility to return usize::MAX in that case.
72
- ///
73
- /// # Safety
74
- ///
75
- /// `cap` must be in the `0..=isize::MAX` range.
76
- cap : Cap ,
93
+ cap : C ,
77
94
alloc : A ,
78
95
}
79
96
@@ -129,6 +146,27 @@ impl<T> RawVec<T, Global> {
129
146
}
130
147
}
131
148
149
+ impl < T , A : Allocator , C : CapacityHolder > RawVec < T , A , C > {
150
+ fn current_memory ( & self ) -> Option < ( NonNull < u8 > , Layout ) > {
151
+ let cap = self . cap . as_usize :: < T > ( ) ;
152
+ if T :: IS_ZST || cap == 0 {
153
+ None
154
+ } else {
155
+ // We could use Layout::array here which ensures the absence of isize and usize overflows
156
+ // and could hypothetically handle differences between stride and size, but this memory
157
+ // has already been allocated so we know it can't overflow and currently Rust does not
158
+ // support such types. So we can do better by skipping some checks and avoid an unwrap.
159
+ const { assert ! ( mem:: size_of:: <T >( ) % mem:: align_of:: <T >( ) == 0 ) } ;
160
+ unsafe {
161
+ let align = mem:: align_of :: < T > ( ) ;
162
+ let size = mem:: size_of :: < T > ( ) . unchecked_mul ( cap) ;
163
+ let layout = Layout :: from_size_align_unchecked ( size, align) ;
164
+ Some ( ( self . ptr . cast ( ) . into ( ) , layout) )
165
+ }
166
+ }
167
+ }
168
+ }
169
+
132
170
impl < T , A : Allocator > RawVec < T , A > {
133
171
// Tiny Vecs are dumb. Skip to:
134
172
// - 8 if the element size is 1, because any heap allocators is likely
@@ -296,24 +334,6 @@ impl<T, A: Allocator> RawVec<T, A> {
296
334
& self . alloc
297
335
}
298
336
299
- fn current_memory ( & self ) -> Option < ( NonNull < u8 > , Layout ) > {
300
- if T :: IS_ZST || self . cap . 0 == 0 {
301
- None
302
- } else {
303
- // We could use Layout::array here which ensures the absence of isize and usize overflows
304
- // and could hypothetically handle differences between stride and size, but this memory
305
- // has already been allocated so we know it can't overflow and currently Rust does not
306
- // support such types. So we can do better by skipping some checks and avoid an unwrap.
307
- const { assert ! ( mem:: size_of:: <T >( ) % mem:: align_of:: <T >( ) == 0 ) } ;
308
- unsafe {
309
- let align = mem:: align_of :: < T > ( ) ;
310
- let size = mem:: size_of :: < T > ( ) . unchecked_mul ( self . cap . 0 ) ;
311
- let layout = Layout :: from_size_align_unchecked ( size, align) ;
312
- Some ( ( self . ptr . cast ( ) . into ( ) , layout) )
313
- }
314
- }
315
- }
316
-
317
337
/// Ensures that the buffer contains at least enough space to hold `len +
318
338
/// additional` elements. If it doesn't already have enough capacity, will
319
339
/// reallocate enough space plus comfortable slack space to get amortized
@@ -576,7 +596,7 @@ where
576
596
memory. map_err ( |_| AllocError { layout : new_layout, non_exhaustive : ( ) } . into ( ) )
577
597
}
578
598
579
- unsafe impl < #[ may_dangle] T , A : Allocator > Drop for RawVec < T , A > {
599
+ unsafe impl < #[ may_dangle] T , A : Allocator , C : CapacityHolder > Drop for RawVec < T , A , C > {
580
600
/// Frees the memory owned by the `RawVec` *without* trying to drop its contents.
581
601
fn drop ( & mut self ) {
582
602
if let Some ( ( ptr, layout) ) = self . current_memory ( ) {
0 commit comments