@@ -15,7 +15,7 @@ pub struct BlobVec {
15
15
/// Number of elements, not bytes
16
16
len : usize ,
17
17
data : NonNull < u8 > ,
18
- swap_scratch : NonNull < u8 > ,
18
+ swap : unsafe fn ( Ptr < ' _ > , Ptr < ' _ > ) ,
19
19
// None if the underlying type doesn't need to be dropped
20
20
drop : Option < unsafe fn ( OwningPtr < ' _ > ) > ,
21
21
}
@@ -28,7 +28,6 @@ impl std::fmt::Debug for BlobVec {
28
28
. field ( "capacity" , & self . capacity )
29
29
. field ( "len" , & self . len )
30
30
. field ( "data" , & self . data )
31
- . field ( "swap_scratch" , & self . swap_scratch )
32
31
. finish ( )
33
32
}
34
33
}
@@ -43,27 +42,26 @@ impl BlobVec {
43
42
/// [`needs_drop`]: core::mem::needs_drop
44
43
pub unsafe fn new (
45
44
item_layout : Layout ,
45
+ swap : unsafe fn ( Ptr < ' _ > , Ptr < ' _ > ) ,
46
46
drop : Option < unsafe fn ( OwningPtr < ' _ > ) > ,
47
47
capacity : usize ,
48
48
) -> BlobVec {
49
49
if item_layout. size ( ) == 0 {
50
50
BlobVec {
51
- swap_scratch : NonNull :: dangling ( ) ,
52
51
data : NonNull :: dangling ( ) ,
53
52
capacity : usize:: MAX ,
54
53
len : 0 ,
55
54
item_layout,
55
+ swap,
56
56
drop,
57
57
}
58
58
} else {
59
- let swap_scratch = NonNull :: new ( std:: alloc:: alloc ( item_layout) )
60
- . unwrap_or_else ( || std:: alloc:: handle_alloc_error ( item_layout) ) ;
61
59
let mut blob_vec = BlobVec {
62
- swap_scratch,
63
60
data : NonNull :: dangling ( ) ,
64
61
capacity : 0 ,
65
62
len : 0 ,
66
63
item_layout,
64
+ swap,
67
65
drop,
68
66
} ;
69
67
blob_vec. reserve_exact ( capacity) ;
@@ -180,28 +178,17 @@ impl BlobVec {
180
178
/// caller's responsibility to drop the returned pointer, if that is desirable.
181
179
///
182
180
/// # Safety
183
- /// It is the caller's responsibility to ensure that `index` is < `self.len()`
181
+ /// It is the caller's responsibility to ensure that `index` is less than `self.len()`.
184
182
#[ inline]
185
183
#[ must_use = "The returned pointer should be used to dropped the removed element" ]
186
184
pub unsafe fn swap_remove_and_forget_unchecked ( & mut self , index : usize ) -> OwningPtr < ' _ > {
187
- // FIXME: This should probably just use `core::ptr::swap` and return an `OwningPtr`
188
- // into the underlying `BlobVec` allocation, and remove swap_scratch
189
-
190
185
debug_assert ! ( index < self . len( ) ) ;
191
- let last = self . len - 1 ;
192
- let swap_scratch = self . swap_scratch . as_ptr ( ) ;
193
- std:: ptr:: copy_nonoverlapping :: < u8 > (
194
- self . get_unchecked_mut ( index) . as_ptr ( ) ,
195
- swap_scratch,
196
- self . item_layout . size ( ) ,
197
- ) ;
198
- std:: ptr:: copy :: < u8 > (
199
- self . get_unchecked_mut ( last) . as_ptr ( ) ,
200
- self . get_unchecked_mut ( index) . as_ptr ( ) ,
201
- self . item_layout . size ( ) ,
202
- ) ;
203
- self . len -= 1 ;
204
- OwningPtr :: new ( self . swap_scratch )
186
+ let new_len = self . len - 1 ;
187
+ let size = self . item_layout . size ( ) ;
188
+ ( self . swap ) ( self . get_unchecked ( new_len) , self . get_unchecked ( index) ) ;
189
+ self . len = new_len;
190
+ // Cannot use get_unchecked here as this is technically out of bounds after changing len.
191
+ self . get_ptr_mut ( ) . byte_add ( new_len * size) . promote ( )
205
192
}
206
193
207
194
/// # Safety
@@ -283,7 +270,6 @@ impl Drop for BlobVec {
283
270
if array_layout. size ( ) > 0 {
284
271
unsafe {
285
272
std:: alloc:: dealloc ( self . get_ptr_mut ( ) . as_ptr ( ) , array_layout) ;
286
- std:: alloc:: dealloc ( self . swap_scratch . as_ptr ( ) , self . item_layout ) ;
287
273
}
288
274
}
289
275
}
@@ -345,7 +331,7 @@ const fn padding_needed_for(layout: &Layout, align: usize) -> usize {
345
331
346
332
#[ cfg( test) ]
347
333
mod tests {
348
- use crate :: ptr:: OwningPtr ;
334
+ use crate :: ptr:: { OwningPtr , Ptr } ;
349
335
350
336
use super :: BlobVec ;
351
337
use std:: { alloc:: Layout , cell:: RefCell , rc:: Rc } ;
@@ -355,6 +341,11 @@ mod tests {
355
341
x. drop_as :: < T > ( )
356
342
}
357
343
344
+ // SAFETY: The pointer points to a valid value of type `T` and it is safe to drop this value.
345
+ unsafe fn swap_ptr < T > ( a : Ptr < ' _ > , b : Ptr < ' _ > ) {
346
+ core:: ptr:: swap ( a. as_ptr ( ) . cast :: < T > ( ) , b. as_ptr ( ) . cast :: < T > ( ) ) ;
347
+ }
348
+
358
349
/// # Safety
359
350
///
360
351
/// `blob_vec` must have a layout that matches `Layout::new::<T>()`
@@ -386,7 +377,7 @@ mod tests {
386
377
fn resize_test ( ) {
387
378
let item_layout = Layout :: new :: < usize > ( ) ;
388
379
// usize doesn't need dropping
389
- let mut blob_vec = unsafe { BlobVec :: new ( item_layout, None , 64 ) } ;
380
+ let mut blob_vec = unsafe { BlobVec :: new ( item_layout, swap_ptr :: < usize > , None , 64 ) } ;
390
381
unsafe {
391
382
for i in 0 ..1_000 {
392
383
push ( & mut blob_vec, i as usize ) ;
@@ -416,7 +407,7 @@ mod tests {
416
407
{
417
408
let item_layout = Layout :: new :: < Foo > ( ) ;
418
409
let drop = drop_ptr :: < Foo > ;
419
- let mut blob_vec = unsafe { BlobVec :: new ( item_layout, Some ( drop) , 2 ) } ;
410
+ let mut blob_vec = unsafe { BlobVec :: new ( item_layout, swap_ptr :: < Foo > , Some ( drop) , 2 ) } ;
420
411
assert_eq ! ( blob_vec. capacity( ) , 2 ) ;
421
412
unsafe {
422
413
let foo1 = Foo {
@@ -476,6 +467,6 @@ mod tests {
476
467
fn blob_vec_drop_empty_capacity ( ) {
477
468
let item_layout = Layout :: new :: < Foo > ( ) ;
478
469
let drop = drop_ptr :: < Foo > ;
479
- let _ = unsafe { BlobVec :: new ( item_layout, Some ( drop) , 0 ) } ;
470
+ let _ = unsafe { BlobVec :: new ( item_layout, swap_ptr :: < Foo > , Some ( drop) , 0 ) } ;
480
471
}
481
472
}
0 commit comments