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/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
147
mod tests {
148
149
    use crate::DashMap;
150
151
    fn construct_sample_map() -> DashMap<i32, String> {
152
        let map = DashMap::new();
153
154
        map.insert(1, "one".to_string());
155
156
        map.insert(10, "ten".to_string());
157
158
        map.insert(27, "twenty seven".to_string());
159
160
        map.insert(45, "forty five".to_string());
161
162
        map
163
    }
164
165
    #[test]
166
167
    fn test_properties() {
168
        let map = construct_sample_map();
169
170
        let view = map.clone().into_read_only();
171
172
        assert_eq!(view.is_empty(), map.is_empty());
173
174
        assert_eq!(view.len(), map.len());
175
176
        assert_eq!(view.capacity(), map.capacity());
177
178
        let new_map = view.into_inner();
179
180
        assert_eq!(new_map.is_empty(), map.is_empty());
181
182
        assert_eq!(new_map.len(), map.len());
183
184
        assert_eq!(new_map.capacity(), map.capacity());
185
    }
186
187
    #[test]
188
189
    fn test_get() {
190
        let map = construct_sample_map();
191
192
        let view = map.clone().into_read_only();
193
194
        for key in map.iter().map(|entry| *entry.key()) {
195
            assert!(view.contains_key(&key));
196
197
            let map_entry = map.get(&key).unwrap();
198
199
            assert_eq!(view.get(&key).unwrap(), map_entry.value());
200
201
            let key_value: (&i32, &String) = view.get_key_value(&key).unwrap();
202
203
            assert_eq!(key_value.0, map_entry.key());
204
205
            assert_eq!(key_value.1, map_entry.value());
206
        }
207
    }
208
209
    #[test]
210
211
    fn test_iters() {
212
        let map = construct_sample_map();
213
214
        let view = map.clone().into_read_only();
215
216
        let mut visited_items = Vec::new();
217
218
        for (key, value) in view.iter() {
219
            map.contains_key(key);
220
221
            let map_entry = map.get(key).unwrap();
222
223
            assert_eq!(key, map_entry.key());
224
225
            assert_eq!(value, map_entry.value());
226
227
            visited_items.push((key, value));
228
        }
229
230
        let mut visited_keys = Vec::new();
231
232
        for key in view.keys() {
233
            map.contains_key(key);
234
235
            let map_entry = map.get(key).unwrap();
236
237
            assert_eq!(key, map_entry.key());
238
239
            assert_eq!(view.get(key).unwrap(), map_entry.value());
240
241
            visited_keys.push(key);
242
        }
243
244
        let mut visited_values = Vec::new();
245
246
        for value in view.values() {
247
            visited_values.push(value);
248
        }
249
250
        for entry in map.iter() {
251
            let key = entry.key();
252
253
            let value = entry.value();
254
255
            assert!(visited_keys.contains(&key));
256
257
            assert!(visited_values.contains(&value));
258
259
            assert!(visited_items.contains(&(key, value)));
260
        }
261
    }
262
}