Coverage Report

Created: 2026-10-28 06:53

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