1
- #![ allow( unsafe_code) ]
2
1
//! This is the core implementation that doesn't depend on the hasher at all.
3
2
//!
4
3
//! The methods of `IndexMapCore` don't use any Hash properties of K.
8
7
//!
9
8
//! However, we should probably not let this show in the public API or docs.
10
9
10
+ mod raw;
11
+
11
12
#[ cfg( not( has_std) ) ]
12
13
use std:: vec:: Vec ;
13
14
@@ -23,8 +24,6 @@ use equivalent::Equivalent;
23
24
use util:: enumerate;
24
25
use { Bucket , Entries , HashValue } ;
25
26
26
- type RawBucket = hashbrown:: raw:: Bucket < usize > ;
27
-
28
27
/// Core of the map that does not depend on S
29
28
pub ( crate ) struct IndexMapCore < K , V > {
30
29
/// indices mapping from the entry hash to its index.
67
66
V : fmt:: Debug ,
68
67
{
69
68
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
70
- struct DebugIndices < ' a > ( & ' a RawTable < usize > ) ;
71
- impl fmt:: Debug for DebugIndices < ' _ > {
72
- fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
73
- let indices = unsafe { self . 0 . iter ( ) . map ( |raw_bucket| raw_bucket. read ( ) ) } ;
74
- f. debug_list ( ) . entries ( indices) . finish ( )
75
- }
76
- }
77
-
78
69
f. debug_struct ( "IndexMapCore" )
79
- . field ( "indices" , & DebugIndices ( & self . indices ) )
70
+ . field ( "indices" , & raw :: DebugIndices ( & self . indices ) )
80
71
. field ( "entries" , & self . entries )
81
72
. finish ( )
82
73
}
@@ -168,8 +159,7 @@ impl<K, V> IndexMapCore<K, V> {
168
159
pub ( crate ) fn pop ( & mut self ) -> Option < ( K , V ) > {
169
160
if let Some ( entry) = self . entries . pop ( ) {
170
161
let last = self . entries . len ( ) ;
171
- let raw_bucket = self . find_index ( entry. hash , last) . unwrap ( ) ;
172
- unsafe { self . indices . erase_no_drop ( & raw_bucket) } ;
162
+ self . erase_index ( entry. hash , last) ;
173
163
Some ( ( entry. key , entry. value ) )
174
164
} else {
175
165
None
@@ -190,17 +180,6 @@ impl<K, V> IndexMapCore<K, V> {
190
180
i
191
181
}
192
182
193
- /// Return the index in `entries` where an equivalent key can be found
194
- pub ( crate ) fn get_index_of < Q > ( & self , hash : HashValue , key : & Q ) -> Option < usize >
195
- where
196
- Q : ?Sized + Equivalent < K > ,
197
- {
198
- match self . find_equivalent ( hash, key) {
199
- Some ( raw_bucket) => Some ( unsafe { raw_bucket. read ( ) } ) ,
200
- None => None ,
201
- }
202
- }
203
-
204
183
pub ( crate ) fn insert_full ( & mut self , hash : HashValue , key : K , value : V ) -> ( usize , Option < V > )
205
184
where
206
185
K : Eq ,
@@ -211,150 +190,6 @@ impl<K, V> IndexMapCore<K, V> {
211
190
}
212
191
}
213
192
214
- pub ( crate ) fn entry ( & mut self , hash : HashValue , key : K ) -> Entry < K , V >
215
- where
216
- K : Eq ,
217
- {
218
- match self . find_equivalent ( hash, & key) {
219
- // Safety: The entry is created with a live raw bucket, at the same time we have a &mut
220
- // reference to the map, so it can not be modified further.
221
- Some ( raw_bucket) => Entry :: Occupied ( OccupiedEntry {
222
- map : self ,
223
- raw_bucket,
224
- key,
225
- } ) ,
226
- None => Entry :: Vacant ( VacantEntry {
227
- map : self ,
228
- hash,
229
- key,
230
- } ) ,
231
- }
232
- }
233
-
234
- /// Return the raw bucket with an equivalent key
235
- fn find_equivalent < Q > ( & self , hash : HashValue , key : & Q ) -> Option < RawBucket >
236
- where
237
- Q : ?Sized + Equivalent < K > ,
238
- {
239
- self . indices . find ( hash. get ( ) , {
240
- |& i| Q :: equivalent ( key, & self . entries [ i] . key )
241
- } )
242
- }
243
-
244
- /// Return the raw bucket for the given index
245
- fn find_index ( & self , hash : HashValue , index : usize ) -> Option < RawBucket > {
246
- self . indices . find ( hash. get ( ) , |& i| i == index)
247
- }
248
-
249
- /// Remove an entry by shifting all entries that follow it
250
- pub ( crate ) fn shift_remove_full < Q > ( & mut self , hash : HashValue , key : & Q ) -> Option < ( usize , K , V ) >
251
- where
252
- Q : ?Sized + Equivalent < K > ,
253
- {
254
- match self . find_equivalent ( hash, key) {
255
- Some ( raw_bucket) => unsafe { Some ( self . shift_remove_bucket ( raw_bucket) ) } ,
256
- None => None ,
257
- }
258
- }
259
-
260
- /// Remove an entry by shifting all entries that follow it
261
- pub ( crate ) fn shift_remove_index ( & mut self , index : usize ) -> Option < ( K , V ) > {
262
- let raw_bucket = match self . entries . get ( index) {
263
- Some ( entry) => self . find_index ( entry. hash , index) . unwrap ( ) ,
264
- None => return None ,
265
- } ;
266
- unsafe {
267
- let ( _, key, value) = self . shift_remove_bucket ( raw_bucket) ;
268
- Some ( ( key, value) )
269
- }
270
- }
271
-
272
- /// Remove an entry by shifting all entries that follow it
273
- ///
274
- /// Safety: The caller must pass a live `raw_bucket`.
275
- #[ allow( unused_unsafe) ]
276
- unsafe fn shift_remove_bucket ( & mut self , raw_bucket : RawBucket ) -> ( usize , K , V ) {
277
- // use Vec::remove, but then we need to update the indices that point
278
- // to all of the other entries that have to move
279
- let index = unsafe {
280
- self . indices . erase_no_drop ( & raw_bucket) ;
281
- raw_bucket. read ( )
282
- } ;
283
- let entry = self . entries . remove ( index) ;
284
-
285
- // correct indices that point to the entries that followed the removed entry.
286
- // use a heuristic between a full sweep vs. a `find()` for every shifted item.
287
- let raw_capacity = self . indices . buckets ( ) ;
288
- let shifted_entries = & self . entries [ index..] ;
289
- if shifted_entries. len ( ) > raw_capacity / 2 {
290
- // shift all indices greater than `index`
291
- unsafe {
292
- for bucket in self . indices . iter ( ) {
293
- let i = bucket. read ( ) ;
294
- if i > index {
295
- bucket. write ( i - 1 ) ;
296
- }
297
- }
298
- }
299
- } else {
300
- // find each following entry to shift its index
301
- for ( i, entry) in ( index + 1 ..) . zip ( shifted_entries) {
302
- let shifted_bucket = self . find_index ( entry. hash , i) . unwrap ( ) ;
303
- unsafe { shifted_bucket. write ( i - 1 ) } ;
304
- }
305
- }
306
-
307
- ( index, entry. key , entry. value )
308
- }
309
-
310
- /// Remove an entry by swapping it with the last
311
- pub ( crate ) fn swap_remove_full < Q > ( & mut self , hash : HashValue , key : & Q ) -> Option < ( usize , K , V ) >
312
- where
313
- Q : ?Sized + Equivalent < K > ,
314
- {
315
- match self . find_equivalent ( hash, key) {
316
- Some ( raw_bucket) => unsafe { Some ( self . swap_remove_bucket ( raw_bucket) ) } ,
317
- None => None ,
318
- }
319
- }
320
-
321
- /// Remove an entry by swapping it with the last
322
- pub ( crate ) fn swap_remove_index ( & mut self , index : usize ) -> Option < ( K , V ) > {
323
- let raw_bucket = match self . entries . get ( index) {
324
- Some ( entry) => self . find_index ( entry. hash , index) . unwrap ( ) ,
325
- None => return None ,
326
- } ;
327
- unsafe {
328
- let ( _, key, value) = self . swap_remove_bucket ( raw_bucket) ;
329
- Some ( ( key, value) )
330
- }
331
- }
332
-
333
- /// Remove an entry by swapping it with the last
334
- ///
335
- /// Safety: The caller must pass a live `raw_bucket`.
336
- #[ allow( unused_unsafe) ]
337
- unsafe fn swap_remove_bucket ( & mut self , raw_bucket : RawBucket ) -> ( usize , K , V ) {
338
- // use swap_remove, but then we need to update the index that points
339
- // to the other entry that has to move
340
- let index = unsafe {
341
- self . indices . erase_no_drop ( & raw_bucket) ;
342
- raw_bucket. read ( )
343
- } ;
344
- let entry = self . entries . swap_remove ( index) ;
345
-
346
- // correct index that points to the entry that had to swap places
347
- if let Some ( entry) = self . entries . get ( index) {
348
- // was not last element
349
- // examine new element in `index` and find it in indices
350
- let last = self . entries . len ( ) ;
351
- let swapped_bucket = self . find_index ( entry. hash , last) . unwrap ( ) ;
352
- unsafe { swapped_bucket. write ( index) } ;
353
- }
354
-
355
- ( index, entry. key , entry. value )
356
- }
357
-
358
193
pub ( crate ) fn retain_in_order < F > ( & mut self , mut keep : F )
359
194
where
360
195
F : FnMut ( & mut K , & mut V ) -> bool ,
@@ -381,20 +216,6 @@ impl<K, V> IndexMapCore<K, V> {
381
216
}
382
217
}
383
218
384
- pub ( crate ) fn reverse ( & mut self ) {
385
- self . entries . reverse ( ) ;
386
-
387
- // No need to save hash indices, can easily calculate what they should
388
- // be, given that this is an in-place reversal.
389
- let len = self . entries . len ( ) ;
390
- unsafe {
391
- for raw_bucket in self . indices . iter ( ) {
392
- let i = raw_bucket. read ( ) ;
393
- raw_bucket. write ( len - i - 1 ) ;
394
- }
395
- }
396
- }
397
-
398
219
fn rebuild_hash_table ( & mut self ) {
399
220
self . indices . clear_no_drop ( ) ;
400
221
debug_assert ! ( self . indices. capacity( ) >= self . entries. len( ) ) ;
@@ -487,52 +308,10 @@ impl<'a, K: 'a + fmt::Debug, V: 'a + fmt::Debug> fmt::Debug for Entry<'a, K, V>
487
308
}
488
309
}
489
310
490
- /// A view into an occupied entry in a `IndexMap`.
491
- /// It is part of the [`Entry`] enum.
492
- ///
493
- /// [`Entry`]: enum.Entry.html
494
- pub struct OccupiedEntry < ' a , K : ' a , V : ' a > {
495
- map : & ' a mut IndexMapCore < K , V > ,
496
- raw_bucket : RawBucket ,
497
- key : K ,
498
- }
499
-
500
- // `hashbrown::raw::Bucket` is only `Send`, not `Sync`.
501
- // SAFETY: `&self` only accesses the bucket to read it.
502
- unsafe impl < K : Sync , V : Sync > Sync for OccupiedEntry < ' _ , K , V > { }
311
+ pub use self :: raw:: OccupiedEntry ;
503
312
313
+ // Extra methods that don't threaten the unsafe encapsulation.
504
314
impl < ' a , K , V > OccupiedEntry < ' a , K , V > {
505
- pub fn key ( & self ) -> & K {
506
- & self . key
507
- }
508
-
509
- pub fn get ( & self ) -> & V {
510
- & self . map . entries [ self . index ( ) ] . value
511
- }
512
-
513
- pub fn get_mut ( & mut self ) -> & mut V {
514
- let index = self . index ( ) ;
515
- & mut self . map . entries [ index] . value
516
- }
517
-
518
- /// Put the new key in the occupied entry's key slot
519
- pub ( crate ) fn replace_key ( self ) -> K {
520
- let index = self . index ( ) ;
521
- let old_key = & mut self . map . entries [ index] . key ;
522
- replace ( old_key, self . key )
523
- }
524
-
525
- /// Return the index of the key-value pair
526
- #[ inline]
527
- pub fn index ( & self ) -> usize {
528
- unsafe { self . raw_bucket . read ( ) }
529
- }
530
-
531
- pub fn into_mut ( self ) -> & ' a mut V {
532
- let index = self . index ( ) ;
533
- & mut self . map . entries [ index] . value
534
- }
535
-
536
315
/// Sets the value of the entry to `value`, and returns the entry's old value.
537
316
pub fn insert ( & mut self , value : V ) -> V {
538
317
replace ( self . get_mut ( ) , value)
@@ -573,38 +352,6 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> {
573
352
pub fn remove_entry ( self ) -> ( K , V ) {
574
353
self . swap_remove_entry ( )
575
354
}
576
-
577
- /// Remove and return the key, value pair stored in the map for this entry
578
- ///
579
- /// Like `Vec::swap_remove`, the pair is removed by swapping it with the
580
- /// last element of the map and popping it off. **This perturbs
581
- /// the postion of what used to be the last element!**
582
- ///
583
- /// Computes in **O(1)** time (average).
584
- pub fn swap_remove_entry ( self ) -> ( K , V ) {
585
- // This is safe because it can only happen once (self is consumed)
586
- // and map.indices have not been modified since entry construction
587
- unsafe {
588
- let ( _, key, value) = self . map . swap_remove_bucket ( self . raw_bucket ) ;
589
- ( key, value)
590
- }
591
- }
592
-
593
- /// Remove and return the key, value pair stored in the map for this entry
594
- ///
595
- /// Like `Vec::remove`, the pair is removed by shifting all of the
596
- /// elements that follow it, preserving their relative order.
597
- /// **This perturbs the index of all of those elements!**
598
- ///
599
- /// Computes in **O(n)** time (average).
600
- pub fn shift_remove_entry ( self ) -> ( K , V ) {
601
- // This is safe because it can only happen once (self is consumed)
602
- // and map.indices have not been modified since entry construction
603
- unsafe {
604
- let ( _, key, value) = self . map . shift_remove_bucket ( self . raw_bucket ) ;
605
- ( key, value)
606
- }
607
- }
608
355
}
609
356
610
357
impl < ' a , K : ' a + fmt:: Debug , V : ' a + fmt:: Debug > fmt:: Debug for OccupiedEntry < ' a , K , V > {
0 commit comments