indexmap/map/entry.rs
1use core::{fmt, mem};
2
3use crate::{
4 Bucket,
5 inner::{Core, OccupiedEntry, VacantEntry},
6};
7
8/// Entry for an existing key-value pair in an [`IndexMap`][crate::IndexMap]
9/// or a vacant location to insert one.
10pub enum Entry<'a, K, V> {
11 /// Existing slot with equivalent key.
12 Occupied(OccupiedEntry<'a, K, V>),
13 /// Vacant slot (no equivalent key in the map).
14 Vacant(VacantEntry<'a, K, V>),
15}
16
17impl<'a, K, V> Entry<'a, K, V> {
18 /// Return the index where the key-value pair exists or will be inserted.
19 pub fn index(&self) -> usize {
20 match self {
21 Entry::Occupied(entry) => entry.index(),
22 Entry::Vacant(entry) => entry.index(),
23 }
24 }
25
26 /// Sets the value of the entry (after inserting if vacant), and returns an `OccupiedEntry`.
27 ///
28 /// Computes in **O(1)** time (amortized average).
29 pub fn insert_entry(self, value: V) -> OccupiedEntry<'a, K, V> {
30 match self {
31 Entry::Occupied(mut entry) => {
32 entry.insert(value);
33 entry
34 }
35 Entry::Vacant(entry) => entry.insert_entry(value),
36 }
37 }
38
39 /// Inserts the given default value in the entry if it is vacant and returns a mutable
40 /// reference to it. Otherwise a mutable reference to an already existent value is returned.
41 ///
42 /// Computes in **O(1)** time (amortized average).
43 pub fn or_insert(self, default: V) -> &'a mut V {
44 match self {
45 Entry::Occupied(entry) => entry.into_mut(),
46 Entry::Vacant(entry) => entry.insert(default),
47 }
48 }
49
50 /// Inserts the result of the `call` function in the entry if it is vacant and returns a mutable
51 /// reference to it. Otherwise a mutable reference to an already existent value is returned.
52 ///
53 /// Computes in **O(1)** time (amortized average).
54 pub fn or_insert_with<F>(self, call: F) -> &'a mut V
55 where
56 F: FnOnce() -> V,
57 {
58 match self {
59 Entry::Occupied(entry) => entry.into_mut(),
60 Entry::Vacant(entry) => entry.insert(call()),
61 }
62 }
63
64 /// Inserts the result of the `call` function with a reference to the entry's key if it is
65 /// vacant, and returns a mutable reference to the new value. Otherwise a mutable reference to
66 /// an already existent value is returned.
67 ///
68 /// Computes in **O(1)** time (amortized average).
69 pub fn or_insert_with_key<F>(self, call: F) -> &'a mut V
70 where
71 F: FnOnce(&K) -> V,
72 {
73 match self {
74 Entry::Occupied(entry) => entry.into_mut(),
75 Entry::Vacant(entry) => {
76 let value = call(entry.key());
77 entry.insert(value)
78 }
79 }
80 }
81
82 /// Gets a reference to the entry's key, either within the map if occupied,
83 /// or else the new key that was used to find the entry.
84 pub fn key(&self) -> &K {
85 match *self {
86 Entry::Occupied(ref entry) => entry.key(),
87 Entry::Vacant(ref entry) => entry.key(),
88 }
89 }
90
91 /// Modifies the entry if it is occupied.
92 pub fn and_modify<F>(mut self, f: F) -> Self
93 where
94 F: FnOnce(&mut V),
95 {
96 if let Entry::Occupied(entry) = &mut self {
97 f(entry.get_mut());
98 }
99 self
100 }
101
102 /// Inserts a default-constructed value in the entry if it is vacant and returns a mutable
103 /// reference to it. Otherwise a mutable reference to an already existent value is returned.
104 ///
105 /// Computes in **O(1)** time (amortized average).
106 pub fn or_default(self) -> &'a mut V
107 where
108 V: Default,
109 {
110 match self {
111 Entry::Occupied(entry) => entry.into_mut(),
112 Entry::Vacant(entry) => entry.insert(V::default()),
113 }
114 }
115}
116
117impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for Entry<'_, K, V> {
118 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
119 let mut tuple = f.debug_tuple("Entry");
120 match self {
121 Entry::Vacant(v) => tuple.field(v),
122 Entry::Occupied(o) => tuple.field(o),
123 };
124 tuple.finish()
125 }
126}
127
128impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for OccupiedEntry<'_, K, V> {
129 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
130 f.debug_struct("OccupiedEntry")
131 .field("key", self.key())
132 .field("value", self.get())
133 .finish()
134 }
135}
136
137impl<K: fmt::Debug, V> fmt::Debug for VacantEntry<'_, K, V> {
138 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
139 f.debug_tuple("VacantEntry").field(self.key()).finish()
140 }
141}
142
143/// A view into an occupied entry in an [`IndexMap`][crate::IndexMap] obtained by index.
144///
145/// This `struct` is created from the [`get_index_entry`][crate::IndexMap::get_index_entry] method.
146pub struct IndexedEntry<'a, K, V> {
147 map: &'a mut Core<K, V>,
148 // We have a mutable reference to the map, which keeps the index
149 // valid and pointing to the correct entry.
150 index: usize,
151}
152
153impl<'a, K, V> IndexedEntry<'a, K, V> {
154 pub(crate) fn new(map: &'a mut Core<K, V>, index: usize) -> Option<Self> {
155 if index < map.len() {
156 Some(Self {
157 map,
158 index,
159 })
160 } else {
161 None
162 }
163 }
164
165 /// Return the index of the key-value pair
166 #[inline]
167 pub fn index(&self) -> usize {
168 self.index
169 }
170
171 pub(crate) fn into_core(self) -> &'a mut Core<K, V> {
172 self.map
173 }
174
175 fn get_bucket(&self) -> &Bucket<K, V> {
176 &self.map.as_entries()[self.index]
177 }
178
179 fn get_bucket_mut(&mut self) -> &mut Bucket<K, V> {
180 &mut self.map.as_entries_mut()[self.index]
181 }
182
183 fn into_bucket(self) -> &'a mut Bucket<K, V> {
184 &mut self.map.as_entries_mut()[self.index]
185 }
186
187 /// Gets a reference to the entry's key in the map.
188 pub fn key(&self) -> &K {
189 &self.get_bucket().key
190 }
191
192 pub(super) fn key_mut(&mut self) -> &mut K {
193 &mut self.get_bucket_mut().key
194 }
195
196 /// Gets a reference to the entry's value in the map.
197 pub fn get(&self) -> &V {
198 &self.get_bucket().value
199 }
200
201 /// Gets a mutable reference to the entry's value in the map.
202 ///
203 /// If you need a reference which may outlive the destruction of the
204 /// `IndexedEntry` value, see [`into_mut`][Self::into_mut].
205 pub fn get_mut(&mut self) -> &mut V {
206 &mut self.get_bucket_mut().value
207 }
208
209 /// Sets the value of the entry to `value`, and returns the entry's old value.
210 pub fn insert(&mut self, value: V) -> V {
211 mem::replace(self.get_mut(), value)
212 }
213
214 /// Converts into a mutable reference to the entry's value in the map,
215 /// with a lifetime bound to the map itself.
216 pub fn into_mut(self) -> &'a mut V {
217 &mut self.into_bucket().value
218 }
219
220 /// Remove and return the key, value pair stored in the map for this entry
221 ///
222 /// Like [`Vec::swap_remove`][alloc::vec::Vec::swap_remove], the pair is removed by swapping it
223 /// with the last element of the map and popping it off.
224 /// **This perturbs the position of what used to be the last element!**
225 ///
226 /// Computes in **O(1)** time (average).
227 pub fn swap_remove_entry(self) -> (K, V) {
228 self.map.swap_remove_index(self.index).unwrap()
229 }
230
231 /// Remove and return the key, value pair stored in the map for this entry
232 ///
233 /// Like [`Vec::remove`][alloc::vec::Vec::remove], the pair is removed by shifting all of the
234 /// elements that follow it, preserving their relative order.
235 /// **This perturbs the index of all of those elements!**
236 ///
237 /// Computes in **O(n)** time (average).
238 pub fn shift_remove_entry(self) -> (K, V) {
239 self.map.shift_remove_index(self.index).unwrap()
240 }
241
242 /// Remove the key, value pair stored in the map for this entry, and return the value.
243 ///
244 /// Like [`Vec::swap_remove`][alloc::vec::Vec::swap_remove], the pair is removed by swapping it
245 /// with the last element of the map and popping it off.
246 /// **This perturbs the position of what used to be the last element!**
247 ///
248 /// Computes in **O(1)** time (average).
249 pub fn swap_remove(self) -> V {
250 self.swap_remove_entry().1
251 }
252
253 /// Remove the key, value pair stored in the map for this entry, and return the value.
254 ///
255 /// Like [`Vec::remove`][alloc::vec::Vec::remove], the pair is removed by shifting all of the
256 /// elements that follow it, preserving their relative order.
257 /// **This perturbs the index of all of those elements!**
258 ///
259 /// Computes in **O(n)** time (average).
260 pub fn shift_remove(self) -> V {
261 self.shift_remove_entry().1
262 }
263
264 /// Moves the position of the entry to a new index
265 /// by shifting all other entries in-between.
266 ///
267 /// This is equivalent to [`IndexMap::move_index`][`crate::IndexMap::move_index`]
268 /// coming `from` the current [`.index()`][Self::index].
269 ///
270 /// * If `self.index() < to`, the other pairs will shift down while the targeted pair moves up.
271 /// * If `self.index() > to`, the other pairs will shift up while the targeted pair moves down.
272 ///
273 /// ***Panics*** if `to` is out of bounds.
274 ///
275 /// Computes in **O(n)** time (average).
276 #[track_caller]
277 pub fn move_index(self, to: usize) {
278 self.map.move_index(self.index, to);
279 }
280
281 /// Swaps the position of entry with another.
282 ///
283 /// This is equivalent to [`IndexMap::swap_indices`][`crate::IndexMap::swap_indices`]
284 /// with the current [`.index()`][Self::index] as one of the two being swapped.
285 ///
286 /// ***Panics*** if the `other` index is out of bounds.
287 ///
288 /// Computes in **O(1)** time (average).
289 #[track_caller]
290 pub fn swap_indices(self, other: usize) {
291 self.map.swap_indices(self.index, other);
292 }
293}
294
295impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for IndexedEntry<'_, K, V> {
296 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
297 f.debug_struct("IndexedEntry")
298 .field("index", &self.index)
299 .field("key", self.key())
300 .field("value", self.get())
301 .finish()
302 }
303}
304
305impl<'a, K, V> From<OccupiedEntry<'a, K, V>> for IndexedEntry<'a, K, V> {
306 fn from(other: OccupiedEntry<'a, K, V>) -> Self {
307 Self {
308 index: other.index(),
309 map: other.into_core(),
310 }
311 }
312}
313
314#[test]
315fn assert_send_sync() {
316 fn assert_send_sync<T: Send + Sync>() {}
317 assert_send_sync::<Entry<'_, i32, i32>>();
318 assert_send_sync::<IndexedEntry<'_, i32, i32>>();
319}