indexmap/inner/entry.rs
1use core::{cmp::Ordering, mem};
2
3use super::{Bucket, Core, equal, get_hash};
4use crate::{
5 HashValue,
6 map::{Entry, IndexedEntry},
7 util::assert_index_lt,
8};
9
10impl<'a, K, V> Entry<'a, K, V> {
11 pub(crate) fn new(map: &'a mut Core<K, V>, hash: HashValue, key: K) -> Self
12 where
13 K: Eq,
14 {
15 let eq = equal(&key, &map.entries);
16 match map.indices.find_entry(hash.get(), eq) {
17 Ok(entry) => Entry::Occupied(OccupiedEntry {
18 bucket: entry.bucket_index(),
19 index: *entry.get(),
20 map,
21 }),
22 Err(_) => Entry::Vacant(VacantEntry {
23 map,
24 hash,
25 key,
26 }),
27 }
28 }
29}
30
31/// A view into an occupied entry in an [`IndexMap`][crate::IndexMap].
32/// It is part of the [`Entry`] enum.
33pub struct OccupiedEntry<'a, K, V> {
34 map: &'a mut Core<K, V>,
35 // We have a mutable reference to the map, which keeps these two
36 // indices valid and pointing to the correct entry.
37 index: usize,
38 bucket: usize,
39}
40
41impl<'a, K, V> OccupiedEntry<'a, K, V> {
42 /// Constructor for `RawEntryMut::from_hash`
43 pub(crate) fn from_hash<F>(
44 map: &'a mut Core<K, V>,
45 hash: HashValue,
46 mut is_match: F,
47 ) -> Result<Self, &'a mut Core<K, V>>
48 where
49 F: FnMut(&K) -> bool,
50 {
51 let entries = &*map.entries;
52 let eq = move |&i: &usize| is_match(&entries[i].key);
53 match map.indices.find_entry(hash.get(), eq) {
54 Ok(entry) => Ok(OccupiedEntry {
55 bucket: entry.bucket_index(),
56 index: *entry.get(),
57 map,
58 }),
59 Err(_) => Err(map),
60 }
61 }
62
63 pub(crate) fn into_core(self) -> &'a mut Core<K, V> {
64 self.map
65 }
66
67 pub(crate) fn get_bucket(&self) -> &Bucket<K, V> {
68 &self.map.entries[self.index]
69 }
70
71 pub(crate) fn get_bucket_mut(&mut self) -> &mut Bucket<K, V> {
72 &mut self.map.entries[self.index]
73 }
74
75 pub(crate) fn into_bucket(self) -> &'a mut Bucket<K, V> {
76 &mut self.map.entries[self.index]
77 }
78
79 /// Return the index of the key-value pair
80 #[inline]
81 pub fn index(&self) -> usize {
82 self.index
83 }
84
85 /// Gets a reference to the entry's key in the map.
86 ///
87 /// Note that this is not the key that was used to find the entry. There may be an observable
88 /// difference if the key type has any distinguishing features outside of `Hash` and `Eq`, like
89 /// extra fields or the memory address of an allocation.
90 pub fn key(&self) -> &K {
91 &self.get_bucket().key
92 }
93
94 /// Gets a reference to the entry's value in the map.
95 pub fn get(&self) -> &V {
96 &self.get_bucket().value
97 }
98
99 /// Gets a mutable reference to the entry's value in the map.
100 ///
101 /// If you need a reference which may outlive the destruction of the
102 /// [`Entry`] value, see [`into_mut`][Self::into_mut].
103 pub fn get_mut(&mut self) -> &mut V {
104 &mut self.get_bucket_mut().value
105 }
106
107 /// Converts into a mutable reference to the entry's value in the map,
108 /// with a lifetime bound to the map itself.
109 pub fn into_mut(self) -> &'a mut V {
110 &mut self.into_bucket().value
111 }
112
113 /// Sets the value of the entry to `value`, and returns the entry's old value.
114 pub fn insert(&mut self, value: V) -> V {
115 mem::replace(self.get_mut(), value)
116 }
117
118 /// Remove the key, value pair stored in the map for this entry, and return the value.
119 ///
120 /// **NOTE:** This is equivalent to [`.swap_remove()`][Self::swap_remove], replacing this
121 /// entry's position with the last element, and it is deprecated in favor of calling that
122 /// explicitly. If you need to preserve the relative order of the keys in the map, use
123 /// [`.shift_remove()`][Self::shift_remove] instead.
124 #[deprecated(note = "`remove` disrupts the map order -- \
125 use `swap_remove` or `shift_remove` for explicit behavior.")]
126 pub fn remove(self) -> V {
127 self.swap_remove()
128 }
129
130 /// Remove the key, value pair stored in the map for this entry, and return the value.
131 ///
132 /// Like [`Vec::swap_remove`][alloc::vec::Vec::swap_remove], the pair is removed by swapping it
133 /// with the last element of the map and popping it off.
134 /// **This perturbs the position of what used to be the last element!**
135 ///
136 /// Computes in **O(1)** time (average).
137 pub fn swap_remove(self) -> V {
138 self.swap_remove_entry().1
139 }
140
141 /// Remove the key, value pair stored in the map for this entry, and return the value.
142 ///
143 /// Like [`Vec::remove`][alloc::vec::Vec::remove], the pair is removed by shifting all of the
144 /// elements that follow it, preserving their relative order.
145 /// **This perturbs the index of all of those elements!**
146 ///
147 /// Computes in **O(n)** time (average).
148 pub fn shift_remove(self) -> V {
149 self.shift_remove_entry().1
150 }
151
152 /// Remove and return the key, value pair stored in the map for this entry
153 ///
154 /// **NOTE:** This is equivalent to [`.swap_remove_entry()`][Self::swap_remove_entry],
155 /// replacing this entry's position with the last element, and it is deprecated in favor of
156 /// calling that explicitly. If you need to preserve the relative order of the keys in the map,
157 /// use [`.shift_remove_entry()`][Self::shift_remove_entry] instead.
158 #[deprecated(note = "`remove_entry` disrupts the map order -- \
159 use `swap_remove_entry` or `shift_remove_entry` for explicit behavior.")]
160 pub fn remove_entry(self) -> (K, V) {
161 self.swap_remove_entry()
162 }
163
164 /// Remove and return the key, value pair stored in the map for this entry
165 ///
166 /// Like [`Vec::swap_remove`][alloc::vec::Vec::swap_remove], the pair is removed by swapping it
167 /// with the last element of the map and popping it off.
168 /// **This perturbs the position of what used to be the last element!**
169 ///
170 /// Computes in **O(1)** time (average).
171 pub fn swap_remove_entry(mut self) -> (K, V) {
172 self.remove_index();
173 self.map.swap_remove_finish(self.index)
174 }
175
176 /// Remove and return the key, value pair stored in the map for this entry
177 ///
178 /// Like [`Vec::remove`][alloc::vec::Vec::remove], the pair is removed by shifting all of the
179 /// elements that follow it, preserving their relative order.
180 /// **This perturbs the index of all of those elements!**
181 ///
182 /// Computes in **O(n)** time (average).
183 pub fn shift_remove_entry(mut self) -> (K, V) {
184 self.remove_index();
185 self.map.shift_remove_finish(self.index)
186 }
187
188 fn remove_index(&mut self) {
189 let entry = self.map.indices.get_bucket_entry(self.bucket).unwrap();
190 debug_assert_eq!(*entry.get(), self.index);
191 entry.remove();
192 }
193
194 /// Moves the position of the entry to a new index
195 /// by shifting all other entries in-between.
196 ///
197 /// This is equivalent to [`IndexMap::move_index`][`crate::IndexMap::move_index`]
198 /// coming `from` the current [`.index()`][Self::index].
199 ///
200 /// * If `self.index() < to`, the other pairs will shift down while the targeted pair moves up.
201 /// * If `self.index() > to`, the other pairs will shift up while the targeted pair moves down.
202 ///
203 /// ***Panics*** if `to` is out of bounds.
204 ///
205 /// Computes in **O(n)** time (average).
206 #[track_caller]
207 pub fn move_index(self, to: usize) {
208 if self.index != to {
209 assert_index_lt(to, self.map.len());
210 self.map.move_index_inner(self.index, to);
211 self.update_index(to);
212 }
213 }
214
215 /// Swaps the position of entry with another.
216 ///
217 /// This is equivalent to [`IndexMap::swap_indices`][`crate::IndexMap::swap_indices`]
218 /// with the current [`.index()`][Self::index] as one of the two being swapped.
219 ///
220 /// ***Panics*** if the `other` index is out of bounds.
221 ///
222 /// Computes in **O(1)** time (average).
223 #[track_caller]
224 pub fn swap_indices(self, other: usize) {
225 if self.index != other {
226 assert_index_lt(other, self.map.len());
227
228 // Since we already know where our bucket is, we only need to find the other.
229 let hash = self.map.entries[other].hash;
230 let other_mut = self.map.indices.find_mut(hash.get(), move |&i| i == other);
231 *other_mut.expect("index not found") = self.index;
232
233 self.map.entries.swap(self.index, other);
234 self.update_index(other);
235 }
236 }
237
238 fn update_index(self, to: usize) {
239 let index = self.map.indices.get_bucket_mut(self.bucket).unwrap();
240 debug_assert_eq!(*index, self.index);
241 *index = to;
242 }
243}
244
245impl<'a, K, V> From<IndexedEntry<'a, K, V>> for OccupiedEntry<'a, K, V> {
246 fn from(other: IndexedEntry<'a, K, V>) -> Self {
247 let index = other.index();
248 let map = other.into_core();
249 let hash = map.entries[index].hash;
250 let bucket = map
251 .indices
252 .find_bucket_index(hash.get(), move |&i| i == index)
253 .expect("index not found");
254 Self {
255 map,
256 index,
257 bucket,
258 }
259 }
260}
261
262/// A view into a vacant entry in an [`IndexMap`][crate::IndexMap].
263/// It is part of the [`Entry`] enum.
264pub struct VacantEntry<'a, K, V> {
265 map: &'a mut Core<K, V>,
266 hash: HashValue,
267 key: K,
268}
269
270impl<'a, K, V> VacantEntry<'a, K, V> {
271 /// Return the index where a key-value pair may be inserted.
272 pub fn index(&self) -> usize {
273 self.map.indices.len()
274 }
275
276 /// Gets a reference to the key that was used to find the entry.
277 pub fn key(&self) -> &K {
278 &self.key
279 }
280
281 pub(crate) fn key_mut(&mut self) -> &mut K {
282 &mut self.key
283 }
284
285 /// Takes ownership of the key, leaving the entry vacant.
286 pub fn into_key(self) -> K {
287 self.key
288 }
289
290 /// Inserts the entry's key and the given value into the map, and returns a mutable reference
291 /// to the value.
292 ///
293 /// Computes in **O(1)** time (amortized average).
294 pub fn insert(self, value: V) -> &'a mut V {
295 let Self {
296 map,
297 hash,
298 key,
299 } = self;
300 map.insert_unique(hash, key, value).value_mut()
301 }
302
303 /// Inserts the entry's key and the given value into the map, and returns an `OccupiedEntry`.
304 ///
305 /// Computes in **O(1)** time (amortized average).
306 pub fn insert_entry(self, value: V) -> OccupiedEntry<'a, K, V> {
307 let Self {
308 map,
309 hash,
310 key,
311 } = self;
312 let index = map.indices.len();
313 debug_assert_eq!(index, map.entries.len());
314 let bucket = map
315 .indices
316 .insert_unique(hash.get(), index, get_hash(&map.entries))
317 .bucket_index();
318 map.push_entry(hash, key, value);
319 OccupiedEntry {
320 map,
321 index,
322 bucket,
323 }
324 }
325
326 /// Inserts the entry's key and the given value into the map at its ordered
327 /// position among sorted keys, and returns the new index and a mutable
328 /// reference to the value.
329 ///
330 /// If the existing keys are **not** already sorted, then the insertion
331 /// index is unspecified (like [`slice::binary_search`]), but the key-value
332 /// pair is inserted at that position regardless.
333 ///
334 /// Computes in **O(n)** time (average).
335 pub fn insert_sorted(self, value: V) -> (usize, &'a mut V)
336 where
337 K: Ord,
338 {
339 let slice = crate::map::Slice::from_slice(&self.map.entries);
340 let i = slice.binary_search_keys(&self.key).unwrap_err();
341 (i, self.shift_insert(i, value))
342 }
343
344 /// Inserts the entry's key and the given value into the map at its ordered
345 /// position among keys sorted by `cmp`, and returns the new index and a
346 /// mutable reference to the value.
347 ///
348 /// If the existing keys are **not** already sorted, then the insertion
349 /// index is unspecified (like [`slice::binary_search`]), but the key-value
350 /// pair is inserted at that position regardless.
351 ///
352 /// Computes in **O(n)** time (average).
353 pub fn insert_sorted_by<F>(self, value: V, mut cmp: F) -> (usize, &'a mut V)
354 where
355 F: FnMut(&K, &V, &K, &V) -> Ordering,
356 {
357 let slice = crate::map::Slice::from_slice(&self.map.entries);
358 let (Ok(i) | Err(i)) = slice.binary_search_by(|k, v| cmp(k, v, &self.key, &value));
359 (i, self.shift_insert(i, value))
360 }
361
362 /// Inserts the entry's key and the given value into the map at its ordered
363 /// position using a sort-key extraction function, and returns the new index
364 /// and a mutable reference to the value.
365 ///
366 /// If the existing keys are **not** already sorted, then the insertion
367 /// index is unspecified (like [`slice::binary_search`]), but the key-value
368 /// pair is inserted at that position regardless.
369 ///
370 /// Computes in **O(n)** time (average).
371 pub fn insert_sorted_by_key<B, F>(self, value: V, mut sort_key: F) -> (usize, &'a mut V)
372 where
373 B: Ord,
374 F: FnMut(&K, &V) -> B,
375 {
376 let search_key = sort_key(&self.key, &value);
377 let slice = crate::map::Slice::from_slice(&self.map.entries);
378 let (Ok(i) | Err(i)) = slice.binary_search_by_key(&search_key, sort_key);
379 (i, self.shift_insert(i, value))
380 }
381
382 /// Inserts the entry's key and the given value into the map at the given index,
383 /// shifting others to the right, and returns a mutable reference to the value.
384 ///
385 /// ***Panics*** if `index` is out of bounds.
386 ///
387 /// Computes in **O(n)** time (average).
388 #[track_caller]
389 pub fn shift_insert(self, index: usize, value: V) -> &'a mut V {
390 self.map
391 .shift_insert_unique(index, self.hash, self.key, value)
392 .value_mut()
393 }
394
395 /// Replaces the key at the given index with this entry's key, returning the
396 /// old key and an `OccupiedEntry` for that index.
397 ///
398 /// ***Panics*** if `index` is out of bounds.
399 ///
400 /// Computes in **O(1)** time (average).
401 #[track_caller]
402 pub fn replace_index(self, index: usize) -> (K, OccupiedEntry<'a, K, V>) {
403 let Self {
404 map,
405 hash,
406 key,
407 } = self;
408 assert_index_lt(index, map.len());
409
410 // NB: This removal and insertion isn't "no grow" (with unreachable hasher)
411 // because hashbrown's tombstones might force a resize anyway.
412 let old_hash = map.entries[index].hash;
413 map.indices
414 .find_entry(old_hash.get(), move |&i| i == index)
415 .expect("index not found")
416 .remove();
417 let bucket = map
418 .indices
419 .insert_unique(hash.get(), index, get_hash(&map.entries))
420 .bucket_index();
421
422 let entry = &mut map.entries[index];
423 entry.hash = hash;
424 let old_key = mem::replace(&mut entry.key, key);
425
426 (
427 old_key,
428 OccupiedEntry {
429 map,
430 index,
431 bucket,
432 },
433 )
434 }
435}