mule_map/mule_map/
entry.rs

1use super::key::PrimInt;
2use Entry::{Occupied, Vacant};
3
4/// A view into a single entry in a map, which may either be vacant or occupied.
5///
6/// This enum is constructed from the entry method on [`crate::MuleMap`].
7///
8/// Analogous to [`std::collections::hash_map::Entry`]
9pub enum Entry<'a, K: 'a, V: 'a> {
10    Occupied(OccupiedEntry<'a, K, V>),
11    Vacant(VacantEntry<'a, K, V>),
12}
13
14pub enum OccupiedEntry<'a, K: 'a, V: 'a> {
15    HashMap(OccupiedHashMapEntry<'a, K, V>),
16    Vec(OccupiedVecEntry<'a, K, V>),
17}
18
19pub enum VacantEntry<'a, K: 'a, V: 'a> {
20    HashMap(VacantHashMapEntry<'a, K, V>),
21    Vec(VacantVecEntry<'a, K, V>),
22}
23
24#[derive(Debug)]
25pub struct OccupiedHashMapEntry<'a, K: 'a, V: 'a> {
26    pub(crate) base: std::collections::hash_map::OccupiedEntry<'a, K, V>,
27}
28
29#[derive(Debug)]
30pub struct OccupiedVecEntry<'a, K: 'a, V: 'a> {
31    pub(crate) value: &'a mut Option<V>,
32    pub(crate) key: K,
33}
34
35#[derive(Debug)]
36pub struct VacantHashMapEntry<'a, K: 'a, V: 'a> {
37    pub(crate) base: std::collections::hash_map::VacantEntry<'a, K, V>,
38}
39
40#[derive(Debug)]
41pub struct VacantVecEntry<'a, K: 'a, V: 'a> {
42    pub(crate) value: &'a mut Option<V>,
43    pub(crate) key: K,
44}
45
46impl<'a, K, V> Entry<'a, K, V>
47where
48    K: PrimInt,
49    V: PartialEq,
50{
51    /// Ensures a value is in the entry by inserting the default if empty, and returns a mutable reference to the value
52    /// in the entry.
53    ///
54    /// # Example
55    /// ```
56    /// let mut mule_map = mule_map::MuleMap::<u32, usize, fnv_rs::FnvBuildHasher>::new();
57    /// mule_map.entry(5).or_insert(3);
58    /// ```
59    ///
60    /// Analogous to [`std::collections::hash_map::Entry::or_insert`]
61    #[inline]
62    pub fn or_insert(self, default: V) -> &'a mut V {
63        match self {
64            Occupied(entry) => entry.into_mut(),
65            Vacant(entry) => entry.insert(default),
66        }
67    }
68
69    /// Ensures a value is in the entry by inserting the result of the default function if empty, and returns a mutable
70    /// reference to the value in the entry.
71    ///
72    /// # Example
73    /// ```
74    /// let mut mule_map = mule_map::MuleMap::<u32, usize, fnv_rs::FnvBuildHasher>::new();
75    /// mule_map.entry(5).or_insert_with(|| 1 + 1);
76    /// ```
77    ///
78    /// Analogous to [`std::collections::hash_map::Entry::or_insert_with`]
79    #[inline]
80    pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V {
81        match self {
82            Occupied(entry) => entry.into_mut(),
83            Vacant(entry) => entry.insert(default()),
84        }
85    }
86
87    /// Ensures a value is in the entry by inserting, if empty, the result of the default function.
88    ///
89    /// # Example
90    /// ```
91    /// let mut mule_map = mule_map::MuleMap::<u32, usize, fnv_rs::FnvBuildHasher>::new();
92    /// mule_map.entry(5).or_insert_with_key(|key| key as usize + 1);
93    /// ```
94    ///
95    /// Analogous to [`std::collections::hash_map::Entry::or_insert_with_key`]
96    #[inline]
97    pub fn or_insert_with_key<F: FnOnce(K) -> V>(self, default: F) -> &'a mut V {
98        match self {
99            Occupied(entry) => entry.into_mut(),
100            Vacant(entry) => {
101                let value = default(entry.key());
102                entry.insert(value)
103            }
104        }
105    }
106
107    /// Returns this entry’s key.
108    ///
109    /// # Example
110    /// ```
111    /// let mut mule_map = mule_map::MuleMap::<u32, usize, fnv_rs::FnvBuildHasher>::new();
112    /// assert_eq!(mule_map.entry(5).key(), 5);
113    /// ```
114    ///
115    /// Analogous to [`std::collections::hash_map::Entry::key`]
116    #[inline]
117    #[must_use]
118    pub fn key(&self) -> K {
119        match *self {
120            Occupied(ref entry) => entry.key(),
121            Vacant(ref entry) => entry.key(),
122        }
123    }
124
125    /// Provides in-place mutable access to an occupied entry before any potential inserts into the map.
126    ///
127    /// # Example
128    /// ```
129    /// let mut mule_map = mule_map::MuleMap::<u32, usize, fnv_rs::FnvBuildHasher>::new();
130    /// mule_map.entry(5).and_modify(|e| *e += 1).or_insert(1);
131    /// ```
132    ///
133    /// Analogous to [`std::collections::hash_map::Entry::and_modify`]
134    #[inline]
135    #[allow(clippy::return_self_not_must_use)]
136    pub fn and_modify<F>(self, f: F) -> Self
137    where
138        F: FnOnce(&mut V),
139    {
140        match self {
141            Occupied(mut entry) => {
142                f(entry.get_mut());
143                Occupied(entry)
144            }
145            Vacant(entry) => Vacant(entry),
146        }
147    }
148
149    /// Sets the value of the entry, and returns an [`OccupiedEntry`].
150    ///
151    /// # Example
152    /// ```
153    /// let mut mule_map = mule_map::MuleMap::<u32, usize, fnv_rs::FnvBuildHasher>::new();
154    /// let entry = mule_map.entry(5).insert_entry(10);
155    /// ```
156    ///
157    /// Analogous to [`std::collections::hash_map::Entry::insert_entry`]
158    #[inline]
159    pub fn insert_entry(self, value: V) -> OccupiedEntry<'a, K, V> {
160        match self {
161            Occupied(mut entry) => {
162                entry.insert(value);
163                entry
164            }
165            Vacant(entry) => entry.insert_entry(value),
166        }
167    }
168}
169
170impl<'a, K, V> OccupiedEntry<'a, K, V>
171where
172    K: PrimInt,
173    V: PartialEq,
174{
175    /// Returns this entry’s key.
176    ///
177    /// # Example
178    /// ```
179    /// let mut mule_map = mule_map::MuleMap::<u32, usize, fnv_rs::FnvBuildHasher>::new();
180    /// mule_map.entry(5).or_insert(12);
181    /// assert_eq!(mule_map.entry(5).key(), 5);
182    /// ```
183    ///
184    /// Analogous to [`std::collections::hash_map::OccupiedEntry::key`]
185    #[inline]
186    #[must_use]
187    pub fn key(&self) -> K {
188        match self {
189            OccupiedEntry::HashMap(entry) => *entry.base.key(),
190            OccupiedEntry::Vec(entry) => entry.key(),
191        }
192    }
193
194    /// Take the ownership of the key and value from the map.
195    ///
196    /// # Example
197    /// ```
198    /// let mut mule_map = mule_map::MuleMap::<u32, usize, fnv_rs::FnvBuildHasher>::new();
199    /// mule_map.entry(5).or_insert(12);
200    /// if let mule_map::Entry::Occupied(o) = mule_map.entry(5) {
201    ///    o.remove_entry();
202    /// }
203    ///
204    /// assert_eq!(mule_map.contains_key(5), false);
205    /// ```
206    ///
207    /// Analogous to [`std::collections::hash_map::OccupiedEntry::remove_entry`]
208    #[inline]
209    pub fn remove_entry(self) -> (K, V)
210    where
211        V: Clone,
212    {
213        match self {
214            OccupiedEntry::HashMap(entry) => entry.base.remove_entry(),
215            OccupiedEntry::Vec(entry) => entry.remove_entry(),
216        }
217    }
218
219    /// Gets a reference to the value in the entry.
220    ///
221    /// # Example
222    /// ```
223    /// let mut mule_map = mule_map::MuleMap::<u32, usize, fnv_rs::FnvBuildHasher>::new();
224    /// mule_map.entry(5).or_insert(12);
225    /// if let mule_map::Entry::Occupied(o) = mule_map.entry(5) {
226    ///    assert_eq!(o.get(), &12);
227    /// }
228    /// ```
229    ///
230    /// Analogous to [`std::collections::hash_map::OccupiedEntry::get`]
231    #[inline]
232    #[must_use]
233    pub fn get(&self) -> &V {
234        match self {
235            OccupiedEntry::HashMap(entry) => entry.base.get(),
236            OccupiedEntry::Vec(entry) => entry.get(),
237        }
238    }
239
240    /// Gets a mutable reference to the value in the entry.
241    ///
242    /// If you need a reference to the [`OccupiedEntry`] which may outlive the destruction of the [`Entry`] value, see
243    /// [`OccupiedEntry::into_mut`].
244    ///
245    /// # Example
246    /// ```
247    /// let mut mule_map = mule_map::MuleMap::<u32, usize, fnv_rs::FnvBuildHasher>::new();
248    /// mule_map.entry(5).or_insert(12);
249    /// if let mule_map::Entry::Occupied(mut o) = mule_map.entry(5) {
250    ///     *o.get_mut() += 10;
251    ///     assert_eq!(o.get(), &22);
252    ///     *o.get_mut() += 2;
253    /// }
254    /// assert_eq!(mule_map.get(5), Some(&24));
255    /// ```
256    ///
257    /// Analogous to [`std::collections::hash_map::OccupiedEntry::get_mut`]
258    #[inline]
259    #[must_use]
260    pub fn get_mut(&mut self) -> &mut V {
261        match self {
262            OccupiedEntry::HashMap(entry) => entry.base.get_mut(),
263            OccupiedEntry::Vec(entry) => entry.get_mut(),
264        }
265    }
266
267    /// Converts the [`OccupiedEntry`] into a mutable reference to the value in the entry with a lifetime bound to the
268    /// map itself.
269    ///
270    /// If you need multiple references to the [`OccupiedEntry`], see [`OccupiedEntry::get_mut`].
271    ///
272    /// # Example
273    /// ```
274    /// let mut mule_map = mule_map::MuleMap::<u32, usize, fnv_rs::FnvBuildHasher>::new();
275    /// mule_map.entry(5).or_insert(12);
276    /// if let mule_map::Entry::Occupied(mut o) = mule_map.entry(5) {
277    ///     *o.into_mut() += 10;
278    /// }
279    /// assert_eq!(mule_map.get(5), Some(&22));
280    /// ```
281    ///
282    /// Analogous to [`std::collections::hash_map::OccupiedEntry::into_mut`]
283    #[inline]
284    #[must_use]
285    pub fn into_mut(self) -> &'a mut V {
286        match self {
287            OccupiedEntry::HashMap(entry) => entry.base.into_mut(),
288            OccupiedEntry::Vec(entry) => entry.into_mut(),
289        }
290    }
291
292    /// Sets the value of the entry, and returns the entry’s old value.
293    ///
294    /// # Example
295    /// ```
296    /// let mut mule_map = mule_map::MuleMap::<u32, usize, fnv_rs::FnvBuildHasher>::new();
297    /// mule_map.entry(5).or_insert(12);
298    /// if let mule_map::Entry::Occupied(mut o) = mule_map.entry(5) {
299    ///     assert_eq!(o.insert(15), 12);
300    /// }
301    /// assert_eq!(mule_map.get(5), Some(&15));
302    /// ```
303    ///
304    /// Analogous to [`std::collections::hash_map::OccupiedEntry::insert`]
305    #[inline]
306    pub fn insert(&mut self, value: V) -> V {
307        match self {
308            OccupiedEntry::HashMap(entry) => entry.base.insert(value),
309            OccupiedEntry::Vec(entry) => entry.insert(value),
310        }
311    }
312
313    /// Takes the value out of the entry, and returns it.
314    ///
315    /// # Example
316    /// ```
317    /// let mut mule_map = mule_map::MuleMap::<u32, usize, fnv_rs::FnvBuildHasher>::new();
318    /// mule_map.entry(5).or_insert(12);
319    /// if let mule_map::Entry::Occupied(mut o) = mule_map.entry(5) {
320    ///     assert_eq!(o.remove(), 12);
321    /// }
322    /// assert_eq!(mule_map.contains_key(5), false);
323    /// ```
324    ///
325    /// Analogous to [`std::collections::hash_map::OccupiedEntry::remove`]
326    #[inline]
327    pub fn remove(self) -> V
328    where
329        V: Clone,
330    {
331        match self {
332            OccupiedEntry::HashMap(entry) => entry.base.remove(),
333            OccupiedEntry::Vec(entry) => entry.remove(),
334        }
335    }
336}
337
338impl<'a, K, V> OccupiedVecEntry<'a, K, V>
339where
340    K: PrimInt,
341{
342    #[inline]
343    #[must_use]
344    pub(crate) fn key(&self) -> K {
345        self.key
346    }
347    #[inline]
348    pub(crate) fn remove_entry(self) -> (K, V) {
349        (
350            self.key,
351            self.value.take().expect("Value should be occupied."),
352        )
353    }
354    #[inline]
355    #[must_use]
356    pub(crate) fn get(&self) -> &V {
357        self.value.as_ref().expect("Value should be occupied.")
358    }
359    #[inline]
360    #[must_use]
361    pub(crate) fn get_mut(&mut self) -> &mut V {
362        self.value.as_mut().expect("Value should be occupied.")
363    }
364    #[inline]
365    #[must_use]
366    pub(crate) fn into_mut(self) -> &'a mut V {
367        self.value.as_mut().expect("Value should be occupied.")
368    }
369    #[inline]
370    pub(crate) fn insert(&mut self, value: V) -> V {
371        let mut value = value;
372        std::mem::swap(&mut value, self.get_mut());
373        value
374    }
375    #[inline]
376    pub(crate) fn remove(self) -> V {
377        self.value.take().expect("Value should be occupied.")
378    }
379}
380
381impl<'a, K, V> VacantEntry<'a, K, V>
382where
383    K: PrimInt,
384{
385    /// Returns this entry’s key.
386    ///
387    /// # Example
388    /// ```
389    /// let mut mule_map = mule_map::MuleMap::<u32, usize, fnv_rs::FnvBuildHasher>::new();
390    /// assert_eq!(mule_map.entry(5).key(), 5);
391    /// ```
392    ///
393    /// Analogous to [`std::collections::hash_map::VacantEntry::key`]
394    #[inline]
395    #[must_use]
396    pub fn key(&self) -> K {
397        match self {
398            VacantEntry::HashMap(entry) => *entry.base.key(),
399            VacantEntry::Vec(entry) => entry.key(),
400        }
401    }
402
403    /// Sets the value of the entry with the VacantEntry’s key, and returns a mutable reference to it.
404    ///
405    /// # Example
406    /// ```
407    /// let mut mule_map = mule_map::MuleMap::<u32, usize, fnv_rs::FnvBuildHasher>::new();
408    /// if let mule_map::Entry::Vacant(o) = mule_map.entry(5) {
409    ///     o.insert(37);
410    /// }
411    /// assert_eq!(mule_map.get(5), Some(&37));
412    /// ```
413    ///
414    /// Analogous to [`std::collections::hash_map::VacantEntry::insert`]
415    #[inline]
416    pub fn insert(self, value: V) -> &'a mut V {
417        match self {
418            VacantEntry::HashMap(entry) => entry.base.insert(value),
419            VacantEntry::Vec(entry) => entry.insert(value),
420        }
421    }
422
423    /// Sets the value of the entry with the VacantEntry’s key, and returns an [`OccupiedEntry`].
424    ///
425    /// # Example
426    /// ```
427    /// let mut mule_map = mule_map::MuleMap::<u32, usize, fnv_rs::FnvBuildHasher>::new();
428    /// if let mule_map::Entry::Vacant(o) = mule_map.entry(5) {
429    ///     o.insert_entry(37);
430    /// }
431    /// assert_eq!(mule_map.get(5), Some(&37));
432    /// ```
433    ///
434    /// Analogous to [`std::collections::hash_map::VacantEntry::insert_entry`]
435    #[inline]
436    pub fn insert_entry(self, value: V) -> OccupiedEntry<'a, K, V> {
437        match self {
438            VacantEntry::HashMap(entry) => OccupiedEntry::HashMap(OccupiedHashMapEntry {
439                base: entry.base.insert_entry(value),
440            }),
441            VacantEntry::Vec(entry) => entry.insert_entry(value),
442        }
443    }
444}
445
446impl<'a, K, V> VacantVecEntry<'a, K, V>
447where
448    K: PrimInt,
449{
450    #[inline]
451    #[must_use]
452    pub(crate) fn key(&self) -> K {
453        self.key
454    }
455
456    #[inline]
457    pub(crate) fn insert(self, value: V) -> &'a mut V {
458        self.value.insert(value)
459    }
460
461    #[inline]
462    pub(crate) fn insert_entry(self, value: V) -> OccupiedEntry<'a, K, V> {
463        _ = self.value.insert(value);
464
465        OccupiedEntry::Vec(OccupiedVecEntry {
466            value: self.value,
467            key: self.key,
468        })
469    }
470}
471
472#[cfg(test)]
473mod tests {
474    use crate::MuleMap;
475
476    #[test]
477    fn test_entry() {
478        let mut mule_map = MuleMap::<u32, usize, fnv_rs::FnvBuildHasher>::new();
479        assert_eq!(mule_map.entry(5).and_modify(|e| *e += 1).or_insert(1), &1);
480        assert_eq!(mule_map.entry(5).and_modify(|e| *e += 1).or_insert(1), &2);
481    }
482}