compact_map/base/
entry.rs

1use crate::base::MapImpl;
2use std::collections::hash_map::{
3    OccupiedEntry as HashMapOccupiedEntry, VacantEntry as HashMapVacantEntry,
4};
5use std::fmt;
6use std::fmt::Debug;
7use std::hash::Hash;
8use std::hint::unreachable_unchecked;
9
10/// A view into a single entry in a map, which may either be vacant or occupied.
11///
12/// This `enum` is constructed from the [`entry`] method on [`CompactMap`].
13///
14/// [`entry`]: crate::CompactMap::entry
15/// [`CompactMap`]: crate::CompactMap
16pub enum Entry<'a, K: 'a, V: 'a, const N: usize> {
17    /// An occupied entry.
18    Occupied(OccupiedEntry<'a, K, V, N>),
19    /// A vacant entry.
20    Vacant(VacantEntry<'a, K, V, N>),
21}
22
23impl<K: Debug, V: Debug, const N: usize> Debug for Entry<'_, K, V, N> {
24    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
25        match *self {
26            Entry::Vacant(ref v) => f.debug_tuple("Entry").field(v).finish(),
27            Entry::Occupied(ref o) => f.debug_tuple("Entry").field(o).finish(),
28        }
29    }
30}
31
32/// A view into an occupied entry in a `CompactMap`.
33/// It is part of the [`Entry`] enum.
34pub enum OccupiedEntry<'a, K: 'a, V: 'a, const N: usize> {
35    /// An entry in the heapless state.
36    Heapless(HeaplessEntry<'a, K, V, N>),
37    /// An entry in the spilled state.
38    Spilled(HashMapOccupiedEntry<'a, K, V>),
39}
40
41impl<K: Debug, V: Debug, const N: usize> Debug for OccupiedEntry<'_, K, V, N> {
42    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
43        f.debug_struct("OccupiedEntry")
44            .field("key", self.key())
45            .field("value", self.get())
46            .finish_non_exhaustive()
47    }
48}
49
50/// A view into a vacant entry in a `CompactMap`.
51/// It is part of the [`Entry`] enum.
52pub enum VacantEntry<'a, K: 'a, V: 'a, const N: usize> {
53    /// An entry in the heapless state.
54    Heapless(HeaplessEntry<'a, K, V, N>),
55    /// An entry in the spilled state.
56    Spilled(HashMapVacantEntry<'a, K, V>),
57}
58
59impl<K: Debug, V, const N: usize> Debug for VacantEntry<'_, K, V, N> {
60    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
61        f.debug_tuple("VacantEntry").field(self.key()).finish()
62    }
63}
64
65/// The error returned by [`try_insert`](crate::CompactMap::try_insert) when the key already exists.
66///
67/// Contains the occupied entry, and the value that was not inserted.
68#[cfg(feature = "map_try_insert")]
69pub struct OccupiedError<'a, K: 'a, V: 'a, const N: usize> {
70    /// The entry in the map that was already occupied.
71    pub entry: OccupiedEntry<'a, K, V, N>,
72    /// The value which was not inserted, because the entry was already occupied.
73    pub value: V,
74}
75
76#[cfg(feature = "map_try_insert")]
77impl<K: Debug, V: Debug, const N: usize> Debug for OccupiedError<'_, K, V, N> {
78    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
79        f.debug_struct("OccupiedError")
80            .field("key", self.entry.key())
81            .field("old_value", self.entry.get())
82            .field("new_value", &self.value)
83            .finish_non_exhaustive()
84    }
85}
86
87#[cfg(feature = "map_try_insert")]
88impl<'a, K: Debug, V: Debug, const N: usize> fmt::Display for OccupiedError<'a, K, V, N> {
89    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
90        write!(
91            f,
92            "failed to insert {:?}, key {:?} already exists with value {:?}",
93            self.value,
94            self.entry.key(),
95            self.entry.get(),
96        )
97    }
98}
99
100#[cfg(feature = "map_try_insert")]
101impl<'a, K: Debug, V: Debug, const N: usize> std::error::Error for OccupiedError<'a, K, V, N> {
102    #[allow(deprecated)]
103    fn description(&self) -> &str {
104        "key already exists"
105    }
106}
107
108/// A view into an entry in a `CompactMap`.
109/// It is part of the [`Entry`] enum.
110pub struct HeaplessEntry<'a, K: 'a, V: 'a, const N: usize> {
111    pub(crate) index: usize,
112    pub(crate) key: Option<K>,
113    pub(crate) inner: &'a mut MapImpl<K, V, N>,
114}
115
116impl<'a, K, V, const N: usize> Entry<'a, K, V, N>
117where
118    K: Eq + Hash,
119{
120    /// Ensures a value is in the entry by inserting the default if empty, and returns
121    /// a mutable reference to the value in the entry.
122    ///
123    /// # Examples
124    ///
125    /// ```
126    /// use compact_map::CompactMap;
127    ///
128    /// let mut map: CompactMap<&str, u32, 16> = CompactMap::new();
129    ///
130    /// map.entry("poneyland").or_insert(3);
131    /// assert_eq!(map["poneyland"], 3);
132    ///
133    /// *map.entry("poneyland").or_insert(10) *= 2;
134    /// assert_eq!(map["poneyland"], 6);
135    /// ```
136    #[inline]
137    pub fn or_insert(self, default: V) -> &'a mut V {
138        match self {
139            Entry::Occupied(entry) => entry.into_mut(),
140            Entry::Vacant(entry) => entry.insert(default),
141        }
142    }
143
144    /// Ensures a value is in the entry by inserting the result of the default function if empty,
145    /// and returns a mutable reference to the value in the entry.
146    ///
147    /// # Examples
148    ///
149    /// ```
150    /// use compact_map::CompactMap;
151    ///
152    /// let mut map = CompactMap::default();
153    /// let value = "hoho";
154    ///
155    /// map.entry("poneyland").or_insert_with(|| value);
156    ///
157    /// assert_eq!(map["poneyland"], "hoho");
158    /// ```
159    #[inline]
160    pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V {
161        match self {
162            Entry::Occupied(entry) => entry.into_mut(),
163            Entry::Vacant(entry) => entry.insert(default()),
164        }
165    }
166
167    /// Ensures a value is in the entry by inserting, if empty, the result of the default function.
168    /// This method allows for generating key-derived values for insertion by providing the default
169    /// function a reference to the key that was moved during the `.entry(key)` method call.
170    ///
171    /// The reference to the moved key is provided so that cloning or copying the key is
172    /// unnecessary, unlike with `.or_insert_with(|| ... )`.
173    ///
174    /// # Examples
175    ///
176    /// ```
177    /// use compact_map::CompactMap;
178    ///
179    /// let mut map = CompactMap::default();
180    ///
181    /// map.entry("poneyland").or_insert_with_key(|key| key.chars().count());
182    ///
183    /// assert_eq!(map["poneyland"], 9usize);
184    /// ```
185    #[inline]
186    pub fn or_insert_with_key<F: FnOnce(&K) -> V>(self, default: F) -> &'a mut V {
187        match self {
188            Entry::Occupied(entry) => entry.into_mut(),
189            Entry::Vacant(entry) => {
190                let value = default(entry.key());
191                entry.insert(value)
192            }
193        }
194    }
195
196    /// Sets the value of the entry, and returns an `OccupiedEntry`.
197    ///
198    /// # Examples
199    ///
200    /// ```
201    /// use compact_map::CompactMap;
202    ///
203    /// let mut map: CompactMap<&str, String, 16> = CompactMap::new();
204    /// let entry = map.entry("poneyland").insert_entry("hoho".to_string());
205    ///
206    /// assert_eq!(entry.key(), &"poneyland");
207    /// ```
208    #[cfg_attr(docsrs, doc(cfg(feature = "entry_insert")))]
209    #[cfg(feature = "entry_insert")]
210    #[inline]
211    pub fn insert_entry(self, value: V) -> OccupiedEntry<'a, K, V, N> {
212        match self {
213            Entry::Occupied(mut entry) => {
214                entry.insert(value);
215                entry
216            }
217            Entry::Vacant(entry) => entry.insert_entry(value),
218        }
219    }
220}
221
222impl<'a, K, V, const N: usize> Entry<'a, K, V, N> {
223    /// Returns a reference to this entry's key.
224    ///
225    /// # Examples
226    ///
227    /// ```
228    /// use compact_map::CompactMap;
229    ///
230    /// let mut map: CompactMap<&str, u32, 16> = CompactMap::new();
231    /// assert_eq!(map.entry("poneyland").key(), &"poneyland");
232    /// ```
233    #[inline]
234    pub fn key(&self) -> &K {
235        match *self {
236            Entry::Occupied(ref entry) => entry.key(),
237            Entry::Vacant(ref entry) => entry.key(),
238        }
239    }
240
241    /// Provides in-place mutable access to an occupied entry before any
242    /// potential inserts into the map.
243    ///
244    /// # Examples
245    ///
246    /// ```
247    /// use compact_map::CompactMap;
248    ///
249    /// let mut map: CompactMap<&str, u32, 16> = CompactMap::new();
250    ///
251    /// map.entry("poneyland")
252    ///    .and_modify(|e| { *e += 1 })
253    ///    .or_insert(42);
254    /// assert_eq!(map["poneyland"], 42);
255    ///
256    /// map.entry("poneyland")
257    ///    .and_modify(|e| { *e += 1 })
258    ///    .or_insert(42);
259    /// assert_eq!(map["poneyland"], 43);
260    /// ```
261    #[inline]
262    pub fn and_modify<F>(self, f: F) -> Self
263    where
264        F: FnOnce(&mut V),
265    {
266        match self {
267            Entry::Occupied(mut entry) => {
268                f(entry.get_mut());
269                Entry::Occupied(entry)
270            }
271            Entry::Vacant(entry) => Entry::Vacant(entry),
272        }
273    }
274}
275
276impl<'a, K, V: Default, const N: usize> Entry<'a, K, V, N>
277where
278    K: Eq + Hash,
279{
280    /// Ensures a value is in the entry by inserting the default value if empty,
281    /// and returns a mutable reference to the value in the entry.
282    ///
283    /// # Examples
284    ///
285    /// ```
286    /// # fn main() {
287    /// use compact_map::CompactMap;
288    ///
289    /// let mut map: CompactMap<&str, Option<u32>, 16> = CompactMap::new();
290    /// map.entry("poneyland").or_default();
291    ///
292    /// assert_eq!(map["poneyland"], None);
293    /// # }
294    /// ```
295    #[inline]
296    pub fn or_default(self) -> &'a mut V {
297        match self {
298            Entry::Occupied(entry) => entry.into_mut(),
299            Entry::Vacant(entry) => entry.insert(Default::default()),
300        }
301    }
302}
303
304impl<'a, K, V, const N: usize> OccupiedEntry<'a, K, V, N> {
305    /// Gets a reference to the key in the entry.
306    ///
307    /// # Examples
308    ///
309    /// ```
310    /// use compact_map::CompactMap;
311    ///
312    /// let mut map: CompactMap<&str, u32, 16> = CompactMap::new();
313    /// map.entry("poneyland").or_insert(12);
314    /// assert_eq!(map.entry("poneyland").key(), &"poneyland");
315    /// ```
316    #[inline]
317    pub fn key(&self) -> &K {
318        match self {
319            Self::Heapless(entry) => entry.key(),
320            Self::Spilled(entry) => entry.key(),
321        }
322    }
323
324    /// Take the ownership of the key and value from the map.
325    ///
326    /// # Examples
327    ///
328    /// ```
329    /// use compact_map::{CompactMap, Entry};
330    ///
331    /// let mut map: CompactMap<&str, u32, 16> = CompactMap::new();
332    /// map.entry("poneyland").or_insert(12);
333    ///
334    /// if let Entry::Occupied(o) = map.entry("poneyland") {
335    ///     // We delete the entry from the map.
336    ///     o.remove_entry();
337    /// }
338    ///
339    /// assert_eq!(map.contains_key("poneyland"), false);
340    /// ```
341    #[inline]
342    pub fn remove_entry(self) -> (K, V) {
343        match self {
344            Self::Heapless(entry) => {
345                // SAFETY: the entry is occupied
346                unsafe {
347                    entry
348                        .inner
349                        .as_heapless_mut_unchecked()
350                        .swap_remove_unchecked(entry.index)
351                }
352            }
353            Self::Spilled(entry) => entry.remove_entry(),
354        }
355    }
356
357    /// Gets a reference to the value in the entry.
358    ///
359    /// # Examples
360    ///
361    /// ```
362    /// use compact_map::{CompactMap, Entry};
363    ///
364    /// let mut map: CompactMap<&str, u32, 16> = CompactMap::new();
365    /// map.entry("poneyland").or_insert(12);
366    ///
367    /// if let Entry::Occupied(o) = map.entry("poneyland") {
368    ///     assert_eq!(o.get(), &12);
369    /// }
370    /// ```
371    #[inline]
372    pub fn get(&self) -> &V {
373        match self {
374            Self::Heapless(entry) => {
375                // SAFETY: the entry is occupied
376                unsafe { entry.get_unchecked() }
377            }
378            Self::Spilled(entry) => entry.get(),
379        }
380    }
381
382    /// Gets a mutable reference to the value in the entry.
383    ///
384    /// If you need a reference to the `OccupiedEntry` which may outlive the
385    /// destruction of the `Entry` value, see [`into_mut`].
386    ///
387    /// [`into_mut`]: Self::into_mut
388    ///
389    /// # Examples
390    ///
391    /// ```
392    /// use compact_map::{CompactMap, Entry};
393    ///
394    /// let mut map: CompactMap<&str, u32, 16> = CompactMap::new();
395    /// map.entry("poneyland").or_insert(12);
396    ///
397    /// assert_eq!(map["poneyland"], 12);
398    /// if let Entry::Occupied(mut o) = map.entry("poneyland") {
399    ///     *o.get_mut() += 10;
400    ///     assert_eq!(*o.get(), 22);
401    ///
402    ///     // We can use the same Entry multiple times.
403    ///     *o.get_mut() += 2;
404    /// }
405    ///
406    /// assert_eq!(map["poneyland"], 24);
407    /// ```
408    #[inline]
409    pub fn get_mut(&mut self) -> &mut V {
410        match self {
411            Self::Heapless(entry) => {
412                // SAFETY: the entry is occupied
413                unsafe { entry.get_unchecked_mut() }
414            }
415            Self::Spilled(entry) => entry.get_mut(),
416        }
417    }
418
419    /// Converts the `OccupiedEntry` into a mutable reference to the value in the entry
420    /// with a lifetime bound to the map itself.
421    ///
422    /// If you need multiple references to the `OccupiedEntry`, see [`get_mut`].
423    ///
424    /// [`get_mut`]: Self::get_mut
425    ///
426    /// # Examples
427    ///
428    /// ```
429    /// use compact_map::{CompactMap, Entry};
430    ///
431    /// let mut map: CompactMap<&str, u32, 16> = CompactMap::new();
432    /// map.entry("poneyland").or_insert(12);
433    ///
434    /// assert_eq!(map["poneyland"], 12);
435    /// if let Entry::Occupied(o) = map.entry("poneyland") {
436    ///     *o.into_mut() += 10;
437    /// }
438    ///
439    /// assert_eq!(map["poneyland"], 22);
440    /// ```
441    #[inline]
442    pub fn into_mut(self) -> &'a mut V {
443        match self {
444            Self::Heapless(HeaplessEntry { index, inner, .. }) => {
445                // SAFETY: the entry is occupied
446                unsafe { &mut inner.as_heapless_mut_unchecked().get_unchecked_mut(index).1 }
447            }
448            Self::Spilled(entry) => entry.into_mut(),
449        }
450    }
451
452    /// Sets the value of the entry, and returns the entry's old value.
453    ///
454    /// # Examples
455    ///
456    /// ```
457    /// use compact_map::{CompactMap, Entry};
458    ///
459    /// let mut map: CompactMap<&str, u32, 16> = CompactMap::new();
460    /// map.entry("poneyland").or_insert(12);
461    ///
462    /// if let Entry::Occupied(mut o) = map.entry("poneyland") {
463    ///     assert_eq!(o.insert(15), 12);
464    /// }
465    ///
466    /// assert_eq!(map["poneyland"], 15);
467    /// ```
468    #[inline]
469    pub fn insert(&mut self, value: V) -> V {
470        match self {
471            Self::Heapless(entry) => {
472                // SAFETY: the entry is occupied
473                unsafe { std::mem::replace(entry.get_unchecked_mut(), value) }
474            }
475            Self::Spilled(entry) => entry.insert(value),
476        }
477    }
478
479    /// Takes the value out of the entry, and returns it.
480    ///
481    /// # Examples
482    ///
483    /// ```
484    /// use compact_map::{CompactMap, Entry};
485    ///
486    /// let mut map: CompactMap<&str, u32, 16> = CompactMap::new();
487    /// map.entry("poneyland").or_insert(12);
488    ///
489    /// if let Entry::Occupied(o) = map.entry("poneyland") {
490    ///     assert_eq!(o.remove(), 12);
491    /// }
492    ///
493    /// assert_eq!(map.contains_key("poneyland"), false);
494    /// ```
495    #[inline]
496    pub fn remove(self) -> V {
497        match self {
498            Self::Heapless(entry) => {
499                // SAFETY: the entry is occupied
500                unsafe {
501                    entry
502                        .inner
503                        .as_heapless_mut_unchecked()
504                        .swap_remove_unchecked(entry.index)
505                        .1
506                }
507            }
508            Self::Spilled(entry) => entry.remove(),
509        }
510    }
511}
512
513impl<'a, K: Clone, V, const N: usize> OccupiedEntry<'a, K, V, N> {
514    /// Replaces the entry, returning the old key and value. The new key in the hash map will be
515    /// the key used to create this entry.
516    ///
517    /// # Examples
518    ///
519    /// ```
520    /// use compact_map::{CompactMap, Entry};
521    /// use std::rc::Rc;
522    ///
523    /// let mut map: CompactMap<Rc<String>, u32, 16> = CompactMap::new();
524    /// map.insert(Rc::new("Stringthing".to_string()), 15);
525    ///
526    /// let my_key = Rc::new("Stringthing".to_string());
527    ///
528    /// if let Entry::Occupied(entry) = map.entry(my_key) {
529    ///     // Also replace the key with a handle to our other key.
530    ///     let (old_key, old_value): (Rc<String>, u32) = entry.replace_entry(16);
531    /// }
532    ///
533    /// ```
534    #[cfg_attr(docsrs, doc(cfg(feature = "map_entry_replace")))]
535    #[cfg(feature = "map_entry_replace")]
536    #[inline]
537    pub fn replace_entry(self, value: V) -> (K, V) {
538        match self {
539            Self::Heapless(mut entry) => {
540                let key = entry.key_owned();
541                // SAFETY: it is in heapless state
542                let vec = unsafe { entry.inner.as_heapless_mut_unchecked() };
543                // SAFETY: the entry is occupied
544                let (old_key, old_value) = unsafe { vec.swap_remove_unchecked(entry.index) };
545                // SAFETY: We just removed an element, so the push is safe
546                unsafe {
547                    vec.push((key, value)).unwrap_unchecked();
548                }
549                (old_key, old_value)
550            }
551            Self::Spilled(entry) => entry.replace_entry(value),
552        }
553    }
554
555    /// Replaces the key in the hash map with the key used to create this entry.
556    ///
557    /// # Examples
558    ///
559    /// ```
560    /// use compact_map::{CompactMap, Entry};
561    /// use std::rc::Rc;
562    ///
563    /// let mut map: CompactMap<Rc<String>, u32, 16> = CompactMap::new();
564    /// let known_strings: Vec<Rc<String>> = Vec::new();
565    ///
566    /// // Initialise known strings, run program, etc.
567    ///
568    /// reclaim_memory(&mut map, &known_strings);
569    ///
570    /// fn reclaim_memory(map: &mut CompactMap<Rc<String>, u32, 16>, known_strings: &[Rc<String>] ) {
571    ///     for s in known_strings {
572    ///         if let Entry::Occupied(entry) = map.entry(Rc::clone(s)) {
573    ///             // Replaces the entry's key with our version of it in `known_strings`.
574    ///             entry.replace_key();
575    ///         }
576    ///     }
577    /// }
578    /// ```
579    #[cfg_attr(docsrs, doc(cfg(feature = "map_entry_replace")))]
580    #[cfg(feature = "map_entry_replace")]
581    #[inline]
582    pub fn replace_key(self) -> K {
583        match self {
584            Self::Heapless(mut entry) => {
585                let key = entry.key_owned();
586                // SAFETY: it is in heapless state
587                let vec = unsafe { entry.inner.as_heapless_mut_unchecked() };
588                // SAFETY: the entry is occupied
589                let (old_key, value) = unsafe { vec.swap_remove_unchecked(entry.index) };
590                // SAFETY: We just removed an element, so the push is safe
591                unsafe {
592                    vec.push_unchecked((key, value));
593                }
594                old_key
595            }
596            Self::Spilled(entry) => entry.replace_key(),
597        }
598    }
599}
600
601impl<'a, K: 'a, V: 'a, const N: usize> VacantEntry<'a, K, V, N> {
602    /// Gets a reference to the key that would be used when inserting a value
603    /// through the `VacantEntry`.
604    ///
605    /// # Examples
606    ///
607    /// ```
608    /// use compact_map::{CompactMap, Entry};
609    ///
610    /// let mut map: CompactMap<&str, u32, 16> = CompactMap::new();
611    /// assert_eq!(map.entry("poneyland").key(), &"poneyland");
612    /// ```
613    #[inline]
614    pub fn key(&self) -> &K {
615        match self {
616            Self::Heapless(entry) => {
617                // SAFETY: vacant entry always has a key
618                unsafe { entry.key_unchecked() }
619            }
620            Self::Spilled(entry) => entry.key(),
621        }
622    }
623
624    /// Take ownership of the key.
625    ///
626    /// # Examples
627    ///
628    /// ```
629    /// use compact_map::{CompactMap, Entry};
630    ///
631    /// let mut map: CompactMap<&str, u32, 16> = CompactMap::new();
632    ///
633    /// if let Entry::Vacant(v) = map.entry("poneyland") {
634    ///     v.into_key();
635    /// }
636    /// ```
637    #[inline]
638    pub fn into_key(self) -> K {
639        match self {
640            Self::Heapless(entry) => {
641                // SAFETY: vacant entry always has a key
642                unsafe { entry.key.unwrap_unchecked() }
643            }
644            Self::Spilled(entry) => entry.into_key(),
645        }
646    }
647}
648
649impl<'a, K: 'a, V: 'a, const N: usize> VacantEntry<'a, K, V, N>
650where
651    K: Eq + Hash,
652{
653    /// Sets the value of the entry with the `VacantEntry`'s key,
654    /// and returns a mutable reference to it.
655    ///
656    /// # Examples
657    ///
658    /// ```
659    /// use compact_map::{CompactMap, Entry};
660    ///
661    /// let mut map: CompactMap<&str, u32, 16> = CompactMap::new();
662    ///
663    /// if let Entry::Vacant(o) = map.entry("poneyland") {
664    ///     o.insert(37);
665    /// }
666    /// assert_eq!(map["poneyland"], 37);
667    /// ```
668    #[inline]
669    pub fn insert(self, value: V) -> &'a mut V {
670        match self {
671            Self::Heapless(HeaplessEntry { index, key, inner }) => {
672                // SAFETY: vacant entry always has a key
673                let k = unsafe { key.unwrap_unchecked() };
674                // SAFETY: HeaplessEntry only constructed when the in heapless state
675                let vec_is_full = unsafe { inner.as_heapless_unchecked().is_full() };
676                if !vec_is_full {
677                    let vec = unsafe { inner.as_heapless_mut_unchecked() };
678                    // SAFETY: We just checked that the vec is not full
679                    unsafe { vec.push_unchecked((k, value)) };
680                    debug_assert!(vec.len() - 1 == index);
681                    // SAFETY: index is in bounds
682                    unsafe { &mut vec.get_unchecked_mut(index).1 }
683                } else {
684                    // SAFETY: current in heapless
685                    let map = unsafe { inner.try_spill(1) };
686                    map.unwrap().entry(k).or_insert(value)
687                }
688            }
689            Self::Spilled(entry) => entry.insert(value),
690        }
691    }
692
693    /// Sets the value of the entry with the `VacantEntry`'s key,
694    /// and returns an `OccupiedEntry`.
695    ///
696    /// # Examples
697    ///
698    /// ```
699    /// use compact_map::{CompactMap, Entry};
700    ///
701    /// let mut map: CompactMap<&str, u32, 16> = CompactMap::new();
702    ///
703    /// if let Entry::Vacant(o) = map.entry("poneyland") {
704    ///     o.insert_entry(37);
705    /// }
706    /// assert_eq!(map["poneyland"], 37);
707    /// ```
708    #[cfg_attr(docsrs, doc(cfg(feature = "entry_insert")))]
709    #[cfg(feature = "entry_insert")]
710    #[inline]
711    pub fn insert_entry(self, value: V) -> OccupiedEntry<'a, K, V, N> {
712        match self {
713            Self::Heapless(HeaplessEntry { index, key, inner }) => {
714                // SAFETY: vacant entry always has a key
715                let k = unsafe { key.unwrap_unchecked() };
716                // SAFETY: HeaplessEntry only constructed when the in heapless state
717                let vec = unsafe { inner.as_heapless_mut_unchecked() };
718                if !vec.is_full() {
719                    // SAFETY: We just checked that the vec is not full
720                    unsafe { vec.push_unchecked((k, value)) };
721                    debug_assert!(vec.len() - 1 == index);
722                    OccupiedEntry::Heapless(HeaplessEntry {
723                        index,
724                        key: None,
725                        inner,
726                    })
727                } else {
728                    // SAFETY: current in heapless
729                    let map = unsafe { inner.try_spill(1) };
730                    OccupiedEntry::Spilled(map.unwrap().entry(k).insert_entry(value))
731                }
732            }
733            Self::Spilled(entry) => OccupiedEntry::Spilled(entry.insert_entry(value)),
734        }
735    }
736}
737
738impl<K, V, const N: usize> HeaplessEntry<'_, K, V, N> {
739    #[inline]
740    fn key(&self) -> &K {
741        match self.key {
742            Some(ref k) => k,
743            None => {
744                // SAFETY: vacant entry always has a key
745                unsafe {
746                    &self
747                        .inner
748                        .as_heapless_unchecked()
749                        .get_unchecked(self.index)
750                        .0
751                }
752            }
753        }
754    }
755
756    /// # Safety
757    ///
758    /// Must be called when key is Some.
759    #[inline]
760    unsafe fn key_unchecked(&self) -> &K {
761        match self.key {
762            Some(ref k) => k,
763            None => unreachable_unchecked(),
764        }
765    }
766
767    /// # Safety
768    ///
769    /// Must be called when the entry is occupied.
770    #[inline]
771    unsafe fn get_unchecked(&self) -> &V {
772        &self
773            .inner
774            .as_heapless_unchecked()
775            .get_unchecked(self.index)
776            .1
777    }
778
779    /// # Safety
780    ///
781    /// Must be called when the entry is occupied.
782    #[inline]
783    unsafe fn get_unchecked_mut(&mut self) -> &mut V {
784        &mut self
785            .inner
786            .as_heapless_mut_unchecked()
787            .get_unchecked_mut(self.index)
788            .1
789    }
790}
791
792#[cfg(feature = "map_entry_replace")]
793impl<K: Clone, V, const N: usize> HeaplessEntry<'_, K, V, N> {
794    #[inline]
795    fn key_owned(&mut self) -> K {
796        match self.key.take() {
797            Some(k) => k,
798            None => {
799                // SAFETY: vacant entry always has a key
800                unsafe {
801                    self.inner
802                        .as_heapless_mut_unchecked()
803                        .get_unchecked(self.index)
804                        .0
805                        .clone()
806                }
807            }
808        }
809    }
810}