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
11pub 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 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 pub fn len(&self) -> usize {
46 self.map.len()
47 }
48
49 pub fn is_empty(&self) -> bool {
51 self.map.is_empty()
52 }
53
54 pub fn capacity(&self) -> usize {
56 self.map.capacity()
57 }
58
59 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 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 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 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 pub fn keys(&'a self) -> impl Iterator<Item = &'a K> + 'a {
110 self.iter().map(|(k, _v)| k)
111 }
112
113 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 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}