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}