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
10pub 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 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 pub fn len(&self) -> usize {
45 self.map.len()
46 }
47
48 pub fn is_empty(&self) -> bool {
50 self.map.is_empty()
51 }
52
53 pub fn capacity(&self) -> usize {
55 self.map.capacity()
56 }
57
58 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 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 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 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 pub fn keys(&'a self) -> impl Iterator<Item = &'a K> + 'a {
117 self.shard_read_iter().flat_map(|shard| shard.keys())
118 }
119
120 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 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}