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}