Skip to main content

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}