1 | //! Opt-in access to the experimental raw entry API. |
2 | //! |
3 | //! This module is designed to mimic the raw entry API of [`HashMap`][std::collections::hash_map], |
4 | //! matching its unstable state as of Rust 1.75. See the tracking issue |
5 | //! [rust#56167](https://github.com/rust-lang/rust/issues/56167) for more details. |
6 | //! |
7 | //! The trait [`RawEntryApiV1`] and the `_v1` suffix on its methods are meant to insulate this for |
8 | //! the future, in case later breaking changes are needed. If the standard library stabilizes its |
9 | //! `hash_raw_entry` feature (or some replacement), matching *inherent* methods will be added to |
10 | //! `IndexMap` without such an opt-in trait. |
11 | |
12 | use super::{Entries, RefMut}; |
13 | use crate::{Equivalent, HashValue, IndexMap}; |
14 | use core::fmt; |
15 | use core::hash::{BuildHasher, Hash, Hasher}; |
16 | use core::marker::PhantomData; |
17 | use core::mem; |
18 | use hashbrown::hash_table; |
19 | |
20 | /// Opt-in access to the experimental raw entry API. |
21 | /// |
22 | /// See the [`raw_entry_v1`][self] module documentation for more information. |
23 | pub trait RawEntryApiV1<K, V, S>: private::Sealed { |
24 | /// Creates a raw immutable entry builder for the [`IndexMap`]. |
25 | /// |
26 | /// Raw entries provide the lowest level of control for searching and |
27 | /// manipulating a map. They must be manually initialized with a hash and |
28 | /// then manually searched. |
29 | /// |
30 | /// This is useful for |
31 | /// * Hash memoization |
32 | /// * Using a search key that doesn't work with the [`Equivalent`] trait |
33 | /// * Using custom comparison logic without newtype wrappers |
34 | /// |
35 | /// Unless you are in such a situation, higher-level and more foolproof APIs like |
36 | /// [`get`][IndexMap::get] should be preferred. |
37 | /// |
38 | /// Immutable raw entries have very limited use; you might instead want |
39 | /// [`raw_entry_mut_v1`][Self::raw_entry_mut_v1]. |
40 | /// |
41 | /// # Examples |
42 | /// |
43 | /// ``` |
44 | /// use core::hash::{BuildHasher, Hash}; |
45 | /// use indexmap::map::{IndexMap, RawEntryApiV1}; |
46 | /// |
47 | /// let mut map = IndexMap::new(); |
48 | /// map.extend([("a" , 100), ("b" , 200), ("c" , 300)]); |
49 | /// |
50 | /// fn compute_hash<K: Hash + ?Sized, S: BuildHasher>(hash_builder: &S, key: &K) -> u64 { |
51 | /// use core::hash::Hasher; |
52 | /// let mut state = hash_builder.build_hasher(); |
53 | /// key.hash(&mut state); |
54 | /// state.finish() |
55 | /// } |
56 | /// |
57 | /// for k in ["a" , "b" , "c" , "d" , "e" , "f" ] { |
58 | /// let hash = compute_hash(map.hasher(), k); |
59 | /// let i = map.get_index_of(k); |
60 | /// let v = map.get(k); |
61 | /// let kv = map.get_key_value(k); |
62 | /// let ikv = map.get_full(k); |
63 | /// |
64 | /// println!("Key: {} and value: {:?}" , k, v); |
65 | /// |
66 | /// assert_eq!(map.raw_entry_v1().from_key(k), kv); |
67 | /// assert_eq!(map.raw_entry_v1().from_hash(hash, |q| *q == k), kv); |
68 | /// assert_eq!(map.raw_entry_v1().from_key_hashed_nocheck(hash, k), kv); |
69 | /// assert_eq!(map.raw_entry_v1().from_hash_full(hash, |q| *q == k), ikv); |
70 | /// assert_eq!(map.raw_entry_v1().index_from_hash(hash, |q| *q == k), i); |
71 | /// } |
72 | /// ``` |
73 | fn raw_entry_v1(&self) -> RawEntryBuilder<'_, K, V, S>; |
74 | |
75 | /// Creates a raw entry builder for the [`IndexMap`]. |
76 | /// |
77 | /// Raw entries provide the lowest level of control for searching and |
78 | /// manipulating a map. They must be manually initialized with a hash and |
79 | /// then manually searched. After this, insertions into a vacant entry |
80 | /// still require an owned key to be provided. |
81 | /// |
82 | /// Raw entries are useful for such exotic situations as: |
83 | /// |
84 | /// * Hash memoization |
85 | /// * Deferring the creation of an owned key until it is known to be required |
86 | /// * Using a search key that doesn't work with the [`Equivalent`] trait |
87 | /// * Using custom comparison logic without newtype wrappers |
88 | /// |
89 | /// Because raw entries provide much more low-level control, it's much easier |
90 | /// to put the `IndexMap` into an inconsistent state which, while memory-safe, |
91 | /// will cause the map to produce seemingly random results. Higher-level and more |
92 | /// foolproof APIs like [`entry`][IndexMap::entry] should be preferred when possible. |
93 | /// |
94 | /// Raw entries give mutable access to the keys. This must not be used |
95 | /// to modify how the key would compare or hash, as the map will not re-evaluate |
96 | /// where the key should go, meaning the keys may become "lost" if their |
97 | /// location does not reflect their state. For instance, if you change a key |
98 | /// so that the map now contains keys which compare equal, search may start |
99 | /// acting erratically, with two keys randomly masking each other. Implementations |
100 | /// are free to assume this doesn't happen (within the limits of memory-safety). |
101 | /// |
102 | /// # Examples |
103 | /// |
104 | /// ``` |
105 | /// use core::hash::{BuildHasher, Hash}; |
106 | /// use indexmap::map::{IndexMap, RawEntryApiV1}; |
107 | /// use indexmap::map::raw_entry_v1::RawEntryMut; |
108 | /// |
109 | /// let mut map = IndexMap::new(); |
110 | /// map.extend([("a" , 100), ("b" , 200), ("c" , 300)]); |
111 | /// |
112 | /// fn compute_hash<K: Hash + ?Sized, S: BuildHasher>(hash_builder: &S, key: &K) -> u64 { |
113 | /// use core::hash::Hasher; |
114 | /// let mut state = hash_builder.build_hasher(); |
115 | /// key.hash(&mut state); |
116 | /// state.finish() |
117 | /// } |
118 | /// |
119 | /// // Existing key (insert and update) |
120 | /// match map.raw_entry_mut_v1().from_key("a" ) { |
121 | /// RawEntryMut::Vacant(_) => unreachable!(), |
122 | /// RawEntryMut::Occupied(mut view) => { |
123 | /// assert_eq!(view.index(), 0); |
124 | /// assert_eq!(view.get(), &100); |
125 | /// let v = view.get_mut(); |
126 | /// let new_v = (*v) * 10; |
127 | /// *v = new_v; |
128 | /// assert_eq!(view.insert(1111), 1000); |
129 | /// } |
130 | /// } |
131 | /// |
132 | /// assert_eq!(map["a" ], 1111); |
133 | /// assert_eq!(map.len(), 3); |
134 | /// |
135 | /// // Existing key (take) |
136 | /// let hash = compute_hash(map.hasher(), "c" ); |
137 | /// match map.raw_entry_mut_v1().from_key_hashed_nocheck(hash, "c" ) { |
138 | /// RawEntryMut::Vacant(_) => unreachable!(), |
139 | /// RawEntryMut::Occupied(view) => { |
140 | /// assert_eq!(view.index(), 2); |
141 | /// assert_eq!(view.shift_remove_entry(), ("c" , 300)); |
142 | /// } |
143 | /// } |
144 | /// assert_eq!(map.raw_entry_v1().from_key("c" ), None); |
145 | /// assert_eq!(map.len(), 2); |
146 | /// |
147 | /// // Nonexistent key (insert and update) |
148 | /// let key = "d" ; |
149 | /// let hash = compute_hash(map.hasher(), key); |
150 | /// match map.raw_entry_mut_v1().from_hash(hash, |q| *q == key) { |
151 | /// RawEntryMut::Occupied(_) => unreachable!(), |
152 | /// RawEntryMut::Vacant(view) => { |
153 | /// assert_eq!(view.index(), 2); |
154 | /// let (k, value) = view.insert("d" , 4000); |
155 | /// assert_eq!((*k, *value), ("d" , 4000)); |
156 | /// *value = 40000; |
157 | /// } |
158 | /// } |
159 | /// assert_eq!(map["d" ], 40000); |
160 | /// assert_eq!(map.len(), 3); |
161 | /// |
162 | /// match map.raw_entry_mut_v1().from_hash(hash, |q| *q == key) { |
163 | /// RawEntryMut::Vacant(_) => unreachable!(), |
164 | /// RawEntryMut::Occupied(view) => { |
165 | /// assert_eq!(view.index(), 2); |
166 | /// assert_eq!(view.swap_remove_entry(), ("d" , 40000)); |
167 | /// } |
168 | /// } |
169 | /// assert_eq!(map.get("d" ), None); |
170 | /// assert_eq!(map.len(), 2); |
171 | /// ``` |
172 | fn raw_entry_mut_v1(&mut self) -> RawEntryBuilderMut<'_, K, V, S>; |
173 | } |
174 | |
175 | impl<K, V, S> RawEntryApiV1<K, V, S> for IndexMap<K, V, S> { |
176 | fn raw_entry_v1(&self) -> RawEntryBuilder<'_, K, V, S> { |
177 | RawEntryBuilder { map: self } |
178 | } |
179 | |
180 | fn raw_entry_mut_v1(&mut self) -> RawEntryBuilderMut<'_, K, V, S> { |
181 | RawEntryBuilderMut { map: self } |
182 | } |
183 | } |
184 | |
185 | /// A builder for computing where in an [`IndexMap`] a key-value pair would be stored. |
186 | /// |
187 | /// This `struct` is created by the [`IndexMap::raw_entry_v1`] method, provided by the |
188 | /// [`RawEntryApiV1`] trait. See its documentation for more. |
189 | pub struct RawEntryBuilder<'a, K, V, S> { |
190 | map: &'a IndexMap<K, V, S>, |
191 | } |
192 | |
193 | impl<K, V, S> fmt::Debug for RawEntryBuilder<'_, K, V, S> { |
194 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
195 | f.debug_struct(name:"RawEntryBuilder" ).finish_non_exhaustive() |
196 | } |
197 | } |
198 | |
199 | impl<'a, K, V, S> RawEntryBuilder<'a, K, V, S> { |
200 | /// Access an entry by key. |
201 | pub fn from_key<Q>(self, key: &Q) -> Option<(&'a K, &'a V)> |
202 | where |
203 | S: BuildHasher, |
204 | Q: ?Sized + Hash + Equivalent<K>, |
205 | { |
206 | self.map.get_key_value(key) |
207 | } |
208 | |
209 | /// Access an entry by a key and its hash. |
210 | pub fn from_key_hashed_nocheck<Q>(self, hash: u64, key: &Q) -> Option<(&'a K, &'a V)> |
211 | where |
212 | Q: ?Sized + Equivalent<K>, |
213 | { |
214 | let hash = HashValue(hash as usize); |
215 | let i = self.map.core.get_index_of(hash, key)?; |
216 | self.map.get_index(i) |
217 | } |
218 | |
219 | /// Access an entry by hash. |
220 | pub fn from_hash<F>(self, hash: u64, is_match: F) -> Option<(&'a K, &'a V)> |
221 | where |
222 | F: FnMut(&K) -> bool, |
223 | { |
224 | let map = self.map; |
225 | let i = self.index_from_hash(hash, is_match)?; |
226 | map.get_index(i) |
227 | } |
228 | |
229 | /// Access an entry by hash, including its index. |
230 | pub fn from_hash_full<F>(self, hash: u64, is_match: F) -> Option<(usize, &'a K, &'a V)> |
231 | where |
232 | F: FnMut(&K) -> bool, |
233 | { |
234 | let map = self.map; |
235 | let i = self.index_from_hash(hash, is_match)?; |
236 | let (key, value) = map.get_index(i)?; |
237 | Some((i, key, value)) |
238 | } |
239 | |
240 | /// Access the index of an entry by hash. |
241 | pub fn index_from_hash<F>(self, hash: u64, mut is_match: F) -> Option<usize> |
242 | where |
243 | F: FnMut(&K) -> bool, |
244 | { |
245 | let hash = HashValue(hash as usize); |
246 | let entries = &*self.map.core.entries; |
247 | let eq = move |&i: &usize| is_match(&entries[i].key); |
248 | self.map.core.indices.find(hash.get(), eq).copied() |
249 | } |
250 | } |
251 | |
252 | /// A builder for computing where in an [`IndexMap`] a key-value pair would be stored. |
253 | /// |
254 | /// This `struct` is created by the [`IndexMap::raw_entry_mut_v1`] method, provided by the |
255 | /// [`RawEntryApiV1`] trait. See its documentation for more. |
256 | pub struct RawEntryBuilderMut<'a, K, V, S> { |
257 | map: &'a mut IndexMap<K, V, S>, |
258 | } |
259 | |
260 | impl<K, V, S> fmt::Debug for RawEntryBuilderMut<'_, K, V, S> { |
261 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
262 | f.debug_struct(name:"RawEntryBuilderMut" ).finish_non_exhaustive() |
263 | } |
264 | } |
265 | |
266 | impl<'a, K, V, S> RawEntryBuilderMut<'a, K, V, S> { |
267 | /// Access an entry by key. |
268 | pub fn from_key<Q>(self, key: &Q) -> RawEntryMut<'a, K, V, S> |
269 | where |
270 | S: BuildHasher, |
271 | Q: ?Sized + Hash + Equivalent<K>, |
272 | { |
273 | let hash = self.map.hash(key); |
274 | self.from_key_hashed_nocheck(hash.get(), key) |
275 | } |
276 | |
277 | /// Access an entry by a key and its hash. |
278 | pub fn from_key_hashed_nocheck<Q>(self, hash: u64, key: &Q) -> RawEntryMut<'a, K, V, S> |
279 | where |
280 | Q: ?Sized + Equivalent<K>, |
281 | { |
282 | self.from_hash(hash, |k| Q::equivalent(key, k)) |
283 | } |
284 | |
285 | /// Access an entry by hash. |
286 | pub fn from_hash<F>(self, hash: u64, mut is_match: F) -> RawEntryMut<'a, K, V, S> |
287 | where |
288 | F: FnMut(&K) -> bool, |
289 | { |
290 | let ref_entries = &*self.map.core.entries; |
291 | let eq = move |&i: &usize| is_match(&ref_entries[i].key); |
292 | match self.map.core.indices.find_entry(hash, eq) { |
293 | Ok(index) => RawEntryMut::Occupied(RawOccupiedEntryMut { |
294 | entries: &mut self.map.core.entries, |
295 | index, |
296 | hash_builder: PhantomData, |
297 | }), |
298 | Err(absent) => RawEntryMut::Vacant(RawVacantEntryMut { |
299 | map: RefMut::new(absent.into_table(), &mut self.map.core.entries), |
300 | hash_builder: &self.map.hash_builder, |
301 | }), |
302 | } |
303 | } |
304 | } |
305 | |
306 | /// Raw entry for an existing key-value pair or a vacant location to |
307 | /// insert one. |
308 | pub enum RawEntryMut<'a, K, V, S> { |
309 | /// Existing slot with equivalent key. |
310 | Occupied(RawOccupiedEntryMut<'a, K, V, S>), |
311 | /// Vacant slot (no equivalent key in the map). |
312 | Vacant(RawVacantEntryMut<'a, K, V, S>), |
313 | } |
314 | |
315 | impl<K: fmt::Debug, V: fmt::Debug, S> fmt::Debug for RawEntryMut<'_, K, V, S> { |
316 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
317 | let mut tuple: DebugTuple<'_, '_> = f.debug_tuple(name:"RawEntryMut" ); |
318 | match self { |
319 | Self::Vacant(v: &RawVacantEntryMut<'_, K, …, …>) => tuple.field(v), |
320 | Self::Occupied(o: &RawOccupiedEntryMut<'_, K, …, …>) => tuple.field(o), |
321 | }; |
322 | tuple.finish() |
323 | } |
324 | } |
325 | |
326 | impl<'a, K, V, S> RawEntryMut<'a, K, V, S> { |
327 | /// Return the index where the key-value pair exists or may be inserted. |
328 | #[inline ] |
329 | pub fn index(&self) -> usize { |
330 | match self { |
331 | Self::Occupied(entry) => entry.index(), |
332 | Self::Vacant(entry) => entry.index(), |
333 | } |
334 | } |
335 | |
336 | /// Inserts the given default key and value in the entry if it is vacant and returns mutable |
337 | /// references to them. Otherwise mutable references to an already existent pair are returned. |
338 | pub fn or_insert(self, default_key: K, default_value: V) -> (&'a mut K, &'a mut V) |
339 | where |
340 | K: Hash, |
341 | S: BuildHasher, |
342 | { |
343 | match self { |
344 | Self::Occupied(entry) => entry.into_key_value_mut(), |
345 | Self::Vacant(entry) => entry.insert(default_key, default_value), |
346 | } |
347 | } |
348 | |
349 | /// Inserts the result of the `call` function in the entry if it is vacant and returns mutable |
350 | /// references to them. Otherwise mutable references to an already existent pair are returned. |
351 | pub fn or_insert_with<F>(self, call: F) -> (&'a mut K, &'a mut V) |
352 | where |
353 | F: FnOnce() -> (K, V), |
354 | K: Hash, |
355 | S: BuildHasher, |
356 | { |
357 | match self { |
358 | Self::Occupied(entry) => entry.into_key_value_mut(), |
359 | Self::Vacant(entry) => { |
360 | let (key, value) = call(); |
361 | entry.insert(key, value) |
362 | } |
363 | } |
364 | } |
365 | |
366 | /// Modifies the entry if it is occupied. |
367 | pub fn and_modify<F>(mut self, f: F) -> Self |
368 | where |
369 | F: FnOnce(&mut K, &mut V), |
370 | { |
371 | if let Self::Occupied(entry) = &mut self { |
372 | let (k, v) = entry.get_key_value_mut(); |
373 | f(k, v); |
374 | } |
375 | self |
376 | } |
377 | } |
378 | |
379 | /// A raw view into an occupied entry in an [`IndexMap`]. |
380 | /// It is part of the [`RawEntryMut`] enum. |
381 | pub struct RawOccupiedEntryMut<'a, K, V, S> { |
382 | entries: &'a mut Entries<K, V>, |
383 | index: hash_table::OccupiedEntry<'a, usize>, |
384 | hash_builder: PhantomData<&'a S>, |
385 | } |
386 | |
387 | impl<K: fmt::Debug, V: fmt::Debug, S> fmt::Debug for RawOccupiedEntryMut<'_, K, V, S> { |
388 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
389 | f&mut DebugStruct<'_, '_>.debug_struct("RawOccupiedEntryMut" ) |
390 | .field("key" , self.key()) |
391 | .field(name:"value" , self.get()) |
392 | .finish_non_exhaustive() |
393 | } |
394 | } |
395 | |
396 | impl<'a, K, V, S> RawOccupiedEntryMut<'a, K, V, S> { |
397 | /// Return the index of the key-value pair |
398 | #[inline ] |
399 | pub fn index(&self) -> usize { |
400 | *self.index.get() |
401 | } |
402 | |
403 | #[inline ] |
404 | fn into_ref_mut(self) -> RefMut<'a, K, V> { |
405 | RefMut::new(self.index.into_table(), self.entries) |
406 | } |
407 | |
408 | /// Gets a reference to the entry's key in the map. |
409 | /// |
410 | /// Note that this is not the key that was used to find the entry. There may be an observable |
411 | /// difference if the key type has any distinguishing features outside of `Hash` and `Eq`, like |
412 | /// extra fields or the memory address of an allocation. |
413 | pub fn key(&self) -> &K { |
414 | &self.entries[self.index()].key |
415 | } |
416 | |
417 | /// Gets a mutable reference to the entry's key in the map. |
418 | /// |
419 | /// Note that this is not the key that was used to find the entry. There may be an observable |
420 | /// difference if the key type has any distinguishing features outside of `Hash` and `Eq`, like |
421 | /// extra fields or the memory address of an allocation. |
422 | pub fn key_mut(&mut self) -> &mut K { |
423 | let index = self.index(); |
424 | &mut self.entries[index].key |
425 | } |
426 | |
427 | /// Converts into a mutable reference to the entry's key in the map, |
428 | /// with a lifetime bound to the map itself. |
429 | /// |
430 | /// Note that this is not the key that was used to find the entry. There may be an observable |
431 | /// difference if the key type has any distinguishing features outside of `Hash` and `Eq`, like |
432 | /// extra fields or the memory address of an allocation. |
433 | pub fn into_key(self) -> &'a mut K { |
434 | let index = self.index(); |
435 | &mut self.entries[index].key |
436 | } |
437 | |
438 | /// Gets a reference to the entry's value in the map. |
439 | pub fn get(&self) -> &V { |
440 | &self.entries[self.index()].value |
441 | } |
442 | |
443 | /// Gets a mutable reference to the entry's value in the map. |
444 | /// |
445 | /// If you need a reference which may outlive the destruction of the |
446 | /// [`RawEntryMut`] value, see [`into_mut`][Self::into_mut]. |
447 | pub fn get_mut(&mut self) -> &mut V { |
448 | let index = self.index(); |
449 | &mut self.entries[index].value |
450 | } |
451 | |
452 | /// Converts into a mutable reference to the entry's value in the map, |
453 | /// with a lifetime bound to the map itself. |
454 | pub fn into_mut(self) -> &'a mut V { |
455 | let index = self.index(); |
456 | &mut self.entries[index].value |
457 | } |
458 | |
459 | /// Gets a reference to the entry's key and value in the map. |
460 | pub fn get_key_value(&self) -> (&K, &V) { |
461 | self.entries[self.index()].refs() |
462 | } |
463 | |
464 | /// Gets a reference to the entry's key and value in the map. |
465 | pub fn get_key_value_mut(&mut self) -> (&mut K, &mut V) { |
466 | let index = self.index(); |
467 | self.entries[index].muts() |
468 | } |
469 | |
470 | /// Converts into a mutable reference to the entry's key and value in the map, |
471 | /// with a lifetime bound to the map itself. |
472 | pub fn into_key_value_mut(self) -> (&'a mut K, &'a mut V) { |
473 | let index = self.index(); |
474 | self.entries[index].muts() |
475 | } |
476 | |
477 | /// Sets the value of the entry, and returns the entry's old value. |
478 | pub fn insert(&mut self, value: V) -> V { |
479 | mem::replace(self.get_mut(), value) |
480 | } |
481 | |
482 | /// Sets the key of the entry, and returns the entry's old key. |
483 | pub fn insert_key(&mut self, key: K) -> K { |
484 | mem::replace(self.key_mut(), key) |
485 | } |
486 | |
487 | /// Remove the key, value pair stored in the map for this entry, and return the value. |
488 | /// |
489 | /// **NOTE:** This is equivalent to [`.swap_remove()`][Self::swap_remove], replacing this |
490 | /// entry's position with the last element, and it is deprecated in favor of calling that |
491 | /// explicitly. If you need to preserve the relative order of the keys in the map, use |
492 | /// [`.shift_remove()`][Self::shift_remove] instead. |
493 | #[deprecated (note = "`remove` disrupts the map order -- \ |
494 | use `swap_remove` or `shift_remove` for explicit behavior." )] |
495 | pub fn remove(self) -> V { |
496 | self.swap_remove() |
497 | } |
498 | |
499 | /// Remove the key, value pair stored in the map for this entry, and return the value. |
500 | /// |
501 | /// Like [`Vec::swap_remove`][crate::Vec::swap_remove], the pair is removed by swapping it with |
502 | /// the last element of the map and popping it off. |
503 | /// **This perturbs the position of what used to be the last element!** |
504 | /// |
505 | /// Computes in **O(1)** time (average). |
506 | pub fn swap_remove(self) -> V { |
507 | self.swap_remove_entry().1 |
508 | } |
509 | |
510 | /// Remove the key, value pair stored in the map for this entry, and return the value. |
511 | /// |
512 | /// Like [`Vec::remove`][crate::Vec::remove], the pair is removed by shifting all of the |
513 | /// elements that follow it, preserving their relative order. |
514 | /// **This perturbs the index of all of those elements!** |
515 | /// |
516 | /// Computes in **O(n)** time (average). |
517 | pub fn shift_remove(self) -> V { |
518 | self.shift_remove_entry().1 |
519 | } |
520 | |
521 | /// Remove and return the key, value pair stored in the map for this entry |
522 | /// |
523 | /// **NOTE:** This is equivalent to [`.swap_remove_entry()`][Self::swap_remove_entry], |
524 | /// replacing this entry's position with the last element, and it is deprecated in favor of |
525 | /// calling that explicitly. If you need to preserve the relative order of the keys in the map, |
526 | /// use [`.shift_remove_entry()`][Self::shift_remove_entry] instead. |
527 | #[deprecated (note = "`remove_entry` disrupts the map order -- \ |
528 | use `swap_remove_entry` or `shift_remove_entry` for explicit behavior." )] |
529 | pub fn remove_entry(self) -> (K, V) { |
530 | self.swap_remove_entry() |
531 | } |
532 | |
533 | /// Remove and return the key, value pair stored in the map for this entry |
534 | /// |
535 | /// Like [`Vec::swap_remove`][crate::Vec::swap_remove], the pair is removed by swapping it with |
536 | /// the last element of the map and popping it off. |
537 | /// **This perturbs the position of what used to be the last element!** |
538 | /// |
539 | /// Computes in **O(1)** time (average). |
540 | pub fn swap_remove_entry(self) -> (K, V) { |
541 | let (index, entry) = self.index.remove(); |
542 | RefMut::new(entry.into_table(), self.entries).swap_remove_finish(index) |
543 | } |
544 | |
545 | /// Remove and return the key, value pair stored in the map for this entry |
546 | /// |
547 | /// Like [`Vec::remove`][crate::Vec::remove], the pair is removed by shifting all of the |
548 | /// elements that follow it, preserving their relative order. |
549 | /// **This perturbs the index of all of those elements!** |
550 | /// |
551 | /// Computes in **O(n)** time (average). |
552 | pub fn shift_remove_entry(self) -> (K, V) { |
553 | let (index, entry) = self.index.remove(); |
554 | RefMut::new(entry.into_table(), self.entries).shift_remove_finish(index) |
555 | } |
556 | |
557 | /// Moves the position of the entry to a new index |
558 | /// by shifting all other entries in-between. |
559 | /// |
560 | /// This is equivalent to [`IndexMap::move_index`] |
561 | /// coming `from` the current [`.index()`][Self::index]. |
562 | /// |
563 | /// * If `self.index() < to`, the other pairs will shift down while the targeted pair moves up. |
564 | /// * If `self.index() > to`, the other pairs will shift up while the targeted pair moves down. |
565 | /// |
566 | /// ***Panics*** if `to` is out of bounds. |
567 | /// |
568 | /// Computes in **O(n)** time (average). |
569 | pub fn move_index(self, to: usize) { |
570 | let index = self.index(); |
571 | self.into_ref_mut().move_index(index, to); |
572 | } |
573 | |
574 | /// Swaps the position of entry with another. |
575 | /// |
576 | /// This is equivalent to [`IndexMap::swap_indices`] |
577 | /// with the current [`.index()`][Self::index] as one of the two being swapped. |
578 | /// |
579 | /// ***Panics*** if the `other` index is out of bounds. |
580 | /// |
581 | /// Computes in **O(1)** time (average). |
582 | pub fn swap_indices(self, other: usize) { |
583 | let index = self.index(); |
584 | self.into_ref_mut().swap_indices(index, other); |
585 | } |
586 | } |
587 | |
588 | /// A view into a vacant raw entry in an [`IndexMap`]. |
589 | /// It is part of the [`RawEntryMut`] enum. |
590 | pub struct RawVacantEntryMut<'a, K, V, S> { |
591 | map: RefMut<'a, K, V>, |
592 | hash_builder: &'a S, |
593 | } |
594 | |
595 | impl<K, V, S> fmt::Debug for RawVacantEntryMut<'_, K, V, S> { |
596 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
597 | f.debug_struct(name:"RawVacantEntryMut" ).finish_non_exhaustive() |
598 | } |
599 | } |
600 | |
601 | impl<'a, K, V, S> RawVacantEntryMut<'a, K, V, S> { |
602 | /// Return the index where a key-value pair may be inserted. |
603 | pub fn index(&self) -> usize { |
604 | self.map.indices.len() |
605 | } |
606 | |
607 | /// Inserts the given key and value into the map, |
608 | /// and returns mutable references to them. |
609 | pub fn insert(self, key: K, value: V) -> (&'a mut K, &'a mut V) |
610 | where |
611 | K: Hash, |
612 | S: BuildHasher, |
613 | { |
614 | let mut h = self.hash_builder.build_hasher(); |
615 | key.hash(&mut h); |
616 | self.insert_hashed_nocheck(h.finish(), key, value) |
617 | } |
618 | |
619 | /// Inserts the given key and value into the map with the provided hash, |
620 | /// and returns mutable references to them. |
621 | pub fn insert_hashed_nocheck(self, hash: u64, key: K, value: V) -> (&'a mut K, &'a mut V) { |
622 | let hash = HashValue(hash as usize); |
623 | self.map.insert_unique(hash, key, value).into_muts() |
624 | } |
625 | |
626 | /// Inserts the given key and value into the map at the given index, |
627 | /// shifting others to the right, and returns mutable references to them. |
628 | /// |
629 | /// ***Panics*** if `index` is out of bounds. |
630 | /// |
631 | /// Computes in **O(n)** time (average). |
632 | pub fn shift_insert(self, index: usize, key: K, value: V) -> (&'a mut K, &'a mut V) |
633 | where |
634 | K: Hash, |
635 | S: BuildHasher, |
636 | { |
637 | let mut h = self.hash_builder.build_hasher(); |
638 | key.hash(&mut h); |
639 | self.shift_insert_hashed_nocheck(index, h.finish(), key, value) |
640 | } |
641 | |
642 | /// Inserts the given key and value into the map with the provided hash |
643 | /// at the given index, and returns mutable references to them. |
644 | /// |
645 | /// ***Panics*** if `index` is out of bounds. |
646 | /// |
647 | /// Computes in **O(n)** time (average). |
648 | pub fn shift_insert_hashed_nocheck( |
649 | mut self, |
650 | index: usize, |
651 | hash: u64, |
652 | key: K, |
653 | value: V, |
654 | ) -> (&'a mut K, &'a mut V) { |
655 | let hash = HashValue(hash as usize); |
656 | self.map.shift_insert_unique(index, hash, key, value); |
657 | self.map.entries[index].muts() |
658 | } |
659 | } |
660 | |
661 | mod private { |
662 | pub trait Sealed {} |
663 | |
664 | impl<K, V, S> Sealed for super::IndexMap<K, V, S> {} |
665 | } |
666 | |