dashmap/
read_only.rs

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