@@ -19,7 +19,7 @@ use cmp::{max, Eq, PartialEq};
19
19
use default:: Default ;
20
20
use fmt:: { self , Debug } ;
21
21
use hash:: { self , Hash , SipHasher } ;
22
- use iter:: { self , Iterator , ExactSizeIterator , IntoIterator , IteratorExt , FromIterator , Extend , Map } ;
22
+ use iter:: { Iterator , ExactSizeIterator , IntoIterator , IteratorExt , FromIterator , Extend , Map } ;
23
23
use marker:: Sized ;
24
24
use mem:: { self , replace} ;
25
25
use num:: { Int , UnsignedInt } ;
@@ -38,6 +38,8 @@ use super::table::{
38
38
RawTable ,
39
39
SafeHash ,
40
40
TableRef ,
41
+ PartialRawTable ,
42
+ Put ,
41
43
} ;
42
44
use super :: table:: BucketState :: {
43
45
Empty ,
@@ -307,7 +309,6 @@ fn test_resize_policy() {
307
309
/// }
308
310
/// ```
309
311
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
310
- #[ derive( Clone ) ]
311
312
pub struct HashMap < K , V , S = RandomState > {
312
313
// All hashes are keyed on these values, to prevent hash collision attacks.
313
314
hash_state : S ,
@@ -389,7 +390,7 @@ fn pop_internal<K, V>(starting_bucket: FullBucketMut<K, V>) -> (K, V) {
389
390
/// to recalculate it.
390
391
///
391
392
/// `hash`, `k`, and `v` are the elements to "robin hood" into the hashtable.
392
- fn robin_hood < ' a , K : ' a , V : ' a > ( mut bucket : FullBucketMut < ' a , K , V > ,
393
+ fn robin_hood < ' a , K : ' a , V : ' a > ( bucket : FullBucketMut < ' a , K , V > ,
393
394
mut ib : usize ,
394
395
mut hash : SafeHash ,
395
396
mut k : K ,
@@ -400,9 +401,10 @@ fn robin_hood<'a, K: 'a, V: 'a>(mut bucket: FullBucketMut<'a, K, V>,
400
401
let table = bucket. table ( ) ; // FIXME "lifetime too short".
401
402
table. size ( )
402
403
} ;
403
- // There can be at most `size - dib` buckets to displace, because
404
+ let mut bucket = bucket. stash ( ) ;
405
+ // There can be at most `size - displacement` buckets to displace, because
404
406
// in the worst case, there are `size` elements and we already are
405
- // `distance ` buckets away from the initial one.
407
+ // `displacement ` buckets away from the initial one.
406
408
let idx_end = starting_index + size - bucket. displacement ( ) ;
407
409
408
410
loop {
@@ -420,14 +422,7 @@ fn robin_hood<'a, K: 'a, V: 'a>(mut bucket: FullBucketMut<'a, K, V>,
420
422
let b = bucket. put ( old_hash, old_key, old_val) ;
421
423
// Now that it's stolen, just read the value's pointer
422
424
// right out of the table!
423
- let starting_bucket = Bucket :: at_index ( b. into_table ( ) , starting_index) . ok ( )
424
- . unwrap ( )
425
- . peek ( ) ;
426
- if let Full ( starting_bucket) = starting_bucket {
427
- return starting_bucket. into_mut_refs ( ) . 1 ;
428
- } else {
429
- panic ! ( "Expected full bucket" ) ;
430
- }
425
+ return b. into_table ( ) . into_mut_refs ( ) . 1 ;
431
426
} ,
432
427
Full ( bucket) => bucket
433
428
} ;
@@ -450,7 +445,7 @@ fn robin_hood<'a, K: 'a, V: 'a>(mut bucket: FullBucketMut<'a, K, V>,
450
445
451
446
// Performs insertion with relaxed requirements.
452
447
// The caller should ensure that invariants of Robin Hood linear probing hold.
453
- fn insert_hashed_ordered < M , K , V > ( arg : M , h : SafeHash , k : K , v : V ) -> M
448
+ fn insert_hashed_ordered < M : Put , K , V > ( arg : M , h : SafeHash , k : K , v : V ) -> M
454
449
where RawTable < K , V > : BorrowFromMut < M >
455
450
{
456
451
let table = TableRef ( arg) ;
@@ -720,27 +715,34 @@ impl<K, V, S, H> HashMap<K, V, S>
720
715
// ^ exit once table.size == 0
721
716
let idx_end = bucket. index ( ) + old_capacity;
722
717
723
- while bucket. index ( ) != idx_end {
724
- bucket = match bucket. peek ( ) {
725
- Full ( bucket) => {
726
- let h = * bucket. read ( ) . 0 ;
727
- let ( b, k, v) = bucket. take ( ) ;
728
-
729
- if let Some ( ref mut dest) = destination {
730
- insert_hashed_ordered ( dest, h, k, v) ;
718
+ if let Some ( mut dest) = destination {
719
+ while bucket. index ( ) != idx_end {
720
+ bucket = match bucket. peek ( ) {
721
+ Full ( bucket) => {
722
+ let h = * bucket. read ( ) . 0 ;
723
+ let ( b, k, v) = bucket. take ( ) ;
724
+ insert_hashed_ordered ( & mut dest, h, k, v) ;
731
725
b. into_bucket ( )
732
- } else {
733
- // Resizing in-place.
734
- insert_hashed_ordered ( b. into_bucket ( ) , h, k, v)
735
726
}
736
- }
737
- Empty ( b) => b. into_bucket ( )
738
- } ;
739
- bucket. next ( ) ; // wraps at old_capacity
740
- }
727
+ Empty ( b) => b. into_bucket ( )
728
+ } ;
729
+ bucket. next ( ) ; // wraps at old_capacity
730
+ }
741
731
742
- if let Some ( dest) = destination {
743
732
replace ( bucket. into_table ( ) , dest) ;
733
+ } else {
734
+ while bucket. index ( ) != idx_end {
735
+ bucket = match bucket. peek ( ) {
736
+ Full ( bucket) => {
737
+ let h = * bucket. read ( ) . 0 ;
738
+ let ( b, k, v) = bucket. take ( ) ;
739
+ // Resizing in-place.
740
+ insert_hashed_ordered ( b. into_bucket ( ) , h, k, v)
741
+ }
742
+ Empty ( b) => b. into_bucket ( )
743
+ } ;
744
+ bucket. next ( ) ; // wraps at old_capacity
745
+ }
744
746
}
745
747
}
746
748
@@ -769,11 +771,12 @@ impl<K, V, S, H> HashMap<K, V, S>
769
771
debug_assert ! ( self . len( ) <= min_capacity) ;
770
772
771
773
if self . table . capacity ( ) != min_capacity {
772
- let old_table = replace ( & mut self . table , RawTable :: new ( min_capacity) ) ;
774
+ let mut old_table = PartialRawTable :: new ( replace ( & mut self . table ,
775
+ RawTable :: new ( min_capacity) ) ) ;
773
776
let old_size = old_table. size ( ) ;
774
777
775
778
// Shrink the table. Naive algorithm for resizing:
776
- for ( h, k, v) in old_table. into_iter ( ) {
779
+ while let Some ( ( h, k, v) ) = old_table. take_front ( ) {
777
780
self . insert_hashed_nocheck ( h, k, v) ;
778
781
}
779
782
@@ -925,11 +928,8 @@ impl<K, V, S, H> HashMap<K, V, S>
925
928
/// ```
926
929
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
927
930
pub fn into_iter ( self ) -> IntoIter < K , V > {
928
- fn last_two < A , B , C > ( ( _, b, c) : ( A , B , C ) ) -> ( B , C ) { ( b, c) }
929
- let last_two: fn ( ( SafeHash , K , V ) ) -> ( K , V ) = last_two;
930
-
931
931
IntoIter {
932
- inner : self . table . into_iter ( ) . map ( last_two )
932
+ table : PartialRawTable :: new ( self . table )
933
933
}
934
934
}
935
935
@@ -1231,6 +1231,37 @@ impl<K, V, S, H, Q: ?Sized> IndexMut<Q> for HashMap<K, V, S>
1231
1231
}
1232
1232
}
1233
1233
1234
+ impl < K : Clone , V : Clone , S : Clone > Clone for HashMap < K , V , S > {
1235
+ fn clone ( & self ) -> HashMap < K , V , S > {
1236
+ let mut new_ht = RawTable :: new_uninitialized ( self . table . capacity ( ) ) ;
1237
+
1238
+ let cap = self . table . capacity ( ) ;
1239
+ if let Ok ( mut buckets) = Bucket :: at_index ( & self . table , 0 ) {
1240
+ while buckets. index ( ) != cap {
1241
+ match buckets. peek ( ) {
1242
+ Full ( full) => {
1243
+ let ( h, k, v) = {
1244
+ let ( h, k, v) = full. read ( ) ;
1245
+ ( * h, k. clone ( ) , v. clone ( ) )
1246
+ } ;
1247
+ new_ht. push_back ( Some ( ( h, k, v) ) ) ;
1248
+ }
1249
+ Empty ( ..) => {
1250
+ new_ht. push_back ( None ) ;
1251
+ }
1252
+ }
1253
+ buckets. next ( ) ;
1254
+ }
1255
+ }
1256
+
1257
+ HashMap {
1258
+ table : new_ht. unwrap ( ) ,
1259
+ hash_state : self . hash_state . clone ( ) ,
1260
+ resize_policy : self . resize_policy . clone ( ) ,
1261
+ }
1262
+ }
1263
+ }
1264
+
1234
1265
/// HashMap iterator.
1235
1266
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
1236
1267
pub struct Iter < ' a , K : ' a , V : ' a > {
@@ -1258,7 +1289,7 @@ pub struct IterMut<'a, K: 'a, V: 'a> {
1258
1289
/// HashMap move iterator.
1259
1290
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
1260
1291
pub struct IntoIter < K , V > {
1261
- inner : iter :: Map < table :: IntoIter < K , V > , fn ( ( SafeHash , K , V ) ) -> ( K , V ) >
1292
+ table : PartialRawTable < K , V > ,
1262
1293
}
1263
1294
1264
1295
/// HashMap keys iterator.
@@ -1427,17 +1458,17 @@ impl<K, V> Iterator for IntoIter<K, V> {
1427
1458
1428
1459
#[ inline]
1429
1460
fn next ( & mut self ) -> Option < ( K , V ) > {
1430
- self . inner . next ( )
1461
+ self . table . take_front ( ) . map ( | ( _ , k , v ) | ( k , v ) )
1431
1462
}
1432
1463
1433
1464
#[ inline]
1434
1465
fn size_hint ( & self ) -> ( usize , Option < usize > ) {
1435
- self . inner . size_hint ( )
1466
+ ( self . table . size ( ) , Some ( self . table . size ( ) ) )
1436
1467
}
1437
1468
}
1438
1469
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
1439
1470
impl < K , V > ExactSizeIterator for IntoIter < K , V > {
1440
- #[ inline] fn len ( & self ) -> usize { self . inner . len ( ) }
1471
+ #[ inline] fn len ( & self ) -> usize { self . table . size ( ) }
1441
1472
}
1442
1473
1443
1474
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
@@ -1469,13 +1500,19 @@ impl<'a, K, V> Iterator for Drain<'a, K, V> {
1469
1500
type Item = ( K , V ) ;
1470
1501
1471
1502
fn next ( & mut self ) -> Option < ( K , V ) > {
1472
- if let Some ( ref mut bucket) = self . inner {
1503
+ if let Some ( mut bucket) = self . inner . take ( ) {
1473
1504
let cap = bucket. table ( ) . capacity ( ) ;
1474
1505
while bucket. index ( ) < cap {
1475
- if let Some ( kv_pair) = bucket. peek_take ( ) {
1476
- return Some ( kv_pair) ;
1506
+ match bucket. peek ( ) {
1507
+ Full ( bucket) => {
1508
+ let ( empty, k, v) = bucket. take ( ) ;
1509
+ self . inner = Some ( empty. into_bucket ( ) ) ;
1510
+ return Some ( ( k, v) ) ;
1511
+ }
1512
+ Empty ( empty) => {
1513
+ bucket = empty. into_next ( ) ;
1514
+ }
1477
1515
}
1478
- bucket. next ( ) ;
1479
1516
}
1480
1517
}
1481
1518
0 commit comments