/rust/registry/src/index.crates.io-1949cf8c6b5b557f/dashmap-6.2.1/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 | | mod tests { |
147 | | |
148 | | use crate::DashMap; |
149 | | |
150 | | fn construct_sample_map() -> DashMap<i32, String> { |
151 | | let map = DashMap::new(); |
152 | | |
153 | | map.insert(1, "one".to_string()); |
154 | | |
155 | | map.insert(10, "ten".to_string()); |
156 | | |
157 | | map.insert(27, "twenty seven".to_string()); |
158 | | |
159 | | map.insert(45, "forty five".to_string()); |
160 | | |
161 | | map |
162 | | } |
163 | | |
164 | | #[test] |
165 | | |
166 | | fn test_properties() { |
167 | | let map = construct_sample_map(); |
168 | | |
169 | | let view = map.clone().into_read_only(); |
170 | | |
171 | | assert_eq!(view.is_empty(), map.is_empty()); |
172 | | |
173 | | assert_eq!(view.len(), map.len()); |
174 | | |
175 | | assert_eq!(view.capacity(), map.capacity()); |
176 | | |
177 | | let new_map = view.into_inner(); |
178 | | |
179 | | assert_eq!(new_map.is_empty(), map.is_empty()); |
180 | | |
181 | | assert_eq!(new_map.len(), map.len()); |
182 | | |
183 | | assert_eq!(new_map.capacity(), map.capacity()); |
184 | | } |
185 | | |
186 | | #[test] |
187 | | |
188 | | fn test_get() { |
189 | | let map = construct_sample_map(); |
190 | | |
191 | | let view = map.clone().into_read_only(); |
192 | | |
193 | | for key in map.iter().map(|entry| *entry.key()) { |
194 | | assert!(view.contains_key(&key)); |
195 | | |
196 | | let map_entry = map.get(&key).unwrap(); |
197 | | |
198 | | assert_eq!(view.get(&key).unwrap(), map_entry.value()); |
199 | | |
200 | | let key_value: (&i32, &String) = view.get_key_value(&key).unwrap(); |
201 | | |
202 | | assert_eq!(key_value.0, map_entry.key()); |
203 | | |
204 | | assert_eq!(key_value.1, map_entry.value()); |
205 | | } |
206 | | } |
207 | | |
208 | | #[test] |
209 | | |
210 | | fn test_iters() { |
211 | | let map = construct_sample_map(); |
212 | | |
213 | | let view = map.clone().into_read_only(); |
214 | | |
215 | | let mut visited_items = Vec::new(); |
216 | | |
217 | | for (key, value) in view.iter() { |
218 | | map.contains_key(key); |
219 | | |
220 | | let map_entry = map.get(key).unwrap(); |
221 | | |
222 | | assert_eq!(key, map_entry.key()); |
223 | | |
224 | | assert_eq!(value, map_entry.value()); |
225 | | |
226 | | visited_items.push((key, value)); |
227 | | } |
228 | | |
229 | | let mut visited_keys = Vec::new(); |
230 | | |
231 | | for key in view.keys() { |
232 | | map.contains_key(key); |
233 | | |
234 | | let map_entry = map.get(key).unwrap(); |
235 | | |
236 | | assert_eq!(key, map_entry.key()); |
237 | | |
238 | | assert_eq!(view.get(key).unwrap(), map_entry.value()); |
239 | | |
240 | | visited_keys.push(key); |
241 | | } |
242 | | |
243 | | let mut visited_values = Vec::new(); |
244 | | |
245 | | for value in view.values() { |
246 | | visited_values.push(value); |
247 | | } |
248 | | |
249 | | for entry in map.iter() { |
250 | | let key = entry.key(); |
251 | | |
252 | | let value = entry.value(); |
253 | | |
254 | | assert!(visited_keys.contains(&key)); |
255 | | |
256 | | assert!(visited_values.contains(&value)); |
257 | | |
258 | | assert!(visited_items.contains(&(key, value))); |
259 | | } |
260 | | } |
261 | | } |