@@ -12,9 +12,9 @@ mod raw;
1212use hashbrown:: raw:: RawTable ;
1313
1414use crate :: vec:: { Drain , Vec } ;
15- use core :: cmp ;
15+ use crate :: TryReserveError ;
1616use core:: fmt;
17- use core:: mem:: replace ;
17+ use core:: mem;
1818use core:: ops:: RangeBounds ;
1919
2020use crate :: equivalent:: Equivalent ;
@@ -62,18 +62,18 @@ where
6262 V : Clone ,
6363{
6464 fn clone ( & self ) -> Self {
65- let indices = self . indices . clone ( ) ;
66- let mut entries = Vec :: with_capacity ( indices. capacity ( ) ) ;
67- entries. clone_from ( & self . entries ) ;
68- IndexMapCore { indices, entries }
65+ let mut new = Self :: new ( ) ;
66+ new. clone_from ( self ) ;
67+ new
6968 }
7069
7170 fn clone_from ( & mut self , other : & Self ) {
7271 let hasher = get_hash ( & other. entries ) ;
7372 self . indices . clone_from_with_hasher ( & other. indices , hasher) ;
7473 if self . entries . capacity ( ) < other. entries . len ( ) {
75- // If we must resize, match the indices capacity
76- self . reserve_entries ( ) ;
74+ // If we must resize, match the indices capacity.
75+ let additional = other. entries . len ( ) - self . entries . len ( ) ;
76+ self . reserve_entries ( additional) ;
7777 }
7878 self . entries . clone_from ( & other. entries ) ;
7979 }
@@ -120,6 +120,9 @@ impl<K, V> Entries for IndexMapCore<K, V> {
120120}
121121
122122impl < K , V > IndexMapCore < K , V > {
123+ /// The maximum capacity before the `entries` allocation would exceed `isize::MAX`.
124+ const MAX_ENTRIES_CAPACITY : usize = ( isize:: MAX as usize ) / mem:: size_of :: < Bucket < K , V > > ( ) ;
125+
123126 #[ inline]
124127 pub ( crate ) const fn new ( ) -> Self {
125128 IndexMapCore {
@@ -143,7 +146,7 @@ impl<K, V> IndexMapCore<K, V> {
143146
144147 #[ inline]
145148 pub ( crate ) fn capacity ( & self ) -> usize {
146- cmp :: min ( self . indices . capacity ( ) , self . entries . capacity ( ) )
149+ Ord :: min ( self . indices . capacity ( ) , self . entries . capacity ( ) )
147150 }
148151
149152 pub ( crate ) fn clear ( & mut self ) {
@@ -193,15 +196,67 @@ impl<K, V> IndexMapCore<K, V> {
193196 /// Reserve capacity for `additional` more key-value pairs.
194197 pub ( crate ) fn reserve ( & mut self , additional : usize ) {
195198 self . indices . reserve ( additional, get_hash ( & self . entries ) ) ;
196- self . reserve_entries ( ) ;
199+ // Only grow entries if necessary, since we also round up capacity.
200+ if additional > self . entries . capacity ( ) - self . entries . len ( ) {
201+ self . reserve_entries ( additional) ;
202+ }
203+ }
204+
205+ /// Reserve entries capacity, rounded up to match the indices
206+ fn reserve_entries ( & mut self , additional : usize ) {
207+ // Use a soft-limit on the maximum capacity, but if the caller explicitly
208+ // requested more, do it and let them have the resulting panic.
209+ let new_capacity = Ord :: min ( self . indices . capacity ( ) , Self :: MAX_ENTRIES_CAPACITY ) ;
210+ let try_add = new_capacity - self . entries . len ( ) ;
211+ if try_add > additional && self . entries . try_reserve_exact ( try_add) . is_ok ( ) {
212+ return ;
213+ }
214+ self . entries . reserve_exact ( additional) ;
197215 }
198216
199- /// Reserve entries capacity to match the indices
200- fn reserve_entries ( & mut self ) {
201- let additional = self . indices . capacity ( ) - self . entries . len ( ) ;
217+ /// Reserve capacity for `additional` more key-value pairs, without over-allocating.
218+ pub ( crate ) fn reserve_exact ( & mut self , additional : usize ) {
219+ self . indices . reserve ( additional , get_hash ( & self . entries ) ) ;
202220 self . entries . reserve_exact ( additional) ;
203221 }
204222
223+ /// Try to reserve capacity for `additional` more key-value pairs.
224+ pub ( crate ) fn try_reserve ( & mut self , additional : usize ) -> Result < ( ) , TryReserveError > {
225+ self . indices
226+ . try_reserve ( additional, get_hash ( & self . entries ) )
227+ . map_err ( TryReserveError :: from_hashbrown) ?;
228+ // Only grow entries if necessary, since we also round up capacity.
229+ if additional > self . entries . capacity ( ) - self . entries . len ( ) {
230+ self . try_reserve_entries ( additional)
231+ } else {
232+ Ok ( ( ) )
233+ }
234+ }
235+
236+ /// Try to reserve entries capacity, rounded up to match the indices
237+ fn try_reserve_entries ( & mut self , additional : usize ) -> Result < ( ) , TryReserveError > {
238+ // Use a soft-limit on the maximum capacity, but if the caller explicitly
239+ // requested more, do it and let them have the resulting error.
240+ let new_capacity = Ord :: min ( self . indices . capacity ( ) , Self :: MAX_ENTRIES_CAPACITY ) ;
241+ let try_add = new_capacity - self . entries . len ( ) ;
242+ if try_add > additional && self . entries . try_reserve_exact ( try_add) . is_ok ( ) {
243+ return Ok ( ( ) ) ;
244+ }
245+ self . entries
246+ . try_reserve_exact ( additional)
247+ . map_err ( TryReserveError :: from_alloc)
248+ }
249+
250+ /// Try to reserve capacity for `additional` more key-value pairs, without over-allocating.
251+ pub ( crate ) fn try_reserve_exact ( & mut self , additional : usize ) -> Result < ( ) , TryReserveError > {
252+ self . indices
253+ . try_reserve ( additional, get_hash ( & self . entries ) )
254+ . map_err ( TryReserveError :: from_hashbrown) ?;
255+ self . entries
256+ . try_reserve_exact ( additional)
257+ . map_err ( TryReserveError :: from_alloc)
258+ }
259+
205260 /// Shrink the capacity of the map with a lower bound
206261 pub ( crate ) fn shrink_to ( & mut self , min_capacity : usize ) {
207262 self . indices
@@ -228,7 +283,7 @@ impl<K, V> IndexMapCore<K, V> {
228283 if i == self . entries . capacity ( ) {
229284 // Reserve our own capacity synced to the indices,
230285 // rather than letting `Vec::push` just double it.
231- self . reserve_entries ( ) ;
286+ self . reserve_entries ( 1 ) ;
232287 }
233288 self . entries . push ( Bucket { hash, key, value } ) ;
234289 i
@@ -248,7 +303,7 @@ impl<K, V> IndexMapCore<K, V> {
248303 K : Eq ,
249304 {
250305 match self . get_index_of ( hash, & key) {
251- Some ( i) => ( i, Some ( replace ( & mut self . entries [ i] . value , value) ) ) ,
306+ Some ( i) => ( i, Some ( mem :: replace ( & mut self . entries [ i] . value , value) ) ) ,
252307 None => ( self . push ( hash, key, value) , None ) ,
253308 }
254309 }
@@ -601,7 +656,7 @@ pub use self::raw::OccupiedEntry;
601656impl < K , V > OccupiedEntry < ' _ , K , V > {
602657 /// Sets the value of the entry to `value`, and returns the entry's old value.
603658 pub fn insert ( & mut self , value : V ) -> V {
604- replace ( self . get_mut ( ) , value)
659+ mem :: replace ( self . get_mut ( ) , value)
605660 }
606661
607662 /// Remove the key, value pair stored in the map for this entry, and return the value.
0 commit comments