typedmap/
dashentry.rs

1//! Entry type for TypedDashMap
2use std::marker::PhantomData;
3
4use crate::bounds::{Bounds, HasBounds};
5use crate::typedvalue::TypedMapValue;
6use crate::TypedMapKey;
7use crate::{dashmap::RefMut, typedkey::TypedKey};
8
9const INVALID_ENTRY: &str = "Broken TypedDashMap: invalid entry";
10
11pub struct OccupiedEntry<'a, K, KB, VB, Marker>
12where
13    K: 'static + TypedMapKey<Marker>,
14    KB: 'static + Bounds + HasBounds<K>,
15    VB: 'static + Bounds + HasBounds<K::Value>,
16{
17    base: dashmap::mapref::entry::OccupiedEntry<'a, TypedKey<KB>, TypedMapValue<VB>>,
18    _phantom: PhantomData<Marker>,
19    _phantom_key: PhantomData<K>,
20}
21
22impl<'a, K, KB, VB, Marker> OccupiedEntry<'a, K, KB, VB, Marker>
23where
24    K: 'static + TypedMapKey<Marker>,
25    KB: 'static + Bounds + HasBounds<K>,
26    VB: 'static + Bounds + HasBounds<K::Value>,
27{
28    #[inline]
29    pub fn into_ref(self) -> RefMut<'a, Marker, K, KB, VB> {
30        let refmut = self.base.into_ref();
31
32        RefMut(refmut, PhantomData, PhantomData)
33    }
34
35    #[inline]
36    pub fn key(&self) -> &K {
37        self.base.key().downcast_ref::<K>().expect(INVALID_ENTRY)
38    }
39
40    #[inline]
41    pub fn remove_entry(self) -> (K, K::Value) {
42        let (k, v) = self.base.remove_entry();
43        let v = v.downcast::<K::Value>().expect(INVALID_ENTRY);
44        let k = k.downcast::<K>().expect(INVALID_ENTRY);
45        (k, v)
46    }
47
48    #[inline]
49    pub fn get(&self) -> &K::Value {
50        self.base
51            .get()
52            .downcast_ref::<K::Value>()
53            .expect(INVALID_ENTRY)
54    }
55
56    #[inline]
57    pub fn get_mut(&mut self) -> &mut K::Value {
58        self.base
59            .get_mut()
60            .downcast_mut::<K::Value>()
61            .expect(INVALID_ENTRY)
62    }
63
64    #[inline]
65    pub fn insert(&mut self, value: K::Value) -> K::Value {
66        let value = TypedMapValue::from_value(value);
67        self.base
68            .insert(value)
69            .downcast::<K::Value>()
70            .expect(INVALID_ENTRY)
71    }
72
73    #[inline]
74    pub fn remove(self) -> K::Value {
75        self.base
76            .remove()
77            .downcast::<K::Value>()
78            .expect(INVALID_ENTRY)
79    }
80}
81
82pub struct VacantEntry<'a, K, KB, VB, Marker>
83where
84    K: 'static + TypedMapKey<Marker>,
85    KB: 'static + Bounds + HasBounds<K>,
86    VB: 'static + Bounds + HasBounds<K::Value>,
87{
88    base: dashmap::mapref::entry::VacantEntry<'a, TypedKey<KB>, TypedMapValue<VB>>,
89    _phantom: PhantomData<Marker>,
90    _phantom_key: PhantomData<K>,
91}
92
93impl<'a, K, KB, VB, Marker> VacantEntry<'a, K, KB, VB, Marker>
94where
95    K: 'static + TypedMapKey<Marker>,
96    KB: 'static + Bounds + HasBounds<K>,
97    VB: 'static + Bounds + HasBounds<K::Value>,
98{
99    #[inline]
100    pub fn key(&self) -> &K {
101        self.base.key().downcast_ref::<K>().expect(INVALID_ENTRY)
102    }
103
104    #[inline]
105    pub fn into_key(self) -> K {
106        self.base.into_key().downcast::<K>().expect(INVALID_ENTRY)
107    }
108
109    #[inline]
110    pub fn insert(self, value: K::Value) -> RefMut<'a, Marker, K, KB, VB> {
111        let value = TypedMapValue::from_value(value);
112        let refmut = self.base.insert(value);
113
114        RefMut(refmut, PhantomData, PhantomData)
115    }
116}
117
118pub enum Entry<'a, K, KB, VB, Marker>
119where
120    K: 'static + TypedMapKey<Marker>,
121    KB: 'static + Bounds + HasBounds<K>,
122    VB: 'static + Bounds + HasBounds<K::Value>,
123{
124    Occupied(OccupiedEntry<'a, K, KB, VB, Marker>),
125    Vacant(VacantEntry<'a, K, KB, VB, Marker>),
126}
127
128pub(crate) fn map_entry<Marker, K, KB, VB>(
129    entry: dashmap::mapref::entry::Entry<'_, TypedKey<KB>, TypedMapValue<VB>>,
130) -> Entry<'_, K, KB, VB, Marker>
131where
132    K: 'static + TypedMapKey<Marker>,
133    KB: 'static + Bounds + HasBounds<K>,
134    VB: 'static + Bounds + HasBounds<K::Value>,
135{
136    match entry {
137        dashmap::mapref::entry::Entry::Occupied(base) => Entry::Occupied(OccupiedEntry {
138            base,
139            _phantom: PhantomData,
140            _phantom_key: PhantomData,
141        }),
142        dashmap::mapref::entry::Entry::Vacant(base) => Entry::Vacant(VacantEntry {
143            base,
144            _phantom: PhantomData,
145            _phantom_key: PhantomData,
146        }),
147    }
148}
149
150impl<'a, Marker, K, KB, VB> Entry<'a, K, KB, VB, Marker>
151where
152    K: 'static + TypedMapKey<Marker>,
153    KB: 'static + Bounds + HasBounds<K>,
154    VB: 'static + Bounds + HasBounds<K::Value>,
155{
156    #[inline]
157    pub fn or_insert(self, default: K::Value) -> RefMut<'a, Marker, K, KB, VB> {
158        match self {
159            Self::Occupied(entry) => entry.into_ref(),
160            Self::Vacant(entry) => entry.insert(default),
161        }
162    }
163
164    #[inline]
165    pub fn or_insert_with<F: FnOnce() -> K::Value>(
166        self,
167        default: F,
168    ) -> RefMut<'a, Marker, K, KB, VB> {
169        match self {
170            Self::Occupied(entry) => entry.into_ref(),
171            Self::Vacant(entry) => entry.insert(default()),
172        }
173    }
174
175    pub fn key(&self) -> &K {
176        match *self {
177            Self::Occupied(ref entry) => entry.key(),
178            Self::Vacant(ref entry) => entry.key(),
179        }
180    }
181
182    pub fn and_modify<F>(self, f: F) -> Self
183    where
184        F: FnOnce(&mut K::Value),
185    {
186        match self {
187            Self::Occupied(mut entry) => {
188                f(entry.get_mut());
189                Self::Occupied(entry)
190            }
191            Self::Vacant(entry) => Self::Vacant(entry),
192        }
193    }
194}
195
196impl<'a, Marker, K, KB, VB> Entry<'a, K, KB, VB, Marker>
197where
198    K: 'static + TypedMapKey<Marker>,
199    K::Value: 'static + Default,
200    KB: 'static + Bounds + HasBounds<K>,
201    VB: 'static + Bounds + HasBounds<K::Value>,
202{
203    pub fn or_default(self) -> RefMut<'a, Marker, K, KB, VB> {
204        match self {
205            Self::Occupied(entry) => entry.into_ref(),
206            Self::Vacant(entry) => entry.insert(Default::default()),
207        }
208    }
209}