@@ -98,7 +98,11 @@ impl Pos {
98
98
}
99
99
}
100
100
101
- struct Insert < V > {
101
+ enum Insert < K , V > {
102
+ Success ( Inserted < V > ) ,
103
+ Full ( ( K , V ) ) ,
104
+ }
105
+ struct Inserted < V > {
102
106
index : usize ,
103
107
old_value : Option < V > ,
104
108
}
@@ -175,7 +179,7 @@ where
175
179
} ) ;
176
180
}
177
181
178
- fn insert ( & mut self , hash : HashValue , key : K , value : V ) -> Insert < V > {
182
+ fn insert ( & mut self , hash : HashValue , key : K , value : V ) -> Insert < K , V > {
179
183
let mut probe = hash. desired_pos ( Self :: mask ( ) ) ;
180
184
let mut dist = 0 ;
181
185
@@ -191,32 +195,38 @@ where
191
195
let their_dist = entry_hash. probe_distance( Self :: mask( ) , probe) ;
192
196
193
197
if their_dist < dist {
198
+ if self . entries. is_full( ) {
199
+ return Insert :: Full ( ( key, value) ) ;
200
+ }
194
201
// robin hood: steal the spot if it's better for us
195
202
let index = self . entries. len( ) ;
196
203
unsafe { self . entries. push_unchecked( Bucket { hash, key, value } ) } ;
197
- return Insert {
204
+ return Insert :: Success ( Inserted {
198
205
index: self . insert_phase_2( probe, Pos :: new( index, hash) ) ,
199
206
old_value: None
200
- }
207
+ } ) ;
201
208
} else if entry_hash == hash && unsafe { self . entries. get_unchecked( i) . key == key }
202
209
{
203
- return Insert {
210
+ return Insert :: Success ( Inserted {
204
211
index: i,
205
212
old_value: Some ( mem:: replace(
206
213
unsafe { & mut self . entries. get_unchecked_mut( i) . value } ,
207
214
value,
208
215
) ) ,
209
- } ;
216
+ } ) ;
210
217
}
211
218
} else {
219
+ if self . entries. is_full( ) {
220
+ return Insert :: Full ( ( key, value) )
221
+ }
212
222
// empty bucket, insert here
213
223
let index = self . entries. len( ) ;
214
224
* pos = Some ( Pos :: new( index, hash) ) ;
215
225
unsafe { self . entries. push_unchecked( Bucket { hash, key, value } ) } ;
216
- return Insert {
226
+ return Insert :: Success ( Inserted {
217
227
index,
218
228
old_value: None ,
219
- }
229
+ } ) ;
220
230
}
221
231
dist += 1 ;
222
232
} ) ;
@@ -394,11 +404,15 @@ impl<'a, K, V, const N: usize> VacantEntry<'a, K, V, N> where K: Eq + Hash {
394
404
if self . core . entries . is_full ( ) {
395
405
Err ( value)
396
406
} else {
397
- let index = self . core . insert ( self . hash_val , self . key , value) . index ;
398
- unsafe {
399
- // SAFETY: Already checked existence at instantiation and the only mutable reference
400
- // to the map is internally held.
401
- Ok ( & mut self . core . entries . get_unchecked_mut ( index) . value )
407
+ match self . core . insert ( self . hash_val , self . key , value) {
408
+ Insert :: Success ( inserted) => {
409
+ unsafe {
410
+ // SAFETY: Already checked existence at instantiation and the only mutable reference
411
+ // to the map is internally held.
412
+ Ok ( & mut self . core . entries . get_unchecked_mut ( inserted. index ) . value )
413
+ }
414
+ }
415
+ Insert :: Full ( ( _, v) ) => Err ( v) ,
402
416
}
403
417
}
404
418
}
@@ -777,11 +791,10 @@ where
777
791
/// assert_eq!(map[&37], "c");
778
792
/// ```
779
793
pub fn insert ( & mut self , key : K , value : V ) -> Result < Option < V > , ( K , V ) > {
780
- if self . core . entries . is_full ( ) {
781
- Err ( ( key, value) )
782
- } else {
783
- let hash = hash_with ( & key, & self . build_hasher ) ;
784
- Ok ( self . core . insert ( hash, key, value) . old_value )
794
+ let hash = hash_with ( & key, & self . build_hasher ) ;
795
+ match self . core . insert ( hash, key, value) {
796
+ Insert :: Success ( inserted) => Ok ( inserted. old_value ) ,
797
+ Insert :: Full ( ( k, v) ) => Err ( ( k, v) )
785
798
}
786
799
}
787
800
@@ -1129,6 +1142,15 @@ mod tests {
1129
1142
}
1130
1143
}
1131
1144
1145
+ #[ test]
1146
+ fn insert_replaces_on_full_map ( ) {
1147
+ let mut a: FnvIndexMap < _ , _ , 2 > = FnvIndexMap :: new ( ) ;
1148
+ a. insert ( "k1" , "v1" ) . unwrap ( ) ;
1149
+ a. insert ( "k2" , "v2" ) . unwrap ( ) ;
1150
+ a. insert ( "k1" , "v2" ) . unwrap ( ) ;
1151
+ assert_eq ! ( a. get( "k1" ) , a. get( "k2" ) ) ;
1152
+ }
1153
+
1132
1154
const MAP_SLOTS : usize = 4096 ;
1133
1155
fn almost_filled_map ( ) -> FnvIndexMap < usize , usize , MAP_SLOTS > {
1134
1156
let mut almost_filled = FnvIndexMap :: new ( ) ;
0 commit comments