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 std::collections::hash_map::RandomState;
9 
10 /// A read-only view into a `DashMap`. Allows to obtain raw references to the stored values.
11 pub struct ReadOnlyView<K, V, S = RandomState> {
12     pub(crate) map: DashMap<K, V, S>,
13 }
14 
15 impl<K: Eq + Hash + Clone, V: Clone, S: Clone> Clone for ReadOnlyView<K, V, S> {
clone(&self) -> Self16     fn clone(&self) -> Self {
17         Self {
18             map: self.map.clone(),
19         }
20     }
21 }
22 
23 impl<K: Eq + Hash + fmt::Debug, V: fmt::Debug, S: BuildHasher + Clone> fmt::Debug
24     for ReadOnlyView<K, V, S>
25 {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result26     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
27         self.map.fmt(f)
28     }
29 }
30 
31 impl<K, V, S> ReadOnlyView<K, V, S> {
new(map: DashMap<K, V, S>) -> Self32     pub(crate) fn new(map: DashMap<K, V, S>) -> Self {
33         Self { map }
34     }
35 
36     /// Consumes this `ReadOnlyView`, returning the underlying `DashMap`.
into_inner(self) -> DashMap<K, V, S>37     pub fn into_inner(self) -> DashMap<K, V, S> {
38         self.map
39     }
40 }
41 
42 impl<'a, K: 'a + Eq + Hash, V: 'a, S: BuildHasher + Clone> ReadOnlyView<K, V, S> {
43     /// Returns the number of elements in the map.
len(&self) -> usize44     pub fn len(&self) -> usize {
45         self.map.len()
46     }
47 
48     /// Returns `true` if the map contains no elements.
is_empty(&self) -> bool49     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.
capacity(&self) -> usize54     pub fn capacity(&self) -> usize {
55         self.map.capacity()
56     }
57 
58     /// Returns `true` if the map contains a value for the specified key.
contains_key<Q>(&'a self, key: &Q) -> bool where K: Borrow<Q>, Q: Hash + Eq + ?Sized,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.
get<Q>(&'a self, key: &Q) -> Option<&'a V> where K: Borrow<Q>, Q: Hash + Eq + ?Sized,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.
get_key_value<Q>(&'a self, key: &Q) -> Option<(&'a K, &'a V)> where K: Borrow<Q>, Q: Hash + Eq + ?Sized,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 
shard_read_iter(&'a self) -> impl Iterator<Item = &'a HashMap<K, V, S>> + 'a103     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)`.
iter(&'a self) -> impl Iterator<Item = (&'a K, &'a V)> + 'a109     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`.
keys(&'a self) -> impl Iterator<Item = &'a K> + 'a116     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`.
values(&'a self) -> impl Iterator<Item = &'a V> + 'a121     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 
156 mod tests {
157 
158     use crate::DashMap;
159 
construct_sample_map() -> DashMap<i32, String>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 
test_properties()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 
test_get()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 
test_iters()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 }
272