@@ -19,7 +19,7 @@ use cmp::{max, Eq, PartialEq};
1919use default:: Default ;
2020use fmt:: { self , Debug } ;
2121use 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 } ;
2323use marker:: Sized ;
2424use mem:: { self , replace} ;
2525use num:: { Int , UnsignedInt } ;
@@ -38,6 +38,8 @@ use super::table::{
3838 RawTable ,
3939 SafeHash ,
4040 TableRef ,
41+ PartialRawTable ,
42+ Put ,
4143} ;
4244use super :: table:: BucketState :: {
4345 Empty ,
@@ -307,7 +309,6 @@ fn test_resize_policy() {
307309/// }
308310/// ```
309311#[ stable( feature = "rust1" , since = "1.0.0" ) ]
310- #[ derive( Clone ) ]
311312pub struct HashMap < K , V , S = RandomState > {
312313 // All hashes are keyed on these values, to prevent hash collision attacks.
313314 hash_state : S ,
@@ -389,7 +390,7 @@ fn pop_internal<K, V>(starting_bucket: FullBucketMut<K, V>) -> (K, V) {
389390/// to recalculate it.
390391///
391392/// `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 > ,
393394 mut ib : usize ,
394395 mut hash : SafeHash ,
395396 mut k : K ,
@@ -400,9 +401,10 @@ fn robin_hood<'a, K: 'a, V: 'a>(mut bucket: FullBucketMut<'a, K, V>,
400401 let table = bucket. table ( ) ; // FIXME "lifetime too short".
401402 table. size ( )
402403 } ;
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
404406 // 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.
406408 let idx_end = starting_index + size - bucket. displacement ( ) ;
407409
408410 loop {
@@ -420,14 +422,7 @@ fn robin_hood<'a, K: 'a, V: 'a>(mut bucket: FullBucketMut<'a, K, V>,
420422 let b = bucket. put ( old_hash, old_key, old_val) ;
421423 // Now that it's stolen, just read the value's pointer
422424 // 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 ;
431426 } ,
432427 Full ( bucket) => bucket
433428 } ;
@@ -450,7 +445,7 @@ fn robin_hood<'a, K: 'a, V: 'a>(mut bucket: FullBucketMut<'a, K, V>,
450445
451446// Performs insertion with relaxed requirements.
452447// 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
454449 where RawTable < K , V > : BorrowFromMut < M >
455450{
456451 let table = TableRef ( arg) ;
@@ -720,27 +715,34 @@ impl<K, V, S, H> HashMap<K, V, S>
720715 // ^ exit once table.size == 0
721716 let idx_end = bucket. index ( ) + old_capacity;
722717
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) ;
731725 b. into_bucket ( )
732- } else {
733- // Resizing in-place.
734- insert_hashed_ordered ( b. into_bucket ( ) , h, k, v)
735726 }
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+ }
741731
742- if let Some ( dest) = destination {
743732 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+ }
744746 }
745747 }
746748
@@ -769,11 +771,12 @@ impl<K, V, S, H> HashMap<K, V, S>
769771 debug_assert ! ( self . len( ) <= min_capacity) ;
770772
771773 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) ) ) ;
773776 let old_size = old_table. size ( ) ;
774777
775778 // 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 ( ) {
777780 self . insert_hashed_nocheck ( h, k, v) ;
778781 }
779782
@@ -925,11 +928,8 @@ impl<K, V, S, H> HashMap<K, V, S>
925928 /// ```
926929 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
927930 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-
931931 IntoIter {
932- inner : self . table . into_iter ( ) . map ( last_two )
932+ table : PartialRawTable :: new ( self . table )
933933 }
934934 }
935935
@@ -1231,6 +1231,37 @@ impl<K, V, S, H, Q: ?Sized> IndexMut<Q> for HashMap<K, V, S>
12311231 }
12321232}
12331233
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+
12341265/// HashMap iterator.
12351266#[ stable( feature = "rust1" , since = "1.0.0" ) ]
12361267pub struct Iter < ' a , K : ' a , V : ' a > {
@@ -1258,7 +1289,7 @@ pub struct IterMut<'a, K: 'a, V: 'a> {
12581289/// HashMap move iterator.
12591290#[ stable( feature = "rust1" , since = "1.0.0" ) ]
12601291pub struct IntoIter < K , V > {
1261- inner : iter :: Map < table :: IntoIter < K , V > , fn ( ( SafeHash , K , V ) ) -> ( K , V ) >
1292+ table : PartialRawTable < K , V > ,
12621293}
12631294
12641295/// HashMap keys iterator.
@@ -1427,17 +1458,17 @@ impl<K, V> Iterator for IntoIter<K, V> {
14271458
14281459 #[ inline]
14291460 fn next ( & mut self ) -> Option < ( K , V ) > {
1430- self . inner . next ( )
1461+ self . table . take_front ( ) . map ( | ( _ , k , v ) | ( k , v ) )
14311462 }
14321463
14331464 #[ inline]
14341465 fn size_hint ( & self ) -> ( usize , Option < usize > ) {
1435- self . inner . size_hint ( )
1466+ ( self . table . size ( ) , Some ( self . table . size ( ) ) )
14361467 }
14371468}
14381469#[ stable( feature = "rust1" , since = "1.0.0" ) ]
14391470impl < 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 ( ) }
14411472}
14421473
14431474#[ stable( feature = "rust1" , since = "1.0.0" ) ]
@@ -1469,13 +1500,19 @@ impl<'a, K, V> Iterator for Drain<'a, K, V> {
14691500 type Item = ( K , V ) ;
14701501
14711502 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 ( ) {
14731504 let cap = bucket. table ( ) . capacity ( ) ;
14741505 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+ }
14771515 }
1478- bucket. next ( ) ;
14791516 }
14801517 }
14811518
0 commit comments