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