abi_stable/std_types/map/
entry.rs

1use super::*;
2
3use std::{
4    collections::hash_map::{Entry, OccupiedEntry, VacantEntry},
5    mem::ManuallyDrop,
6    ptr,
7};
8
9use crate::{
10    marker_type::UnsafeIgnoredType,
11    prefix_type::WithMetadata,
12    sabi_types::{RMut, RRef},
13};
14
15/// The enum stored alongside the unerased HashMap.
16pub(super) enum BoxedREntry<'a, K, V> {
17    Occupied(UnerasedOccupiedEntry<'a, K, V>),
18    Vacant(UnerasedVacantEntry<'a, K, V>),
19}
20
21/// A handle into an entry in a map, which is either vacant or occupied.
22#[derive(StableAbi)]
23#[repr(C)]
24#[sabi(bound(K: 'a), bound(V: 'a))]
25pub enum REntry<'a, K, V> {
26    /// An occupied entry
27    Occupied(ROccupiedEntry<'a, K, V>),
28    /// A vacnt entry
29    Vacant(RVacantEntry<'a, K, V>),
30}
31
32/////////////////////////////////////////////////////////////////////////////////////////////
33
34#[derive(StableAbi)]
35#[repr(C)]
36struct ErasedOccupiedEntry<K, V>(PhantomData<(K, V)>);
37
38#[derive(StableAbi)]
39#[repr(C)]
40struct ErasedVacantEntry<K, V>(PhantomData<(K, V)>);
41
42type UnerasedOccupiedEntry<'a, K, V> = ManuallyDrop<OccupiedEntry<'a, MapKey<K>, V>>;
43
44type UnerasedVacantEntry<'a, K, V> = ManuallyDrop<VacantEntry<'a, MapKey<K>, V>>;
45
46impl<'a, K: 'a, V: 'a> ErasedType<'a> for ErasedOccupiedEntry<K, V> {
47    type Unerased = UnerasedOccupiedEntry<'a, K, V>;
48}
49
50impl<'a, K: 'a, V: 'a> ErasedType<'a> for ErasedVacantEntry<K, V> {
51    type Unerased = UnerasedVacantEntry<'a, K, V>;
52}
53
54/////////////////////////////////////////////////////////////////////////////////////////////
55
56impl<'a, K, V> From<Entry<'a, MapKey<K>, V>> for BoxedREntry<'a, K, V>
57where
58    K: Eq + Hash,
59{
60    fn from(entry: Entry<'a, MapKey<K>, V>) -> Self {
61        match entry {
62            Entry::Occupied(entry) => entry.piped(ManuallyDrop::new).piped(BoxedREntry::Occupied),
63            Entry::Vacant(entry) => entry.piped(ManuallyDrop::new).piped(BoxedREntry::Vacant),
64        }
65    }
66}
67
68impl<'a, K, V> REntry<'a, K, V>
69where
70    K: Eq + Hash,
71{
72    pub(super) unsafe fn new(entry: &'a mut BoxedREntry<'a, K, V>) -> Self {
73        match entry {
74            BoxedREntry::Occupied(entry) => {
75                entry.piped(ROccupiedEntry::new).piped(REntry::Occupied)
76            }
77            BoxedREntry::Vacant(entry) => entry.piped(RVacantEntry::new).piped(REntry::Vacant),
78        }
79    }
80}
81
82/////////////////////////////////////////////////////////////////////////////////////////////
83
84impl<'a, K, V> REntry<'a, K, V> {
85    /// Returns a reference to the value in the entry.
86    ///
87    /// # Example
88    ///
89    /// ```
90    /// use abi_stable::std_types::RHashMap;
91    ///
92    /// let mut map: RHashMap<u32, u32> = vec![(1, 100)].into_iter().collect();
93    ///
94    /// assert_eq!(map.entry(0).get(), None);
95    /// assert_eq!(map.entry(1).get(), Some(&100));
96    ///
97    /// ```
98    pub fn get(&self) -> Option<&V> {
99        match self {
100            REntry::Occupied(entry) => Some(entry.get()),
101            REntry::Vacant(_) => None,
102        }
103    }
104
105    /// Returns a mutable reference to the value in the entry.
106    ///
107    /// # Example
108    ///
109    /// ```
110    /// use abi_stable::std_types::RHashMap;
111    ///
112    /// let mut map: RHashMap<u32, u32> = vec![(1, 100)].into_iter().collect();
113    ///
114    /// assert_eq!(map.entry(0).get_mut(), None);
115    /// assert_eq!(map.entry(1).get_mut(), Some(&mut 100));
116    ///
117    /// ```
118    pub fn get_mut(&mut self) -> Option<&mut V> {
119        match self {
120            REntry::Occupied(entry) => Some(entry.get_mut()),
121            REntry::Vacant(_) => None,
122        }
123    }
124
125    /// Inserts `default` as the value in the entry if it wasn't occupied,
126    /// returning a mutable reference to the value in the entry.
127    ///
128    /// # Example
129    ///
130    /// ```
131    /// use abi_stable::std_types::RHashMap;
132    ///
133    /// let mut map = RHashMap::<u32, u32>::new();
134    ///
135    /// assert_eq!(map.entry(0).or_insert(100), &mut 100);
136    ///
137    /// assert_eq!(map.entry(0).or_insert(400), &mut 100);
138    ///
139    /// ```
140    pub fn or_insert(self, default: V) -> &'a mut V {
141        match self {
142            REntry::Occupied(entry) => entry.into_mut(),
143            REntry::Vacant(entry) => entry.insert(default),
144        }
145    }
146
147    /// Inserts `default()` as the value in the entry if it wasn't occupied,
148    /// returning a mutable reference to the value in the entry.
149    ///
150    /// # Example
151    ///
152    /// ```
153    /// use abi_stable::std_types::{RHashMap, RString};
154    ///
155    /// let mut map = RHashMap::<u32, RString>::new();
156    ///
157    /// assert_eq!(
158    ///     map.entry(0).or_insert_with(|| "foo".into()),
159    ///     &mut RString::from("foo")
160    /// );
161    ///
162    /// assert_eq!(
163    ///     map.entry(0).or_insert_with(|| "bar".into()),
164    ///     &mut RString::from("foo")
165    /// );
166    ///
167    /// ```
168    pub fn or_insert_with<F>(self, default: F) -> &'a mut V
169    where
170        F: FnOnce() -> V,
171    {
172        match self {
173            REntry::Occupied(entry) => entry.into_mut(),
174            REntry::Vacant(entry) => entry.insert(default()),
175        }
176    }
177
178    /// Gets the key of the entry.
179    ///
180    /// # Example
181    ///
182    /// ```
183    /// use abi_stable::std_types::{RHashMap, RString};
184    ///
185    /// let mut map = RHashMap::<RString, RString>::new();
186    /// map.insert("foo".into(), "bar".into());
187    ///
188    /// assert_eq!(map.entry("foo".into()).key(), &RString::from("foo"));
189    /// ```
190    pub fn key(&self) -> &K {
191        match self {
192            REntry::Occupied(entry) => entry.key(),
193            REntry::Vacant(entry) => entry.key(),
194        }
195    }
196
197    /// Allows mutating an occupied entry before doing other operations.
198    ///
199    /// This is a no-op on a vacant entry.
200    ///
201    /// # Example
202    ///
203    /// ```
204    /// use abi_stable::std_types::{RHashMap, RString};
205    ///
206    /// let mut map = RHashMap::<RString, RString>::new();
207    /// map.insert("foo".into(), "bar".into());
208    ///
209    /// assert_eq!(
210    ///     map.entry("foo".into())
211    ///         .and_modify(|x| x.push_str("hoo"))
212    ///         .get(),
213    ///     Some(&RString::from("barhoo"))
214    /// );
215    /// ```
216    pub fn and_modify<F>(self, f: F) -> Self
217    where
218        F: FnOnce(&mut V),
219    {
220        match self {
221            REntry::Occupied(mut entry) => {
222                f(entry.get_mut());
223                REntry::Occupied(entry)
224            }
225            REntry::Vacant(entry) => REntry::Vacant(entry),
226        }
227    }
228
229    /// Inserts the `V::default()` value in the entry if it wasn't occupied,
230    /// returning a mutable reference to the value in the entry.
231    ///
232    /// # Example
233    ///
234    /// ```
235    /// use abi_stable::std_types::RHashMap;
236    ///
237    /// let mut map = RHashMap::<u32, u32>::new();
238    ///
239    /// assert_eq!(map.entry(0).or_insert(100), &mut 100);
240    /// assert_eq!(map.entry(0).or_default(), &mut 100);
241    ///
242    /// assert_eq!(map.entry(1).or_default(), &mut 0);
243    ///
244    /// ```
245    pub fn or_default(self) -> &'a mut V
246    where
247        V: Default,
248    {
249        match self {
250            REntry::Occupied(entry) => entry.into_mut(),
251            REntry::Vacant(entry) => entry.insert(Default::default()),
252        }
253    }
254}
255
256impl<K, V> Debug for REntry<'_, K, V>
257where
258    K: Debug,
259    V: Debug,
260{
261    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
262        match self {
263            REntry::Occupied(entry) => Debug::fmt(entry, f),
264            REntry::Vacant(entry) => Debug::fmt(entry, f),
265        }
266    }
267}
268
269/////////////////////////////////////////////////////////////////////////////////////////////
270
271/// A handle into an occupied entry in a map.
272#[derive(StableAbi)]
273#[repr(C)]
274#[sabi(bound(K: 'a), bound(V: 'a))]
275pub struct ROccupiedEntry<'a, K, V> {
276    entry: RMut<'a, ErasedOccupiedEntry<K, V>>,
277    vtable: OccupiedVTable_Ref<K, V>,
278    _marker: UnsafeIgnoredType<OccupiedEntry<'a, K, V>>,
279}
280
281/// A handle into a vacant entry in a map.
282#[derive(StableAbi)]
283#[repr(C)]
284#[sabi(bound(K: 'a), bound(V: 'a))]
285pub struct RVacantEntry<'a, K, V> {
286    entry: RMut<'a, ErasedVacantEntry<K, V>>,
287    vtable: VacantVTable_Ref<K, V>,
288    _marker: UnsafeIgnoredType<VacantEntry<'a, K, V>>,
289}
290
291/////////////////////////////////////////////////////////////////////////////////////////////
292
293impl<'a, K, V> ROccupiedEntry<'a, K, V> {
294    const fn vtable(&self) -> OccupiedVTable_Ref<K, V> {
295        self.vtable
296    }
297}
298
299impl<'a, K, V> ROccupiedEntry<'a, K, V> {
300    fn into_inner(self) -> RMut<'a, ErasedOccupiedEntry<K, V>> {
301        let mut this = ManuallyDrop::new(self);
302        unsafe { ((&mut this.entry) as *mut RMut<'a, ErasedOccupiedEntry<K, V>>).read() }
303    }
304
305    pub(super) fn new(entry: &'a mut UnerasedOccupiedEntry<'a, K, V>) -> Self {
306        unsafe {
307            Self {
308                entry: ErasedOccupiedEntry::from_unerased(entry),
309                vtable: OccupiedVTable::VTABLE_REF,
310                _marker: UnsafeIgnoredType::DEFAULT,
311            }
312        }
313    }
314
315    /// Gets a reference to the key of the entry.
316    ///
317    /// # Example
318    ///
319    /// ```
320    /// use abi_stable::std_types::map::{REntry, RHashMap};
321    ///
322    /// let mut map = RHashMap::<u32, u32>::new();
323    ///
324    /// map.insert(0, 100);
325    ///
326    /// match map.entry(0) {
327    ///     REntry::Occupied(entry) => {
328    ///         assert_eq!(entry.key(), &0);
329    ///     }
330    ///     REntry::Vacant(_) => unreachable!(),
331    /// };
332    ///
333    /// ```
334    pub fn key(&self) -> &K {
335        let vtable = self.vtable();
336
337        vtable.key()(self.entry.as_rref())
338    }
339
340    /// Gets a reference to the value in the entry.
341    ///
342    /// # Example
343    ///
344    /// ```
345    /// use abi_stable::std_types::map::{REntry, RHashMap};
346    ///
347    /// let mut map = RHashMap::<u32, u32>::new();
348    ///
349    /// map.insert(6, 15);
350    ///
351    /// match map.entry(6) {
352    ///     REntry::Occupied(entry) => {
353    ///         assert_eq!(entry.get(), &15);
354    ///     }
355    ///     REntry::Vacant(_) => unreachable!(),
356    /// };
357    ///
358    ///
359    /// ```
360    pub fn get(&self) -> &V {
361        let vtable = self.vtable();
362
363        vtable.get_elem()(self.entry.as_rref())
364    }
365
366    /// Gets a mutable reference to the value in the entry.
367    /// To borrow with the lifetime of the map, use `ROccupiedEntry::into_mut`.
368    ///
369    /// # Example
370    ///
371    /// ```
372    /// use abi_stable::std_types::map::{REntry, RHashMap};
373    ///
374    /// let mut map = RHashMap::<u32, u32>::new();
375    ///
376    /// map.insert(6, 15);
377    ///
378    /// match map.entry(6) {
379    ///     REntry::Occupied(mut entry) => {
380    ///         assert_eq!(entry.get_mut(), &mut 15);
381    ///     }
382    ///     REntry::Vacant(_) => unreachable!(),
383    /// };
384    ///
385    ///
386    /// ```
387    pub fn get_mut(&mut self) -> &mut V {
388        let vtable = self.vtable();
389
390        vtable.get_mut_elem()(self.entry.reborrow())
391    }
392
393    /// Gets a mutable reference to the value in the entry,
394    /// that borrows with the lifetime of the map instead of
395    /// borrowing from this `ROccupiedEntry`.
396    ///
397    /// # Example
398    ///
399    /// ```
400    /// use abi_stable::std_types::map::{REntry, RHashMap};
401    ///
402    /// let mut map = RHashMap::<String, u32>::new();
403    ///
404    /// map.insert("baz".into(), 0xDEAD);
405    ///
406    /// match map.entry("baz".into()) {
407    ///     REntry::Occupied(entry) => {
408    ///         assert_eq!(entry.into_mut(), &mut 0xDEAD);
409    ///     }
410    ///     REntry::Vacant(_) => unreachable!(),
411    /// };
412    ///
413    ///
414    /// ```
415    pub fn into_mut(self) -> &'a mut V {
416        let vtable = self.vtable();
417
418        vtable.fn_into_mut_elem()(self)
419    }
420
421    /// Replaces the current value of the entry with `value`, returning the previous value.
422    ///
423    /// # Example
424    ///
425    /// ```
426    /// use abi_stable::std_types::map::{REntry, RHashMap};
427    ///
428    /// let mut map = RHashMap::<String, u32>::new();
429    ///
430    /// map.insert("baz".into(), 0xD00D);
431    ///
432    /// match map.entry("baz".into()) {
433    ///     REntry::Occupied(mut entry) => {
434    ///         assert_eq!(entry.insert(0xDEAD), 0xD00D);
435    ///     }
436    ///     REntry::Vacant(_) => {
437    ///         unreachable!();
438    ///     }
439    /// }
440    ///
441    /// assert_eq!(map.get("baz"), Some(&0xDEAD));
442    ///
443    /// ```
444    pub fn insert(&mut self, value: V) -> V {
445        let vtable = self.vtable();
446
447        vtable.insert_elem()(self.entry.reborrow(), value)
448    }
449
450    /// Removes the entry from the map, returns the value.
451    ///
452    /// # Example
453    ///
454    /// ```
455    /// use abi_stable::std_types::map::{REntry, RHashMap};
456    ///
457    /// let mut map = RHashMap::<String, u32>::new();
458    ///
459    /// map.insert("baz".into(), 0xDEAD);
460    ///
461    /// match map.entry("baz".into()) {
462    ///     REntry::Occupied(entry) => {
463    ///         assert_eq!(entry.remove(), 0xDEAD);
464    ///     }
465    ///     REntry::Vacant(_) => {
466    ///         unreachable!();
467    ///     }
468    /// }
469    ///
470    /// assert!(!map.contains_key("baz"));
471    ///
472    /// ```
473    pub fn remove(self) -> V {
474        let vtable = self.vtable();
475
476        vtable.remove()(self)
477    }
478}
479
480impl<K, V> Debug for ROccupiedEntry<'_, K, V>
481where
482    K: Debug,
483    V: Debug,
484{
485    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
486        f.debug_struct("ROccupiedEntry")
487            .field("key", self.key())
488            .field("value", self.get())
489            .finish()
490    }
491}
492
493impl<'a, K, V> Drop for ROccupiedEntry<'a, K, V> {
494    fn drop(&mut self) {
495        let vtable = self.vtable();
496
497        unsafe {
498            vtable.drop_entry()(self.entry.reborrow());
499        }
500    }
501}
502
503/////////////////////////////////////////////////////////////////////////////////////////////
504
505impl<'a, K, V> RVacantEntry<'a, K, V> {
506    const fn vtable(&self) -> VacantVTable_Ref<K, V> {
507        self.vtable
508    }
509}
510
511impl<'a, K, V> RVacantEntry<'a, K, V> {
512    fn into_inner(self) -> RMut<'a, ErasedVacantEntry<K, V>> {
513        let mut this = ManuallyDrop::new(self);
514        unsafe { ((&mut this.entry) as *mut RMut<'a, ErasedVacantEntry<K, V>>).read() }
515    }
516
517    pub(super) fn new(entry: &'a mut UnerasedVacantEntry<'a, K, V>) -> Self
518    where
519        K: Eq + Hash,
520    {
521        unsafe {
522            Self {
523                entry: ErasedVacantEntry::from_unerased(entry),
524                vtable: VacantVTable::VTABLE_REF,
525                _marker: UnsafeIgnoredType::DEFAULT,
526            }
527        }
528    }
529
530    /// Gets a reference to the key of the entry.
531    ///
532    /// # Example
533    ///
534    /// ```
535    /// use abi_stable::std_types::map::{REntry, RHashMap};
536    ///
537    /// let mut map = RHashMap::<u32, u32>::new();
538    ///
539    /// match map.entry(1337) {
540    ///     REntry::Occupied(_) => {
541    ///         unreachable!();
542    ///     }
543    ///     REntry::Vacant(entry) => {
544    ///         assert_eq!(entry.key(), &1337);
545    ///     }
546    /// }
547    ///
548    /// assert_eq!(map.get(&1337), None);
549    ///
550    /// ```
551    pub fn key(&self) -> &K {
552        let vtable = self.vtable();
553
554        vtable.key()(self.entry.as_rref())
555    }
556
557    /// Gets back the key that was passed to `RHashMap::entry`.
558    ///
559    /// # Example
560    ///
561    /// ```
562    /// use abi_stable::std_types::map::{REntry, RHashMap};
563    ///
564    /// let mut map = RHashMap::<String, u32>::new();
565    ///
566    /// match map.entry("lol".into()) {
567    ///     REntry::Occupied(_) => {
568    ///         unreachable!();
569    ///     }
570    ///     REntry::Vacant(entry) => {
571    ///         assert_eq!(entry.into_key(), "lol".to_string());
572    ///     }
573    /// }
574    ///
575    /// assert_eq!(map.get("lol"), None);
576    ///
577    /// ```
578    pub fn into_key(self) -> K {
579        let vtable = self.vtable();
580
581        vtable.fn_into_key()(self)
582    }
583
584    /// Sets the value of the entry, returning a mutable reference to it.
585    ///
586    /// # Example
587    ///
588    /// ```
589    /// use abi_stable::std_types::map::{REntry, RHashMap};
590    ///
591    /// let mut map = RHashMap::<String, u32>::new();
592    ///
593    /// match map.entry("lol".into()) {
594    ///     REntry::Occupied(_) => {
595    ///         unreachable!();
596    ///     }
597    ///     REntry::Vacant(entry) => {
598    ///         assert_eq!(entry.insert(67), &mut 67);
599    ///     }
600    /// }
601    ///
602    /// assert_eq!(map.get("lol"), Some(&67));
603    ///
604    /// ```
605    pub fn insert(self, value: V) -> &'a mut V {
606        let vtable = self.vtable();
607
608        vtable.insert_elem()(self, value)
609    }
610}
611
612impl<K, V> Debug for RVacantEntry<'_, K, V>
613where
614    K: Debug,
615{
616    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
617        f.debug_struct("RVacantEntry")
618            .field("key", self.key())
619            .finish()
620    }
621}
622
623impl<'a, K, V> Drop for RVacantEntry<'a, K, V> {
624    fn drop(&mut self) {
625        let vtable = self.vtable();
626
627        unsafe { vtable.drop_entry()(self.entry.reborrow()) }
628    }
629}
630
631/////////////////////////////////////////////////////////////////////////////////////////////
632
633#[derive(StableAbi)]
634#[repr(C)]
635#[sabi(kind(Prefix), missing_field(panic))]
636pub struct OccupiedVTable<K, V> {
637    drop_entry: unsafe extern "C" fn(RMut<'_, ErasedOccupiedEntry<K, V>>),
638    key: extern "C" fn(RRef<'_, ErasedOccupiedEntry<K, V>>) -> &K,
639    get_elem: extern "C" fn(RRef<'_, ErasedOccupiedEntry<K, V>>) -> &V,
640    get_mut_elem: extern "C" fn(RMut<'_, ErasedOccupiedEntry<K, V>>) -> &mut V,
641    fn_into_mut_elem: extern "C" fn(ROccupiedEntry<'_, K, V>) -> &'_ mut V,
642    insert_elem: extern "C" fn(RMut<'_, ErasedOccupiedEntry<K, V>>, V) -> V,
643    remove: extern "C" fn(ROccupiedEntry<'_, K, V>) -> V,
644}
645
646impl<K, V> OccupiedVTable<K, V> {
647    const VTABLE_REF: OccupiedVTable_Ref<K, V> = OccupiedVTable_Ref(Self::WM_VTABLE.as_prefix());
648
649    staticref! {
650        const WM_VTABLE: WithMetadata<OccupiedVTable<K, V>> = WithMetadata::new(Self::VTABLE)
651    }
652
653    const VTABLE: OccupiedVTable<K, V> = OccupiedVTable {
654        drop_entry: ErasedOccupiedEntry::drop_entry,
655        key: ErasedOccupiedEntry::key,
656        get_elem: ErasedOccupiedEntry::get_elem,
657        get_mut_elem: ErasedOccupiedEntry::get_mut_elem,
658        fn_into_mut_elem: ErasedOccupiedEntry::fn_into_mut_elem,
659        insert_elem: ErasedOccupiedEntry::insert_elem,
660        remove: ErasedOccupiedEntry::remove,
661    };
662}
663
664impl<K, V> ErasedOccupiedEntry<K, V> {
665    unsafe extern "C" fn drop_entry(this: RMut<'_, Self>) {
666        unsafe {
667            extern_fn_panic_handling! {no_early_return;
668                Self::run_downcast_as_mut(this, |this| {
669                    ManuallyDrop::drop(this);
670                })
671            }
672        }
673    }
674    extern "C" fn key(this: RRef<'_, Self>) -> &K {
675        unsafe {
676            extern_fn_panic_handling! {no_early_return;
677                Self::run_downcast_as(
678                    this,
679                    |this| this.key().as_ref()
680                )
681            }
682        }
683    }
684    extern "C" fn get_elem(this: RRef<'_, Self>) -> &V {
685        unsafe {
686            extern_fn_panic_handling! {no_early_return;
687                Self::run_downcast_as(
688                    this,
689                    |this| this.get()
690                )
691            }
692        }
693    }
694    extern "C" fn get_mut_elem(this: RMut<'_, Self>) -> &mut V {
695        unsafe {
696            extern_fn_panic_handling! {no_early_return;
697                Self::run_downcast_as_mut(
698                    this,
699                    |this| this.get_mut()
700                )
701            }
702        }
703    }
704    extern "C" fn fn_into_mut_elem(this: ROccupiedEntry<'_, K, V>) -> &'_ mut V {
705        unsafe {
706            extern_fn_panic_handling! {no_early_return;
707                Self::run_downcast_as_mut(
708                    this.into_inner(),
709                    |this| take_manuallydrop(this).into_mut()
710                )
711            }
712        }
713    }
714    extern "C" fn insert_elem(this: RMut<'_, Self>, elem: V) -> V {
715        unsafe {
716            extern_fn_panic_handling! {no_early_return;
717                Self::run_downcast_as_mut(
718                    this,
719                    |this| this.insert(elem)
720                )
721            }
722        }
723    }
724    extern "C" fn remove(this: ROccupiedEntry<'_, K, V>) -> V {
725        unsafe {
726            extern_fn_panic_handling! {no_early_return;
727                Self::run_downcast_as_mut(
728                    this.into_inner(),
729                    |this| take_manuallydrop(this).remove()
730                )
731            }
732        }
733    }
734}
735
736/////////////////////////////////////////////////////////////////////////////////////////////
737
738#[derive(StableAbi)]
739#[repr(C)]
740#[sabi(kind(Prefix), missing_field(panic))]
741pub struct VacantVTable<K, V> {
742    drop_entry: unsafe extern "C" fn(RMut<'_, ErasedVacantEntry<K, V>>),
743    key: extern "C" fn(RRef<'_, ErasedVacantEntry<K, V>>) -> &K,
744    fn_into_key: extern "C" fn(RVacantEntry<'_, K, V>) -> K,
745    insert_elem: extern "C" fn(RVacantEntry<'_, K, V>, V) -> &'_ mut V,
746}
747
748impl<K, V> VacantVTable<K, V> {
749    const VTABLE_REF: VacantVTable_Ref<K, V> = VacantVTable_Ref(Self::WM_VTABLE.as_prefix());
750
751    staticref! {
752        const WM_VTABLE: WithMetadata<VacantVTable<K, V>> = WithMetadata::new(Self::VTABLE)
753    }
754
755    const VTABLE: VacantVTable<K, V> = VacantVTable {
756        drop_entry: ErasedVacantEntry::drop_entry,
757        key: ErasedVacantEntry::key,
758        fn_into_key: ErasedVacantEntry::fn_into_key,
759        insert_elem: ErasedVacantEntry::insert_elem,
760    };
761}
762
763impl<K, V> ErasedVacantEntry<K, V> {
764    unsafe extern "C" fn drop_entry(this: RMut<'_, Self>) {
765        unsafe {
766            extern_fn_panic_handling! {no_early_return;
767                Self::run_downcast_as_mut(this, |this|{
768                    ManuallyDrop::drop(this);
769                })
770            }
771        }
772    }
773    extern "C" fn key(this: RRef<'_, Self>) -> &K {
774        unsafe {
775            extern_fn_panic_handling! {no_early_return;
776                Self::run_downcast_as(
777                    this,
778                    |this| this.key().as_ref()
779                )
780            }
781        }
782    }
783    extern "C" fn fn_into_key(this: RVacantEntry<'_, K, V>) -> K {
784        unsafe {
785            extern_fn_panic_handling! {no_early_return;
786                Self::run_downcast_as_mut(
787                    this.into_inner(),
788                    |this| take_manuallydrop(this).into_key().into_inner()
789                )
790            }
791        }
792    }
793    extern "C" fn insert_elem(this: RVacantEntry<'_, K, V>, elem: V) -> &'_ mut V {
794        unsafe {
795            extern_fn_panic_handling! {no_early_return;
796                Self::run_downcast_as_mut(
797                    this.into_inner(),
798                    |this| take_manuallydrop(this).insert(elem)
799                )
800            }
801        }
802    }
803}
804
805/////////////////////////////////////////////////////////////////////////////////////////////
806
807/// Copy paste of the unstable `ManuallyDrop::take`
808unsafe fn take_manuallydrop<T>(slot: &mut ManuallyDrop<T>) -> T {
809    unsafe { ManuallyDrop::into_inner(ptr::read(slot)) }
810}