@@ -96,14 +96,15 @@ impl<T, A: Alloc> RawVec<T, A> {
96
96
NonNull :: < T > :: dangling ( ) . as_opaque ( )
97
97
} else {
98
98
let align = mem:: align_of :: < T > ( ) ;
99
+ let layout = Layout :: from_size_align ( alloc_size, align) . unwrap ( ) ;
99
100
let result = if zeroed {
100
- a. alloc_zeroed ( Layout :: from_size_align ( alloc_size , align ) . unwrap ( ) )
101
+ a. alloc_zeroed ( layout )
101
102
} else {
102
- a. alloc ( Layout :: from_size_align ( alloc_size , align ) . unwrap ( ) )
103
+ a. alloc ( layout )
103
104
} ;
104
105
match result {
105
106
Ok ( ptr) => ptr,
106
- Err ( _) => oom ( ) ,
107
+ Err ( _) => oom ( layout ) ,
107
108
}
108
109
} ;
109
110
@@ -318,7 +319,7 @@ impl<T, A: Alloc> RawVec<T, A> {
318
319
new_size) ;
319
320
match ptr_res {
320
321
Ok ( ptr) => ( new_cap, ptr. cast ( ) . into ( ) ) ,
321
- Err ( _) => oom ( ) ,
322
+ Err ( _) => oom ( Layout :: from_size_align_unchecked ( new_size , cur . align ( ) ) ) ,
322
323
}
323
324
}
324
325
None => {
@@ -327,7 +328,7 @@ impl<T, A: Alloc> RawVec<T, A> {
327
328
let new_cap = if elem_size > ( !0 ) / 8 { 1 } else { 4 } ;
328
329
match self . a . alloc_array :: < T > ( new_cap) {
329
330
Ok ( ptr) => ( new_cap, ptr. into ( ) ) ,
330
- Err ( _) => oom ( ) ,
331
+ Err ( _) => oom ( Layout :: array :: < T > ( new_cap ) . unwrap ( ) ) ,
331
332
}
332
333
}
333
334
} ;
@@ -389,37 +390,7 @@ impl<T, A: Alloc> RawVec<T, A> {
389
390
pub fn try_reserve_exact ( & mut self , used_cap : usize , needed_extra_cap : usize )
390
391
-> Result < ( ) , CollectionAllocErr > {
391
392
392
- unsafe {
393
- // NOTE: we don't early branch on ZSTs here because we want this
394
- // to actually catch "asking for more than usize::MAX" in that case.
395
- // If we make it past the first branch then we are guaranteed to
396
- // panic.
397
-
398
- // Don't actually need any more capacity.
399
- // Wrapping in case they gave a bad `used_cap`.
400
- if self . cap ( ) . wrapping_sub ( used_cap) >= needed_extra_cap {
401
- return Ok ( ( ) ) ;
402
- }
403
-
404
- // Nothing we can really do about these checks :(
405
- let new_cap = used_cap. checked_add ( needed_extra_cap) . ok_or ( CapacityOverflow ) ?;
406
- let new_layout = Layout :: array :: < T > ( new_cap) . map_err ( |_| CapacityOverflow ) ?;
407
-
408
- alloc_guard ( new_layout. size ( ) ) ?;
409
-
410
- let res = match self . current_layout ( ) {
411
- Some ( layout) => {
412
- debug_assert ! ( new_layout. align( ) == layout. align( ) ) ;
413
- self . a . realloc ( NonNull :: from ( self . ptr ) . as_opaque ( ) , layout, new_layout. size ( ) )
414
- }
415
- None => self . a . alloc ( new_layout) ,
416
- } ;
417
-
418
- self . ptr = res?. cast ( ) . into ( ) ;
419
- self . cap = new_cap;
420
-
421
- Ok ( ( ) )
422
- }
393
+ self . reserve_internal ( used_cap, needed_extra_cap, Fallible , Exact )
423
394
}
424
395
425
396
/// Ensures that the buffer contains at least enough space to hold
@@ -443,9 +414,9 @@ impl<T, A: Alloc> RawVec<T, A> {
443
414
///
444
415
/// Aborts on OOM
445
416
pub fn reserve_exact ( & mut self , used_cap : usize , needed_extra_cap : usize ) {
446
- match self . try_reserve_exact ( used_cap, needed_extra_cap) {
417
+ match self . reserve_internal ( used_cap, needed_extra_cap, Infallible , Exact ) {
447
418
Err ( CapacityOverflow ) => capacity_overflow ( ) ,
448
- Err ( AllocErr ) => oom ( ) ,
419
+ Err ( AllocErr ) => unreachable ! ( ) ,
449
420
Ok ( ( ) ) => { /* yay */ }
450
421
}
451
422
}
@@ -467,37 +438,7 @@ impl<T, A: Alloc> RawVec<T, A> {
467
438
/// The same as `reserve`, but returns on errors instead of panicking or aborting.
468
439
pub fn try_reserve ( & mut self , used_cap : usize , needed_extra_cap : usize )
469
440
-> Result < ( ) , CollectionAllocErr > {
470
- unsafe {
471
- // NOTE: we don't early branch on ZSTs here because we want this
472
- // to actually catch "asking for more than usize::MAX" in that case.
473
- // If we make it past the first branch then we are guaranteed to
474
- // panic.
475
-
476
- // Don't actually need any more capacity.
477
- // Wrapping in case they give a bad `used_cap`
478
- if self . cap ( ) . wrapping_sub ( used_cap) >= needed_extra_cap {
479
- return Ok ( ( ) ) ;
480
- }
481
-
482
- let new_cap = self . amortized_new_size ( used_cap, needed_extra_cap) ?;
483
- let new_layout = Layout :: array :: < T > ( new_cap) . map_err ( |_| CapacityOverflow ) ?;
484
-
485
- // FIXME: may crash and burn on over-reserve
486
- alloc_guard ( new_layout. size ( ) ) ?;
487
-
488
- let res = match self . current_layout ( ) {
489
- Some ( layout) => {
490
- debug_assert ! ( new_layout. align( ) == layout. align( ) ) ;
491
- self . a . realloc ( NonNull :: from ( self . ptr ) . as_opaque ( ) , layout, new_layout. size ( ) )
492
- }
493
- None => self . a . alloc ( new_layout) ,
494
- } ;
495
-
496
- self . ptr = res?. cast ( ) . into ( ) ;
497
- self . cap = new_cap;
498
-
499
- Ok ( ( ) )
500
- }
441
+ self . reserve_internal ( used_cap, needed_extra_cap, Fallible , Amortized )
501
442
}
502
443
503
444
/// Ensures that the buffer contains at least enough space to hold
@@ -553,12 +494,12 @@ impl<T, A: Alloc> RawVec<T, A> {
553
494
/// # }
554
495
/// ```
555
496
pub fn reserve ( & mut self , used_cap : usize , needed_extra_cap : usize ) {
556
- match self . try_reserve ( used_cap, needed_extra_cap) {
497
+ match self . reserve_internal ( used_cap, needed_extra_cap, Infallible , Amortized ) {
557
498
Err ( CapacityOverflow ) => capacity_overflow ( ) ,
558
- Err ( AllocErr ) => oom ( ) ,
499
+ Err ( AllocErr ) => unreachable ! ( ) ,
559
500
Ok ( ( ) ) => { /* yay */ }
560
- }
561
- }
501
+ }
502
+ }
562
503
/// Attempts to ensure that the buffer contains at least enough space to hold
563
504
/// `used_cap + needed_extra_cap` elements. If it doesn't already have
564
505
/// enough capacity, will reallocate in place enough space plus comfortable slack
@@ -670,14 +611,81 @@ impl<T, A: Alloc> RawVec<T, A> {
670
611
old_layout,
671
612
new_size) {
672
613
Ok ( p) => self . ptr = p. cast ( ) . into ( ) ,
673
- Err ( _) => oom ( ) ,
614
+ Err ( _) => oom ( Layout :: from_size_align_unchecked ( new_size , align ) ) ,
674
615
}
675
616
}
676
617
self . cap = amount;
677
618
}
678
619
}
679
620
}
680
621
622
+ enum Fallibility {
623
+ Fallible ,
624
+ Infallible ,
625
+ }
626
+
627
+ use self :: Fallibility :: * ;
628
+
629
+ enum ReserveStrategy {
630
+ Exact ,
631
+ Amortized ,
632
+ }
633
+
634
+ use self :: ReserveStrategy :: * ;
635
+
636
+ impl < T , A : Alloc > RawVec < T , A > {
637
+ fn reserve_internal (
638
+ & mut self ,
639
+ used_cap : usize ,
640
+ needed_extra_cap : usize ,
641
+ fallibility : Fallibility ,
642
+ strategy : ReserveStrategy ,
643
+ ) -> Result < ( ) , CollectionAllocErr > {
644
+ unsafe {
645
+ use alloc:: AllocErr ;
646
+
647
+ // NOTE: we don't early branch on ZSTs here because we want this
648
+ // to actually catch "asking for more than usize::MAX" in that case.
649
+ // If we make it past the first branch then we are guaranteed to
650
+ // panic.
651
+
652
+ // Don't actually need any more capacity.
653
+ // Wrapping in case they gave a bad `used_cap`.
654
+ if self . cap ( ) . wrapping_sub ( used_cap) >= needed_extra_cap {
655
+ return Ok ( ( ) ) ;
656
+ }
657
+
658
+ // Nothing we can really do about these checks :(
659
+ let new_cap = match strategy {
660
+ Exact => used_cap. checked_add ( needed_extra_cap) . ok_or ( CapacityOverflow ) ?,
661
+ Amortized => self . amortized_new_size ( used_cap, needed_extra_cap) ?,
662
+ } ;
663
+ let new_layout = Layout :: array :: < T > ( new_cap) . map_err ( |_| CapacityOverflow ) ?;
664
+
665
+ alloc_guard ( new_layout. size ( ) ) ?;
666
+
667
+ let res = match self . current_layout ( ) {
668
+ Some ( layout) => {
669
+ debug_assert ! ( new_layout. align( ) == layout. align( ) ) ;
670
+ self . a . realloc ( NonNull :: from ( self . ptr ) . as_opaque ( ) , layout, new_layout. size ( ) )
671
+ }
672
+ None => self . a . alloc ( new_layout) ,
673
+ } ;
674
+
675
+ match ( & res, fallibility) {
676
+ ( Err ( AllocErr ) , Infallible ) => oom ( new_layout) ,
677
+ _ => { }
678
+ }
679
+
680
+ self . ptr = res?. cast ( ) . into ( ) ;
681
+ self . cap = new_cap;
682
+
683
+ Ok ( ( ) )
684
+ }
685
+ }
686
+
687
+ }
688
+
681
689
impl < T > RawVec < T , Global > {
682
690
/// Converts the entire buffer into `Box<[T]>`.
683
691
///
0 commit comments