Coverage Report

Created: 2026-06-30 06:48

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/dashmap-6.2.1/src/read_only.rs
Line
Count
Source
1
use crate::lock::RwLock;
2
use crate::t::Map;
3
use crate::{DashMap, HashMap};
4
use cfg_if::cfg_if;
5
use core::borrow::Borrow;
6
use core::fmt;
7
use core::hash::{BuildHasher, Hash};
8
use crossbeam_utils::CachePadded;
9
use std::collections::hash_map::RandomState;
10
11
/// A read-only view into a `DashMap`. Allows to obtain raw references to the stored values.
12
pub struct ReadOnlyView<K, V, S = RandomState> {
13
    pub(crate) map: DashMap<K, V, S>,
14
}
15
16
impl<K: Eq + Hash + Clone, V: Clone, S: Clone> Clone for ReadOnlyView<K, V, S> {
17
0
    fn clone(&self) -> Self {
18
0
        Self {
19
0
            map: self.map.clone(),
20
0
        }
21
0
    }
22
}
23
24
impl<K: Eq + Hash + fmt::Debug, V: fmt::Debug, S: BuildHasher + Clone> fmt::Debug
25
    for ReadOnlyView<K, V, S>
26
{
27
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
28
0
        self.map.fmt(f)
29
0
    }
30
}
31
32
impl<K, V, S> ReadOnlyView<K, V, S> {
33
0
    pub(crate) fn new(map: DashMap<K, V, S>) -> Self {
34
0
        Self { map }
35
0
    }
36
37
    /// Consumes this `ReadOnlyView`, returning the underlying `DashMap`.
38
0
    pub fn into_inner(self) -> DashMap<K, V, S> {
39
0
        self.map
40
0
    }
41
}
42
43
impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone> ReadOnlyView<K, V, S> {
44
    /// Returns the number of elements in the map.
45
0
    pub fn len(&self) -> usize {
46
0
        self.map.len()
47
0
    }
48
49
    /// Returns `true` if the map contains no elements.
50
0
    pub fn is_empty(&self) -> bool {
51
0
        self.map.is_empty()
52
0
    }
53
54
    /// Returns the number of elements the map can hold without reallocating.
55
0
    pub fn capacity(&self) -> usize {
56
0
        self.map.capacity()
57
0
    }
58
59
    /// Returns `true` if the map contains a value for the specified key.
60
0
    pub fn contains_key<Q>(&'a self, key: &Q) -> bool
61
0
    where
62
0
        K: Borrow<Q>,
63
0
        Q: Hash + Eq + ?Sized,
64
    {
65
0
        self.get(key).is_some()
66
0
    }
67
68
    /// Returns a reference to the value corresponding to the key.
69
0
    pub fn get<Q>(&'a self, key: &Q) -> Option<&'a V>
70
0
    where
71
0
        K: Borrow<Q>,
72
0
        Q: Hash + Eq + ?Sized,
73
    {
74
0
        self.get_key_value(key).map(|(_k, v)| v)
75
0
    }
76
77
    /// Returns the key-value pair corresponding to the supplied key.
78
0
    pub fn get_key_value<Q>(&'a self, key: &Q) -> Option<(&'a K, &'a V)>
79
0
    where
80
0
        K: Borrow<Q>,
81
0
        Q: Hash + Eq + ?Sized,
82
    {
83
0
        let hash = self.map.hash_u64(&key);
84
85
0
        let idx = self.map.determine_shard(hash as usize);
86
87
0
        let shard = unsafe { self.map._get_read_shard(idx) };
88
89
0
        shard.find(hash, |(k, _v)| key == k.borrow()).map(|b| {
90
0
            let (k, v) = unsafe { b.as_ref() };
91
0
            (k, v.get())
92
0
        })
93
0
    }
94
95
    /// An iterator visiting all key-value pairs in arbitrary order. The iterator element type is `(&'a K, &'a V)`.
96
0
    pub fn iter(&'a self) -> impl Iterator<Item = (&'a K, &'a V)> + 'a {
97
        unsafe {
98
0
            (0..self.map._shard_count())
99
0
                .map(move |shard_i| self.map._get_read_shard(shard_i))
100
0
                .flat_map(|shard| shard.iter())
101
0
                .map(|b| {
102
0
                    let (k, v) = b.as_ref();
103
0
                    (k, v.get())
104
0
                })
105
        }
106
0
    }
107
108
    /// An iterator visiting all keys in arbitrary order. The iterator element type is `&'a K`.
109
0
    pub fn keys(&'a self) -> impl Iterator<Item = &'a K> + 'a {
110
0
        self.iter().map(|(k, _v)| k)
111
0
    }
112
113
    /// An iterator visiting all values in arbitrary order. The iterator element type is `&'a V`.
114
0
    pub fn values(&'a self) -> impl Iterator<Item = &'a V> + 'a {
115
0
        self.iter().map(|(_k, v)| v)
116
0
    }
117
118
    cfg_if! {
119
        if #[cfg(feature = "raw-api")] {
120
            /// Allows you to peek at the inner shards that store your data.
121
            /// You should probably not use this unless you know what you are doing.
122
            ///
123
            /// Requires the `raw-api` feature to be enabled.
124
            ///
125
            /// # Examples
126
            ///
127
            /// ```
128
            /// use dashmap::DashMap;
129
            ///
130
            /// let map = DashMap::<(), ()>::new().into_read_only();
131
            /// println!("Amount of shards: {}", map.shards().len());
132
            /// ```
133
            pub fn shards(&self) -> &[CachePadded<RwLock<HashMap<K, V>>>] {
134
                &self.map.shards
135
            }
136
        } else {
137
            #[allow(dead_code)]
138
0
            pub(crate) fn shards(&self) -> &[CachePadded<RwLock<HashMap<K, V>>>] {
139
0
                &self.map.shards
140
0
            }
141
        }
142
    }
143
}
144
145
#[cfg(test)]
146
mod tests {
147
148
    use crate::DashMap;
149
150
    fn construct_sample_map() -> DashMap<i32, String> {
151
        let map = DashMap::new();
152
153
        map.insert(1, "one".to_string());
154
155
        map.insert(10, "ten".to_string());
156
157
        map.insert(27, "twenty seven".to_string());
158
159
        map.insert(45, "forty five".to_string());
160
161
        map
162
    }
163
164
    #[test]
165
166
    fn test_properties() {
167
        let map = construct_sample_map();
168
169
        let view = map.clone().into_read_only();
170
171
        assert_eq!(view.is_empty(), map.is_empty());
172
173
        assert_eq!(view.len(), map.len());
174
175
        assert_eq!(view.capacity(), map.capacity());
176
177
        let new_map = view.into_inner();
178
179
        assert_eq!(new_map.is_empty(), map.is_empty());
180
181
        assert_eq!(new_map.len(), map.len());
182
183
        assert_eq!(new_map.capacity(), map.capacity());
184
    }
185
186
    #[test]
187
188
    fn test_get() {
189
        let map = construct_sample_map();
190
191
        let view = map.clone().into_read_only();
192
193
        for key in map.iter().map(|entry| *entry.key()) {
194
            assert!(view.contains_key(&key));
195
196
            let map_entry = map.get(&key).unwrap();
197
198
            assert_eq!(view.get(&key).unwrap(), map_entry.value());
199
200
            let key_value: (&i32, &String) = view.get_key_value(&key).unwrap();
201
202
            assert_eq!(key_value.0, map_entry.key());
203
204
            assert_eq!(key_value.1, map_entry.value());
205
        }
206
    }
207
208
    #[test]
209
210
    fn test_iters() {
211
        let map = construct_sample_map();
212
213
        let view = map.clone().into_read_only();
214
215
        let mut visited_items = Vec::new();
216
217
        for (key, value) in view.iter() {
218
            map.contains_key(key);
219
220
            let map_entry = map.get(key).unwrap();
221
222
            assert_eq!(key, map_entry.key());
223
224
            assert_eq!(value, map_entry.value());
225
226
            visited_items.push((key, value));
227
        }
228
229
        let mut visited_keys = Vec::new();
230
231
        for key in view.keys() {
232
            map.contains_key(key);
233
234
            let map_entry = map.get(key).unwrap();
235
236
            assert_eq!(key, map_entry.key());
237
238
            assert_eq!(view.get(key).unwrap(), map_entry.value());
239
240
            visited_keys.push(key);
241
        }
242
243
        let mut visited_values = Vec::new();
244
245
        for value in view.values() {
246
            visited_values.push(value);
247
        }
248
249
        for entry in map.iter() {
250
            let key = entry.key();
251
252
            let value = entry.value();
253
254
            assert!(visited_keys.contains(&key));
255
256
            assert!(visited_values.contains(&value));
257
258
            assert!(visited_items.contains(&(key, value)));
259
        }
260
    }
261
}