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}