/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 | | } |