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