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}