@@ -522,40 +522,44 @@ impl<K, V> IndexMapCore<K, V> {
522
522
}
523
523
}
524
524
525
+ /// Reserve entries capacity, rounded up to match the indices (via `try_capacity`).
526
+ fn reserve_entries < K , V > ( entries : & mut Entries < K , V > , additional : usize , try_capacity : usize ) {
527
+ // Use a soft-limit on the maximum capacity, but if the caller explicitly
528
+ // requested more, do it and let them have the resulting panic.
529
+ let try_capacity = try_capacity. min ( IndexMapCore :: < K , V > :: MAX_ENTRIES_CAPACITY ) ;
530
+ let try_add = try_capacity - entries. len ( ) ;
531
+ if try_add > additional && entries. try_reserve_exact ( try_add) . is_ok ( ) {
532
+ return ;
533
+ }
534
+ entries. reserve_exact ( additional) ;
535
+ }
536
+
525
537
impl < ' a , K , V > RefMut < ' a , K , V > {
526
538
#[ inline]
527
539
fn new ( indices : & ' a mut Indices , entries : & ' a mut Entries < K , V > ) -> Self {
528
540
Self { indices, entries }
529
541
}
530
542
531
543
/// Reserve entries capacity, rounded up to match the indices
544
+ #[ inline]
532
545
fn reserve_entries ( & mut self , additional : usize ) {
533
- // Use a soft-limit on the maximum capacity, but if the caller explicitly
534
- // requested more, do it and let them have the resulting panic.
535
- let new_capacity = Ord :: min (
536
- self . indices . capacity ( ) ,
537
- IndexMapCore :: < K , V > :: MAX_ENTRIES_CAPACITY ,
538
- ) ;
539
- let try_add = new_capacity - self . entries . len ( ) ;
540
- if try_add > additional && self . entries . try_reserve_exact ( try_add) . is_ok ( ) {
541
- return ;
542
- }
543
- self . entries . reserve_exact ( additional) ;
546
+ reserve_entries ( self . entries , additional, self . indices . capacity ( ) ) ;
544
547
}
545
548
546
549
/// Insert a key-value pair in `entries`,
547
550
/// *without* checking whether it already exists.
548
- fn insert_unique ( mut self , hash : HashValue , key : K , value : V ) -> OccupiedEntry < ' a , K , V > {
549
- if self . entries . len ( ) == self . entries . capacity ( ) {
550
- // Reserve our own capacity synced to the indices,
551
- // rather than letting `Vec::push` just double it.
552
- self . reserve_entries ( 1 ) ;
553
- }
551
+ fn insert_unique ( self , hash : HashValue , key : K , value : V ) -> OccupiedEntry < ' a , K , V > {
554
552
let i = self . indices . len ( ) ;
553
+ debug_assert_eq ! ( i, self . entries. len( ) ) ;
555
554
let entry = self
556
555
. indices
557
556
. insert_unique ( hash. get ( ) , i, get_hash ( self . entries ) ) ;
558
- debug_assert_eq ! ( i, self . entries. len( ) ) ;
557
+ if self . entries . len ( ) == self . entries . capacity ( ) {
558
+ // We can't call `indices.capacity()` while this `entry` has borrowed it, so we'll have
559
+ // to amortize growth on our own. It's still an improvement over the basic `Vec::push`
560
+ // doubling though, since we also consider `MAX_ENTRIES_CAPACITY`.
561
+ reserve_entries ( self . entries , 1 , 2 * self . entries . capacity ( ) ) ;
562
+ }
559
563
self . entries . push ( Bucket { hash, key, value } ) ;
560
564
OccupiedEntry :: new ( self . entries , entry)
561
565
}
0 commit comments