dashmap/
read_only.rs

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