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