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 crossbeam_utils::CachePadded;
9use std::collections::hash_map::RandomState;
10
11/// A read-only view into a `DashMap`. Allows to obtain raw references to the stored values.
12pub struct ReadOnlyView<K, V, S = RandomState> {
13    pub(crate) map: DashMap<K, V, S>,
14}
15
16impl<K: Eq + Hash + Clone, V: Clone, S: Clone> Clone for ReadOnlyView<K, V, S> {
17    fn clone(&self) -> Self {
18        Self {
19            map: self.map.clone(),
20        }
21    }
22}
23
24impl<K: Eq + Hash + fmt::Debug, V: fmt::Debug, S: BuildHasher + Clone> fmt::Debug
25    for ReadOnlyView<K, V, S>
26{
27    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
28        self.map.fmt(f)
29    }
30}
31
32impl<K, V, S> ReadOnlyView<K, V, S> {
33    pub(crate) fn new(map: DashMap<K, V, S>) -> Self {
34        Self { map }
35    }
36
37    /// Consumes this `ReadOnlyView`, returning the underlying `DashMap`.
38    pub fn into_inner(self) -> DashMap<K, V, S> {
39        self.map
40    }
41}
42
43impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone> ReadOnlyView<K, V, S> {
44    /// Returns the number of elements in the map.
45    pub fn len(&self) -> usize {
46        self.map.len()
47    }
48
49    /// Returns `true` if the map contains no elements.
50    pub fn is_empty(&self) -> bool {
51        self.map.is_empty()
52    }
53
54    /// Returns the number of elements the map can hold without reallocating.
55    pub fn capacity(&self) -> usize {
56        self.map.capacity()
57    }
58
59    /// Returns `true` if the map contains a value for the specified key.
60    pub fn contains_key<Q>(&'a self, key: &Q) -> bool
61    where
62        K: Borrow<Q>,
63        Q: Hash + Eq + ?Sized,
64    {
65        self.get(key).is_some()
66    }
67
68    /// Returns a reference to the value corresponding to the key.
69    pub fn get<Q>(&'a self, key: &Q) -> Option<&'a V>
70    where
71        K: Borrow<Q>,
72        Q: Hash + Eq + ?Sized,
73    {
74        self.get_key_value(key).map(|(_k, v)| v)
75    }
76
77    /// Returns the key-value pair corresponding to the supplied key.
78    pub fn get_key_value<Q>(&'a self, key: &Q) -> Option<(&'a K, &'a V)>
79    where
80        K: Borrow<Q>,
81        Q: Hash + Eq + ?Sized,
82    {
83        let hash = self.map.hash_u64(&key);
84
85        let idx = self.map.determine_shard(hash as usize);
86
87        let shard = unsafe { self.map._get_read_shard(idx) };
88
89        shard.find(hash, |(k, _v)| key == k.borrow()).map(|b| {
90            let (k, v) = unsafe { b.as_ref() };
91            (k, v.get())
92        })
93    }
94
95    /// An iterator visiting all key-value pairs in arbitrary order. The iterator element type is `(&'a K, &'a V)`.
96    pub fn iter(&'a self) -> impl Iterator<Item = (&'a K, &'a V)> + 'a {
97        unsafe {
98            (0..self.map._shard_count())
99                .map(move |shard_i| self.map._get_read_shard(shard_i))
100                .flat_map(|shard| shard.iter())
101                .map(|b| {
102                    let (k, v) = b.as_ref();
103                    (k, v.get())
104                })
105        }
106    }
107
108    /// An iterator visiting all keys in arbitrary order. The iterator element type is `&'a K`.
109    pub fn keys(&'a self) -> impl Iterator<Item = &'a K> + 'a {
110        self.iter().map(|(k, _v)| k)
111    }
112
113    /// An iterator visiting all values in arbitrary order. The iterator element type is `&'a V`.
114    pub fn values(&'a self) -> impl Iterator<Item = &'a V> + 'a {
115        self.iter().map(|(_k, v)| v)
116    }
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            pub(crate) fn shards(&self) -> &[CachePadded<RwLock<HashMap<K, V>>>] {
139                &self.map.shards
140            }
141        }
142    }
143}
144
145#[cfg(test)]
146
147mod 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}