Coverage Report

Created: 2025-09-27 06:48

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/dashmap-6.1.0/src/mapref/entry.rs
Line
Count
Source
1
use super::one::RefMut;
2
use crate::lock::RwLockWriteGuard;
3
use crate::util::SharedValue;
4
use crate::HashMap;
5
use core::hash::Hash;
6
use core::mem;
7
8
pub enum Entry<'a, K, V> {
9
    Occupied(OccupiedEntry<'a, K, V>),
10
    Vacant(VacantEntry<'a, K, V>),
11
}
12
13
impl<'a, K: Eq + Hash, V> Entry<'a, K, V> {
14
    /// Apply a function to the stored value if it exists.
15
0
    pub fn and_modify(self, f: impl FnOnce(&mut V)) -> Self {
16
0
        match self {
17
0
            Entry::Occupied(mut entry) => {
18
0
                f(entry.get_mut());
19
20
0
                Entry::Occupied(entry)
21
            }
22
23
0
            Entry::Vacant(entry) => Entry::Vacant(entry),
24
        }
25
0
    }
Unexecuted instantiation: <dashmap::mapref::entry::Entry<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>>>::and_modify::<gix_tempfile::registry::cleanup_tempfiles_signal_safe::{closure#0}>
Unexecuted instantiation: <dashmap::mapref::entry::Entry<_, _>>::and_modify::<_>
26
27
    /// Get the key of the entry.
28
0
    pub fn key(&self) -> &K {
29
0
        match *self {
30
0
            Entry::Occupied(ref entry) => entry.key(),
31
0
            Entry::Vacant(ref entry) => entry.key(),
32
        }
33
0
    }
34
35
    /// Into the key of the entry.
36
0
    pub fn into_key(self) -> K {
37
0
        match self {
38
0
            Entry::Occupied(entry) => entry.into_key(),
39
0
            Entry::Vacant(entry) => entry.into_key(),
40
        }
41
0
    }
42
43
    /// Return a mutable reference to the element if it exists,
44
    /// otherwise insert the default and return a mutable reference to that.
45
0
    pub fn or_default(self) -> RefMut<'a, K, V>
46
0
    where
47
0
        V: Default,
48
    {
49
0
        match self {
50
0
            Entry::Occupied(entry) => entry.into_ref(),
51
0
            Entry::Vacant(entry) => entry.insert(V::default()),
52
        }
53
0
    }
54
55
    /// Return a mutable reference to the element if it exists,
56
    /// otherwise a provided value and return a mutable reference to that.
57
0
    pub fn or_insert(self, value: V) -> RefMut<'a, K, V> {
58
0
        match self {
59
0
            Entry::Occupied(entry) => entry.into_ref(),
60
0
            Entry::Vacant(entry) => entry.insert(value),
61
        }
62
0
    }
63
64
    /// Return a mutable reference to the element if it exists,
65
    /// otherwise insert the result of a provided function and return a mutable reference to that.
66
0
    pub fn or_insert_with(self, value: impl FnOnce() -> V) -> RefMut<'a, K, V> {
67
0
        match self {
68
0
            Entry::Occupied(entry) => entry.into_ref(),
69
0
            Entry::Vacant(entry) => entry.insert(value()),
70
        }
71
0
    }
72
73
0
    pub fn or_try_insert_with<E>(
74
0
        self,
75
0
        value: impl FnOnce() -> Result<V, E>,
76
0
    ) -> Result<RefMut<'a, K, V>, E> {
77
0
        match self {
78
0
            Entry::Occupied(entry) => Ok(entry.into_ref()),
79
0
            Entry::Vacant(entry) => Ok(entry.insert(value()?)),
80
        }
81
0
    }
82
83
    /// Sets the value of the entry, and returns a reference to the inserted value.
84
0
    pub fn insert(self, value: V) -> RefMut<'a, K, V> {
85
0
        match self {
86
0
            Entry::Occupied(mut entry) => {
87
0
                entry.insert(value);
88
0
                entry.into_ref()
89
            }
90
0
            Entry::Vacant(entry) => entry.insert(value),
91
        }
92
0
    }
93
94
    /// Sets the value of the entry, and returns an OccupiedEntry.
95
    ///
96
    /// If you are not interested in the occupied entry,
97
    /// consider [`insert`] as it doesn't need to clone the key.
98
    ///
99
    /// [`insert`]: Entry::insert
100
0
    pub fn insert_entry(self, value: V) -> OccupiedEntry<'a, K, V>
101
0
    where
102
0
        K: Clone,
103
    {
104
0
        match self {
105
0
            Entry::Occupied(mut entry) => {
106
0
                entry.insert(value);
107
0
                entry
108
            }
109
0
            Entry::Vacant(entry) => entry.insert_entry(value),
110
        }
111
0
    }
112
}
113
114
pub struct VacantEntry<'a, K, V> {
115
    shard: RwLockWriteGuard<'a, HashMap<K, V>>,
116
    key: K,
117
    hash: u64,
118
    slot: hashbrown::raw::InsertSlot,
119
}
120
121
unsafe impl<'a, K: Eq + Hash + Sync, V: Sync> Send for VacantEntry<'a, K, V> {}
122
unsafe impl<'a, K: Eq + Hash + Sync, V: Sync> Sync for VacantEntry<'a, K, V> {}
123
124
impl<'a, K: Eq + Hash, V> VacantEntry<'a, K, V> {
125
0
    pub(crate) unsafe fn new(
126
0
        shard: RwLockWriteGuard<'a, HashMap<K, V>>,
127
0
        key: K,
128
0
        hash: u64,
129
0
        slot: hashbrown::raw::InsertSlot,
130
0
    ) -> Self {
131
0
        Self {
132
0
            shard,
133
0
            key,
134
0
            hash,
135
0
            slot,
136
0
        }
137
0
    }
Unexecuted instantiation: <dashmap::mapref::entry::VacantEntry<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>>>::new
Unexecuted instantiation: <dashmap::mapref::entry::VacantEntry<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>>>::new
Unexecuted instantiation: <dashmap::mapref::entry::VacantEntry<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>>>::new
Unexecuted instantiation: <dashmap::mapref::entry::VacantEntry<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>>>::new
Unexecuted instantiation: <dashmap::mapref::entry::VacantEntry<_, _>>::new
138
139
0
    pub fn insert(mut self, value: V) -> RefMut<'a, K, V> {
140
        unsafe {
141
0
            let occupied = self.shard.insert_in_slot(
142
0
                self.hash,
143
0
                self.slot,
144
0
                (self.key, SharedValue::new(value)),
145
0
            );
146
147
0
            let (k, v) = occupied.as_ref();
148
149
0
            RefMut::new(self.shard, k, v.as_ptr())
150
        }
151
0
    }
Unexecuted instantiation: <dashmap::mapref::entry::VacantEntry<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>>>::insert
Unexecuted instantiation: <dashmap::mapref::entry::VacantEntry<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>>>::insert
Unexecuted instantiation: <dashmap::mapref::entry::VacantEntry<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>>>::insert
Unexecuted instantiation: <dashmap::mapref::entry::VacantEntry<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>>>::insert
Unexecuted instantiation: <dashmap::mapref::entry::VacantEntry<_, _>>::insert
152
153
    /// Sets the value of the entry with the VacantEntry’s key, and returns an OccupiedEntry.
154
0
    pub fn insert_entry(mut self, value: V) -> OccupiedEntry<'a, K, V>
155
0
    where
156
0
        K: Clone,
157
    {
158
        unsafe {
159
0
            let bucket = self.shard.insert_in_slot(
160
0
                self.hash,
161
0
                self.slot,
162
0
                (self.key.clone(), SharedValue::new(value)),
163
0
            );
164
165
0
            OccupiedEntry::new(self.shard, self.key, bucket)
166
        }
167
0
    }
168
169
0
    pub fn into_key(self) -> K {
170
0
        self.key
171
0
    }
172
173
0
    pub fn key(&self) -> &K {
174
0
        &self.key
175
0
    }
176
}
177
178
pub struct OccupiedEntry<'a, K, V> {
179
    shard: RwLockWriteGuard<'a, HashMap<K, V>>,
180
    bucket: hashbrown::raw::Bucket<(K, SharedValue<V>)>,
181
    key: K,
182
}
183
184
unsafe impl<'a, K: Eq + Hash + Sync, V: Sync> Send for OccupiedEntry<'a, K, V> {}
185
unsafe impl<'a, K: Eq + Hash + Sync, V: Sync> Sync for OccupiedEntry<'a, K, V> {}
186
187
impl<'a, K: Eq + Hash, V> OccupiedEntry<'a, K, V> {
188
0
    pub(crate) unsafe fn new(
189
0
        shard: RwLockWriteGuard<'a, HashMap<K, V>>,
190
0
        key: K,
191
0
        bucket: hashbrown::raw::Bucket<(K, SharedValue<V>)>,
192
0
    ) -> Self {
193
0
        Self { shard, bucket, key }
194
0
    }
Unexecuted instantiation: <dashmap::mapref::entry::OccupiedEntry<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>>>::new
Unexecuted instantiation: <dashmap::mapref::entry::OccupiedEntry<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>>>::new
Unexecuted instantiation: <dashmap::mapref::entry::OccupiedEntry<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>>>::new
Unexecuted instantiation: <dashmap::mapref::entry::OccupiedEntry<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>>>::new
Unexecuted instantiation: <dashmap::mapref::entry::OccupiedEntry<_, _>>::new
195
196
0
    pub fn get(&self) -> &V {
197
0
        unsafe { self.bucket.as_ref().1.get() }
198
0
    }
199
200
0
    pub fn get_mut(&mut self) -> &mut V {
201
0
        unsafe { self.bucket.as_mut().1.get_mut() }
202
0
    }
Unexecuted instantiation: <dashmap::mapref::entry::OccupiedEntry<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>>>::get_mut
Unexecuted instantiation: <dashmap::mapref::entry::OccupiedEntry<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>>>::get_mut
Unexecuted instantiation: <dashmap::mapref::entry::OccupiedEntry<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>>>::get_mut
Unexecuted instantiation: <dashmap::mapref::entry::OccupiedEntry<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>>>::get_mut
Unexecuted instantiation: <dashmap::mapref::entry::OccupiedEntry<_, _>>::get_mut
203
204
0
    pub fn insert(&mut self, value: V) -> V {
205
0
        mem::replace(self.get_mut(), value)
206
0
    }
Unexecuted instantiation: <dashmap::mapref::entry::OccupiedEntry<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>>>::insert
Unexecuted instantiation: <dashmap::mapref::entry::OccupiedEntry<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>>>::insert
Unexecuted instantiation: <dashmap::mapref::entry::OccupiedEntry<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>>>::insert
Unexecuted instantiation: <dashmap::mapref::entry::OccupiedEntry<usize, core::option::Option<gix_tempfile::forksafe::ForksafeTempfile>>>::insert
Unexecuted instantiation: <dashmap::mapref::entry::OccupiedEntry<_, _>>::insert
207
208
0
    pub fn into_ref(self) -> RefMut<'a, K, V> {
209
        unsafe {
210
0
            let (k, v) = self.bucket.as_ref();
211
0
            RefMut::new(self.shard, k, v.as_ptr())
212
        }
213
0
    }
214
215
0
    pub fn into_key(self) -> K {
216
0
        self.key
217
0
    }
218
219
0
    pub fn key(&self) -> &K {
220
0
        unsafe { &self.bucket.as_ref().0 }
221
0
    }
222
223
0
    pub fn remove(mut self) -> V {
224
0
        let ((_k, v), _) = unsafe { self.shard.remove(self.bucket) };
225
0
        v.into_inner()
226
0
    }
227
228
0
    pub fn remove_entry(mut self) -> (K, V) {
229
0
        let ((k, v), _) = unsafe { self.shard.remove(self.bucket) };
230
0
        (k, v.into_inner())
231
0
    }
232
233
0
    pub fn replace_entry(self, value: V) -> (K, V) {
234
0
        let (k, v) = mem::replace(
235
0
            unsafe { self.bucket.as_mut() },
236
0
            (self.key, SharedValue::new(value)),
237
0
        );
238
0
        (k, v.into_inner())
239
0
    }
240
}
241
242
#[cfg(test)]
243
mod tests {
244
    use crate::DashMap;
245
246
    use super::*;
247
248
    #[test]
249
    fn test_insert_entry_into_vacant() {
250
        let map: DashMap<u32, u32> = DashMap::new();
251
252
        let entry = map.entry(1);
253
254
        assert!(matches!(entry, Entry::Vacant(_)));
255
256
        let entry = entry.insert_entry(2);
257
258
        assert_eq!(*entry.get(), 2);
259
260
        drop(entry);
261
262
        assert_eq!(*map.get(&1).unwrap(), 2);
263
    }
264
265
    #[test]
266
    fn test_insert_entry_into_occupied() {
267
        let map: DashMap<u32, u32> = DashMap::new();
268
269
        map.insert(1, 1000);
270
271
        let entry = map.entry(1);
272
273
        assert!(matches!(&entry, Entry::Occupied(entry) if *entry.get() == 1000));
274
275
        let entry = entry.insert_entry(2);
276
277
        assert_eq!(*entry.get(), 2);
278
279
        drop(entry);
280
281
        assert_eq!(*map.get(&1).unwrap(), 2);
282
    }
283
}