1
- use crate :: raw:: { Bucket , RawIntoIter , RawIter , RawTable } ;
1
+ use crate :: raw:: { Bucket , RawDrain , RawIntoIter , RawIter , RawTable } ;
2
2
use crate :: TryReserveError ;
3
3
use core:: borrow:: Borrow ;
4
4
use core:: fmt:: { self , Debug } ;
@@ -189,19 +189,27 @@ pub struct HashMap<K, V, S = DefaultHashBuilder> {
189
189
pub ( crate ) table : RawTable < ( K , V ) > ,
190
190
}
191
191
192
- impl < K : Clone , V : Clone , S : Clone > Clone for HashMap < K , V , S > {
192
+ impl < K : Clone + Hash , V : Clone , S : Clone + BuildHasher > Clone for HashMap < K , V , S > {
193
193
fn clone ( & self ) -> Self {
194
+ let hash_builder = self . hash_builder . clone ( ) ;
195
+ let table = self
196
+ . table
197
+ . clone_with_hasher ( |x| make_hash ( & hash_builder, & x. 0 ) ) ;
194
198
HashMap {
195
- hash_builder : self . hash_builder . clone ( ) ,
196
- table : self . table . clone ( ) ,
199
+ hash_builder,
200
+ table,
197
201
}
198
202
}
199
203
200
204
fn clone_from ( & mut self , source : & Self ) {
201
- self . table . clone_from ( & source. table ) ;
205
+ // NOTE: Since we may re-hash leftovers on clone, we need the new hash builder straight
206
+ // away, unlike hashbrown which can get away with just cloning after. We don't want to
207
+ // change self.hash_builder yet though, in case the cloning panics.
208
+ let hash_builder = source. hash_builder . clone ( ) ;
202
209
203
- // Update hash_builder only if we successfully cloned all elements.
204
- self . hash_builder . clone_from ( & source. hash_builder ) ;
210
+ self . table
211
+ . clone_from_with_hasher ( & source. table , |x| make_hash ( & hash_builder, & x. 0 ) ) ;
212
+ self . hash_builder = hash_builder;
205
213
}
206
214
}
207
215
@@ -531,6 +539,35 @@ impl<K, V, S> HashMap<K, V, S> {
531
539
self . len ( ) == 0
532
540
}
533
541
542
+ /// Clears the map, returning all key-value pairs as an iterator. Keeps the
543
+ /// allocated memory for reuse.
544
+ ///
545
+ /// # Examples
546
+ ///
547
+ /// ```
548
+ /// use griddle::HashMap;
549
+ ///
550
+ /// let mut a = HashMap::new();
551
+ /// a.insert(1, "a");
552
+ /// a.insert(2, "b");
553
+ ///
554
+ /// for (k, v) in a.drain().take(1) {
555
+ /// assert!(k == 1 || k == 2);
556
+ /// assert!(v == "a" || v == "b");
557
+ /// }
558
+ ///
559
+ /// assert!(a.is_empty());
560
+ /// ```
561
+ #[ cfg_attr( feature = "inline-more" , inline) ]
562
+ pub fn drain ( & mut self ) -> Drain < ' _ , K , V > {
563
+ // Here we tie the lifetime of self to the iter.
564
+ unsafe {
565
+ Drain {
566
+ inner : self . table . drain ( ) ,
567
+ }
568
+ }
569
+ }
570
+
534
571
/// Retains only the elements specified by the predicate.
535
572
///
536
573
/// In other words, remove all pairs `(k, v)` such that `f(&k,&mut v)` returns `false`.
@@ -553,11 +590,7 @@ impl<K, V, S> HashMap<K, V, S> {
553
590
for item in self . table . iter ( ) {
554
591
let & mut ( ref key, ref mut value) = item. as_mut ( ) ;
555
592
if !f ( key, value) {
556
- // Erase the element from the table first since drop might panic.
557
- // But read it before the erase in case erase invalidates the memory.
558
- let v = item. read ( ) ;
559
- self . table . erase_no_drop ( & item) ;
560
- drop ( v) ;
593
+ self . table . erase ( item) ;
561
594
}
562
595
}
563
596
}
@@ -994,10 +1027,7 @@ where
994
1027
unsafe {
995
1028
let hash = make_hash ( & self . hash_builder , & k) ;
996
1029
if let Some ( item) = self . table . find ( hash, |x| k. eq ( x. 0 . borrow ( ) ) ) {
997
- // Read the item before the erase, in case erase reclaims memory.
998
- let v = item. read ( ) ;
999
- self . table . erase_no_drop ( & item) ;
1000
- Some ( v)
1030
+ Some ( self . table . remove ( item) )
1001
1031
} else {
1002
1032
None
1003
1033
}
@@ -1203,6 +1233,28 @@ impl<K, V: Debug> fmt::Debug for Values<'_, K, V> {
1203
1233
}
1204
1234
}
1205
1235
1236
+ /// A draining iterator over the entries of a `HashMap`.
1237
+ ///
1238
+ /// This `struct` is created by the [`drain`] method on [`HashMap`]. See its
1239
+ /// documentation for more.
1240
+ ///
1241
+ /// [`drain`]: struct.HashMap.html#method.drain
1242
+ /// [`HashMap`]: struct.HashMap.html
1243
+ pub struct Drain < ' a , K , V > {
1244
+ inner : RawDrain < ' a , ( K , V ) > ,
1245
+ }
1246
+
1247
+ impl < K , V > Drain < ' _ , K , V > {
1248
+ /// Returns a iterator of references over the remaining items.
1249
+ #[ cfg_attr( feature = "inline-more" , inline) ]
1250
+ pub ( super ) fn iter ( & self ) -> Iter < ' _ , K , V > {
1251
+ Iter {
1252
+ inner : self . inner . iter ( ) ,
1253
+ marker : PhantomData ,
1254
+ }
1255
+ }
1256
+ }
1257
+
1206
1258
/// A mutable iterator over the values of a `HashMap`.
1207
1259
///
1208
1260
/// This `struct` is created by the [`values_mut`] method on [`HashMap`]. See its
@@ -1489,6 +1541,36 @@ where
1489
1541
}
1490
1542
}
1491
1543
1544
+ impl < ' a , K , V > Iterator for Drain < ' a , K , V > {
1545
+ type Item = ( K , V ) ;
1546
+
1547
+ #[ cfg_attr( feature = "inline-more" , inline) ]
1548
+ fn next ( & mut self ) -> Option < ( K , V ) > {
1549
+ self . inner . next ( )
1550
+ }
1551
+ #[ cfg_attr( feature = "inline-more" , inline) ]
1552
+ fn size_hint ( & self ) -> ( usize , Option < usize > ) {
1553
+ self . inner . size_hint ( )
1554
+ }
1555
+ }
1556
+ impl < K , V > ExactSizeIterator for Drain < ' _ , K , V > {
1557
+ #[ cfg_attr( feature = "inline-more" , inline) ]
1558
+ fn len ( & self ) -> usize {
1559
+ self . inner . len ( )
1560
+ }
1561
+ }
1562
+ impl < K , V > FusedIterator for Drain < ' _ , K , V > { }
1563
+
1564
+ impl < K , V > fmt:: Debug for Drain < ' _ , K , V >
1565
+ where
1566
+ K : fmt:: Debug ,
1567
+ V : fmt:: Debug ,
1568
+ {
1569
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
1570
+ f. debug_list ( ) . entries ( self . iter ( ) ) . finish ( )
1571
+ }
1572
+ }
1573
+
1492
1574
impl < ' a , K , V , S > Entry < ' a , K , V , S > {
1493
1575
/// Sets the value of the entry, and returns an OccupiedEntry.
1494
1576
///
@@ -1719,12 +1801,7 @@ impl<'a, K, V, S> OccupiedEntry<'a, K, V, S> {
1719
1801
/// ```
1720
1802
#[ cfg_attr( feature = "inline-more" , inline) ]
1721
1803
pub fn remove_entry ( self ) -> ( K , V ) {
1722
- unsafe {
1723
- // Read the item before the erase, in case erase reclaims memory.
1724
- let v = self . elem . read ( ) ;
1725
- self . table . table . erase_no_drop ( & self . elem ) ;
1726
- v
1727
- }
1804
+ unsafe { self . table . table . remove ( self . elem ) }
1728
1805
}
1729
1806
1730
1807
/// Gets a reference to the value in the entry.
@@ -2084,6 +2161,11 @@ fn assert_covariance() {
2084
2161
fn values_val < ' a , ' new > ( v : Values < ' a , u8 , & ' static str > ) -> Values < ' a , u8 , & ' new str > {
2085
2162
v
2086
2163
}
2164
+ fn drain < ' new > (
2165
+ d : Drain < ' static , & ' static str , & ' static str > ,
2166
+ ) -> Drain < ' new , & ' new str , & ' new str > {
2167
+ d
2168
+ }
2087
2169
}
2088
2170
2089
2171
#[ cfg( test) ]
@@ -2421,6 +2503,7 @@ mod test_map {
2421
2503
#[ test]
2422
2504
fn test_empty_iter ( ) {
2423
2505
let mut m: HashMap < i32 , bool > = HashMap :: new ( ) ;
2506
+ assert_eq ! ( m. drain( ) . next( ) , None ) ;
2424
2507
assert_eq ! ( m. keys( ) . next( ) , None ) ;
2425
2508
assert_eq ! ( m. values( ) . next( ) , None ) ;
2426
2509
assert_eq ! ( m. values_mut( ) . next( ) , None ) ;
@@ -3094,4 +3177,74 @@ mod test_map {
3094
3177
}
3095
3178
}
3096
3179
}
3180
+
3181
+ #[ test]
3182
+ #[ cfg( feature = "raw" ) ]
3183
+ fn test_into_iter_refresh ( ) {
3184
+ use core:: hash:: { BuildHasher , Hash , Hasher } ;
3185
+
3186
+ #[ cfg( miri) ]
3187
+ const N : usize = 32 ;
3188
+ #[ cfg( not( miri) ) ]
3189
+ const N : usize = 128 ;
3190
+
3191
+ let mut rng = rand:: thread_rng ( ) ;
3192
+ for n in 0 ..N {
3193
+ let mut m = HashMap :: new ( ) ;
3194
+ for i in 0 ..n {
3195
+ assert ! ( m. insert( i, 2 * i) . is_none( ) ) ;
3196
+ }
3197
+ let hasher = m. hasher ( ) . clone ( ) ;
3198
+
3199
+ let mut it = unsafe { m. table . iter ( ) } ;
3200
+ assert_eq ! ( it. len( ) , n) ;
3201
+
3202
+ let mut i = 0 ;
3203
+ let mut left = n;
3204
+ let mut removed = Vec :: new ( ) ;
3205
+ loop {
3206
+ // occasionally remove some elements
3207
+ if i < n && rng. gen_bool ( 0.1 ) {
3208
+ let mut hsh = hasher. build_hasher ( ) ;
3209
+ i. hash ( & mut hsh) ;
3210
+ let hash = hsh. finish ( ) ;
3211
+
3212
+ unsafe {
3213
+ let e = m. table . find ( hash, |q| q. 0 . eq ( & i) ) ;
3214
+ if let Some ( e) = e {
3215
+ it. reflect_remove ( & e) ;
3216
+ let t = m. table . remove ( e) ;
3217
+ removed. push ( t) ;
3218
+ left -= 1 ;
3219
+ } else {
3220
+ assert ! ( removed. contains( & ( i, 2 * i) ) , "{} not in {:?}" , i, removed) ;
3221
+ let e = m
3222
+ . table
3223
+ . insert ( hash, ( i, 2 * i) , |x| super :: make_hash ( & hasher, & x. 0 ) ) ;
3224
+ it. reflect_insert ( & e) ;
3225
+ if let Some ( p) = removed. iter ( ) . position ( |e| e == & ( i, 2 * i) ) {
3226
+ removed. swap_remove ( p) ;
3227
+ }
3228
+ left += 1 ;
3229
+ }
3230
+ }
3231
+ }
3232
+
3233
+ let e = it. next ( ) ;
3234
+ if e. is_none ( ) {
3235
+ break ;
3236
+ }
3237
+ assert ! ( i < n) ;
3238
+ let t = unsafe { e. unwrap ( ) . as_ref ( ) } ;
3239
+ assert ! ( !removed. contains( t) ) ;
3240
+ let ( k, v) = t;
3241
+ assert_eq ! ( * v, 2 * k) ;
3242
+ i += 1 ;
3243
+ }
3244
+ assert ! ( i <= n) ;
3245
+
3246
+ // just for safety:
3247
+ assert_eq ! ( m. table. len( ) , left) ;
3248
+ }
3249
+ }
3097
3250
}
0 commit comments