1
1
use super :: either_iter:: EitherIter ;
2
2
use crate :: fx:: FxHashMap ;
3
3
use arrayvec:: ArrayVec ;
4
- use std:: borrow:: Borrow ;
5
4
use std:: fmt;
6
5
use std:: hash:: Hash ;
7
6
use std:: iter:: FromIterator ;
@@ -30,19 +29,45 @@ const SSO_ARRAY_SIZE: usize = 8;
30
29
///
31
30
/// Stores elements in a small array up to a certain length
32
31
/// and switches to `HashMap` when that length is exceeded.
33
- ///
34
- /// Implements subset of HashMap API.
35
- ///
36
- /// Missing HashMap API:
37
- /// all hasher-related
38
- /// try_reserve (unstable)
39
- /// shrink_to (unstable)
40
- /// drain_filter (unstable)
41
- /// into_keys/into_values (unstable)
42
- /// all raw_entry-related
43
- /// PartialEq/Eq (requires sorting the array)
44
- /// Entry::or_insert_with_key (unstable)
45
- /// Vacant/Occupied entries and related
32
+ //
33
+ // FIXME: Implements subset of HashMap API.
34
+ //
35
+ // Missing HashMap API:
36
+ // all hasher-related
37
+ // try_reserve (unstable)
38
+ // shrink_to (unstable)
39
+ // drain_filter (unstable)
40
+ // into_keys/into_values (unstable)
41
+ // all raw_entry-related
42
+ // PartialEq/Eq (requires sorting the array)
43
+ // Entry::or_insert_with_key (unstable)
44
+ // Vacant/Occupied entries and related
45
+ //
46
+ // FIXME: In HashMap most methods accepting key reference
47
+ // accept reference to generic `Q` where `K: Borrow<Q>`.
48
+ //
49
+ // However, using this approach in `HashMap::get` apparently
50
+ // breaks inlining and noticeably reduces performance.
51
+ //
52
+ // Performance *should* be the same given that borrow is
53
+ // a NOP in most cases, but in practice that's not the case.
54
+ //
55
+ // Further investigation is required.
56
+ //
57
+ // Affected methods:
58
+ // SsoHashMap::get
59
+ // SsoHashMap::get_mut
60
+ // SsoHashMap::get_entry
61
+ // SsoHashMap::get_key_value
62
+ // SsoHashMap::contains_key
63
+ // SsoHashMap::remove
64
+ // SsoHashMap::remove_entry
65
+ // Index::index
66
+ // SsoHashSet::take
67
+ // SsoHashSet::get
68
+ // SsoHashSet::remove
69
+ // SsoHashSet::contains
70
+
46
71
#[ derive( Clone ) ]
47
72
pub enum SsoHashMap < K , V > {
48
73
Array ( ArrayVec < [ ( K , V ) ; SSO_ARRAY_SIZE ] > ) ,
@@ -232,14 +257,10 @@ impl<K: Eq + Hash, V> SsoHashMap<K, V> {
232
257
233
258
/// Removes a key from the map, returning the value at the key if the key
234
259
/// was previously in the map.
235
- pub fn remove < Q : ?Sized > ( & mut self , key : & Q ) -> Option < V >
236
- where
237
- K : Borrow < Q > ,
238
- Q : Hash + Eq ,
239
- {
260
+ pub fn remove ( & mut self , key : & K ) -> Option < V > {
240
261
match self {
241
262
SsoHashMap :: Array ( array) => {
242
- if let Some ( index) = array. iter ( ) . position ( |( k, _v) | k. borrow ( ) == key) {
263
+ if let Some ( index) = array. iter ( ) . position ( |( k, _v) | k == key) {
243
264
Some ( array. swap_remove ( index) . 1 )
244
265
} else {
245
266
None
@@ -251,14 +272,10 @@ impl<K: Eq + Hash, V> SsoHashMap<K, V> {
251
272
252
273
/// Removes a key from the map, returning the stored key and value if the
253
274
/// key was previously in the map.
254
- pub fn remove_entry < Q : ?Sized > ( & mut self , key : & Q ) -> Option < ( K , V ) >
255
- where
256
- K : Borrow < Q > ,
257
- Q : Hash + Eq ,
258
- {
275
+ pub fn remove_entry ( & mut self , key : & K ) -> Option < ( K , V ) > {
259
276
match self {
260
277
SsoHashMap :: Array ( array) => {
261
- if let Some ( index) = array. iter ( ) . position ( |( k, _v) | k. borrow ( ) == key) {
278
+ if let Some ( index) = array. iter ( ) . position ( |( k, _v) | k == key) {
262
279
Some ( array. swap_remove ( index) )
263
280
} else {
264
281
None
@@ -269,15 +286,11 @@ impl<K: Eq + Hash, V> SsoHashMap<K, V> {
269
286
}
270
287
271
288
/// Returns a reference to the value corresponding to the key.
272
- pub fn get < Q : ?Sized > ( & self , key : & Q ) -> Option < & V >
273
- where
274
- K : Borrow < Q > ,
275
- Q : Hash + Eq ,
276
- {
289
+ pub fn get ( & self , key : & K ) -> Option < & V > {
277
290
match self {
278
291
SsoHashMap :: Array ( array) => {
279
292
for ( k, v) in array {
280
- if k. borrow ( ) == key {
293
+ if k == key {
281
294
return Some ( v) ;
282
295
}
283
296
}
@@ -288,15 +301,11 @@ impl<K: Eq + Hash, V> SsoHashMap<K, V> {
288
301
}
289
302
290
303
/// Returns a mutable reference to the value corresponding to the key.
291
- pub fn get_mut < Q : ?Sized > ( & mut self , key : & Q ) -> Option < & mut V >
292
- where
293
- K : Borrow < Q > ,
294
- Q : Hash + Eq ,
295
- {
304
+ pub fn get_mut ( & mut self , key : & K ) -> Option < & mut V > {
296
305
match self {
297
306
SsoHashMap :: Array ( array) => {
298
307
for ( k, v) in array {
299
- if ( * k ) . borrow ( ) == key {
308
+ if k == key {
300
309
return Some ( v) ;
301
310
}
302
311
}
@@ -307,15 +316,11 @@ impl<K: Eq + Hash, V> SsoHashMap<K, V> {
307
316
}
308
317
309
318
/// Returns the key-value pair corresponding to the supplied key.
310
- pub fn get_key_value < Q : ?Sized > ( & self , key : & Q ) -> Option < ( & K , & V ) >
311
- where
312
- K : Borrow < Q > ,
313
- Q : Hash + Eq ,
314
- {
319
+ pub fn get_key_value ( & self , key : & K ) -> Option < ( & K , & V ) > {
315
320
match self {
316
321
SsoHashMap :: Array ( array) => {
317
322
for ( k, v) in array {
318
- if k. borrow ( ) == key {
323
+ if k == key {
319
324
return Some ( ( k, v) ) ;
320
325
}
321
326
}
@@ -326,13 +331,9 @@ impl<K: Eq + Hash, V> SsoHashMap<K, V> {
326
331
}
327
332
328
333
/// Returns `true` if the map contains a value for the specified key.
329
- pub fn contains_key < Q : ?Sized > ( & self , key : & Q ) -> bool
330
- where
331
- K : Borrow < Q > ,
332
- Q : Hash + Eq ,
333
- {
334
+ pub fn contains_key ( & self , key : & K ) -> bool {
334
335
match self {
335
- SsoHashMap :: Array ( array) => array. iter ( ) . any ( |( k, _v) | k. borrow ( ) == key) ,
336
+ SsoHashMap :: Array ( array) => array. iter ( ) . any ( |( k, _v) | k == key) ,
336
337
SsoHashMap :: Map ( map) => map. contains_key ( key) ,
337
338
}
338
339
}
@@ -483,15 +484,14 @@ where
483
484
}
484
485
}
485
486
486
- impl < ' a , K , Q : ? Sized , V > Index < & ' a Q > for SsoHashMap < K , V >
487
+ impl < ' a , K , V > Index < & ' a K > for SsoHashMap < K , V >
487
488
where
488
- K : Eq + Hash + Borrow < Q > ,
489
- Q : Eq + Hash ,
489
+ K : Eq + Hash ,
490
490
{
491
491
type Output = V ;
492
492
493
493
#[ inline]
494
- fn index ( & self , key : & Q ) -> & V {
494
+ fn index ( & self , key : & K ) -> & V {
495
495
self . get ( key) . expect ( "no entry found for key" )
496
496
}
497
497
}
0 commit comments