1 use crate::iter_set::{Iter, OwningIter};
2 #[cfg(feature = "raw-api")]
3 use crate::lock::RwLock;
4 use crate::setref::one::Ref;
5 use crate::DashMap;
6 #[cfg(feature = "raw-api")]
7 use crate::HashMap;
8 use cfg_if::cfg_if;
9 use core::borrow::Borrow;
10 use core::fmt;
11 use core::hash::{BuildHasher, Hash};
12 use core::iter::FromIterator;
13 use std::collections::hash_map::RandomState;
14 
15 /// DashSet is a thin wrapper around [`DashMap`] using `()` as the value type. It uses
16 /// methods and types which are more convenient to work with on a set.
17 ///
18 /// [`DashMap`]: struct.DashMap.html
19 pub struct DashSet<K, S = RandomState> {
20     pub(crate) inner: DashMap<K, (), S>,
21 }
22 
23 impl<K: Eq + Hash + fmt::Debug, S: BuildHasher + Clone> fmt::Debug for DashSet<K, S> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result24     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
25         fmt::Debug::fmt(&self.inner, f)
26     }
27 }
28 
29 impl<K: Eq + Hash + Clone, S: Clone> Clone for DashSet<K, S> {
clone(&self) -> Self30     fn clone(&self) -> Self {
31         Self {
32             inner: self.inner.clone(),
33         }
34     }
35 
clone_from(&mut self, source: &Self)36     fn clone_from(&mut self, source: &Self) {
37         self.inner.clone_from(&source.inner)
38     }
39 }
40 
41 impl<K, S> Default for DashSet<K, S>
42 where
43     K: Eq + Hash,
44     S: Default + BuildHasher + Clone,
45 {
default() -> Self46     fn default() -> Self {
47         Self::with_hasher(Default::default())
48     }
49 }
50 
51 impl<'a, K: 'a + Eq + Hash> DashSet<K, RandomState> {
52     /// Creates a new DashSet with a capacity of 0.
53     ///
54     /// # Examples
55     ///
56     /// ```
57     /// use dashmap::DashSet;
58     ///
59     /// let games = DashSet::new();
60     /// games.insert("Veloren");
61     /// ```
new() -> Self62     pub fn new() -> Self {
63         Self::with_hasher(RandomState::default())
64     }
65 
66     /// Creates a new DashMap with a specified starting capacity.
67     ///
68     /// # Examples
69     ///
70     /// ```
71     /// use dashmap::DashSet;
72     ///
73     /// let numbers = DashSet::with_capacity(2);
74     /// numbers.insert(2);
75     /// numbers.insert(8);
76     /// ```
with_capacity(capacity: usize) -> Self77     pub fn with_capacity(capacity: usize) -> Self {
78         Self::with_capacity_and_hasher(capacity, RandomState::default())
79     }
80 }
81 
82 impl<'a, K: 'a + Eq + Hash, S: BuildHasher + Clone> DashSet<K, S> {
83     /// Creates a new DashMap with a capacity of 0 and the provided hasher.
84     ///
85     /// # Examples
86     ///
87     /// ```
88     /// use dashmap::DashSet;
89     /// use std::collections::hash_map::RandomState;
90     ///
91     /// let s = RandomState::new();
92     /// let games = DashSet::with_hasher(s);
93     /// games.insert("Veloren");
94     /// ```
with_hasher(hasher: S) -> Self95     pub fn with_hasher(hasher: S) -> Self {
96         Self::with_capacity_and_hasher(0, hasher)
97     }
98 
99     /// Creates a new DashMap with a specified starting capacity and hasher.
100     ///
101     /// # Examples
102     ///
103     /// ```
104     /// use dashmap::DashSet;
105     /// use std::collections::hash_map::RandomState;
106     ///
107     /// let s = RandomState::new();
108     /// let numbers = DashSet::with_capacity_and_hasher(2, s);
109     /// numbers.insert(2);
110     /// numbers.insert(8);
111     /// ```
with_capacity_and_hasher(capacity: usize, hasher: S) -> Self112     pub fn with_capacity_and_hasher(capacity: usize, hasher: S) -> Self {
113         Self {
114             inner: DashMap::with_capacity_and_hasher(capacity, hasher),
115         }
116     }
117 
118     /// Hash a given item to produce a usize.
119     /// Uses the provided or default HashBuilder.
hash_usize<T: Hash>(&self, item: &T) -> usize120     pub fn hash_usize<T: Hash>(&self, item: &T) -> usize {
121         self.inner.hash_usize(item)
122     }
123 
124     cfg_if! {
125         if #[cfg(feature = "raw-api")] {
126             /// Allows you to peek at the inner shards that store your data.
127             /// You should probably not use this unless you know what you are doing.
128             ///
129             /// Requires the `raw-api` feature to be enabled.
130             ///
131             /// # Examples
132             ///
133             /// ```
134             /// use dashmap::DashSet;
135             ///
136             /// let set = DashSet::<()>::new();
137             /// println!("Amount of shards: {}", set.shards().len());
138             /// ```
139             pub fn shards(&self) -> &[RwLock<HashMap<K, (), S>>] {
140                 self.inner.shards()
141             }
142         }
143     }
144 
145     cfg_if! {
146         if #[cfg(feature = "raw-api")] {
147             /// Finds which shard a certain key is stored in.
148             /// You should probably not use this unless you know what you are doing.
149             /// Note that shard selection is dependent on the default or provided HashBuilder.
150             ///
151             /// Requires the `raw-api` feature to be enabled.
152             ///
153             /// # Examples
154             ///
155             /// ```
156             /// use dashmap::DashSet;
157             ///
158             /// let set = DashSet::new();
159             /// set.insert("coca-cola");
160             /// println!("coca-cola is stored in shard: {}", set.determine_map("coca-cola"));
161             /// ```
162             pub fn determine_map<Q>(&self, key: &Q) -> usize
163             where
164                 K: Borrow<Q>,
165                 Q: Hash + Eq + ?Sized,
166             {
167                 self.inner.determine_map(key)
168             }
169         }
170     }
171 
172     cfg_if! {
173         if #[cfg(feature = "raw-api")] {
174             /// Finds which shard a certain hash is stored in.
175             ///
176             /// Requires the `raw-api` feature to be enabled.
177             ///
178             /// # Examples
179             ///
180             /// ```
181             /// use dashmap::DashSet;
182             ///
183             /// let set: DashSet<i32> = DashSet::new();
184             /// let key = "key";
185             /// let hash = set.hash_usize(&key);
186             /// println!("hash is stored in shard: {}", set.determine_shard(hash));
187             /// ```
188             pub fn determine_shard(&self, hash: usize) -> usize {
189                 self.inner.determine_shard(hash)
190             }
191         }
192     }
193 
194     /// Inserts a key into the set. Returns true if the key was not already in the set.
195     ///
196     /// # Examples
197     ///
198     /// ```
199     /// use dashmap::DashSet;
200     ///
201     /// let set = DashSet::new();
202     /// set.insert("I am the key!");
203     /// ```
insert(&self, key: K) -> bool204     pub fn insert(&self, key: K) -> bool {
205         self.inner.insert(key, ()).is_none()
206     }
207 
208     /// Removes an entry from the map, returning the key if it existed in the map.
209     ///
210     /// # Examples
211     ///
212     /// ```
213     /// use dashmap::DashSet;
214     ///
215     /// let soccer_team = DashSet::new();
216     /// soccer_team.insert("Jack");
217     /// assert_eq!(soccer_team.remove("Jack").unwrap(), "Jack");
218     /// ```
remove<Q>(&self, key: &Q) -> Option<K> where K: Borrow<Q>, Q: Hash + Eq + ?Sized,219     pub fn remove<Q>(&self, key: &Q) -> Option<K>
220     where
221         K: Borrow<Q>,
222         Q: Hash + Eq + ?Sized,
223     {
224         self.inner.remove(key).map(|(k, _)| k)
225     }
226 
227     /// Removes an entry from the set, returning the key
228     /// if the entry existed and the provided conditional function returned true.
229     ///
230     /// ```
231     /// use dashmap::DashSet;
232     ///
233     /// let soccer_team = DashSet::new();
234     /// soccer_team.insert("Sam");
235     /// soccer_team.remove_if("Sam", |player| player.starts_with("Ja"));
236     /// assert!(soccer_team.contains("Sam"));
237     /// ```
238     /// ```
239     /// use dashmap::DashSet;
240     ///
241     /// let soccer_team = DashSet::new();
242     /// soccer_team.insert("Sam");
243     /// soccer_team.remove_if("Jacob", |player| player.starts_with("Ja"));
244     /// assert!(!soccer_team.contains("Jacob"));
245     /// ```
remove_if<Q>(&self, key: &Q, f: impl FnOnce(&K) -> bool) -> Option<K> where K: Borrow<Q>, Q: Hash + Eq + ?Sized,246     pub fn remove_if<Q>(&self, key: &Q, f: impl FnOnce(&K) -> bool) -> Option<K>
247     where
248         K: Borrow<Q>,
249         Q: Hash + Eq + ?Sized,
250     {
251         // TODO: Don't create another closure around f
252         self.inner.remove_if(key, |k, _| f(k)).map(|(k, _)| k)
253     }
254 
255     /// Creates an iterator over a DashMap yielding immutable references.
256     ///
257     /// # Examples
258     ///
259     /// ```
260     /// use dashmap::DashSet;
261     ///
262     /// let words = DashSet::new();
263     /// words.insert("hello");
264     /// assert_eq!(words.iter().count(), 1);
265     /// ```
iter(&'a self) -> Iter<'a, K, S, DashMap<K, (), S>>266     pub fn iter(&'a self) -> Iter<'a, K, S, DashMap<K, (), S>> {
267         let iter = self.inner.iter();
268 
269         Iter::new(iter)
270     }
271 
272     /// Get a reference to an entry in the set
273     ///
274     /// # Examples
275     ///
276     /// ```
277     /// use dashmap::DashSet;
278     ///
279     /// let youtubers = DashSet::new();
280     /// youtubers.insert("Bosnian Bill");
281     /// assert_eq!(*youtubers.get("Bosnian Bill").unwrap(), "Bosnian Bill");
282     /// ```
get<Q>(&'a self, key: &Q) -> Option<Ref<'a, K, S>> where K: Borrow<Q>, Q: Hash + Eq + ?Sized,283     pub fn get<Q>(&'a self, key: &Q) -> Option<Ref<'a, K, S>>
284     where
285         K: Borrow<Q>,
286         Q: Hash + Eq + ?Sized,
287     {
288         self.inner.get(key).map(Ref::new)
289     }
290 
291     /// Remove excess capacity to reduce memory usage.
shrink_to_fit(&self)292     pub fn shrink_to_fit(&self) {
293         self.inner.shrink_to_fit()
294     }
295 
296     /// Retain elements that whose predicates return true
297     /// and discard elements whose predicates return false.
298     ///
299     /// # Examples
300     ///
301     /// ```
302     /// use dashmap::DashSet;
303     ///
304     /// let people = DashSet::new();
305     /// people.insert("Albin");
306     /// people.insert("Jones");
307     /// people.insert("Charlie");
308     /// people.retain(|name| name.contains('i'));
309     /// assert_eq!(people.len(), 2);
310     /// ```
retain(&self, mut f: impl FnMut(&K) -> bool)311     pub fn retain(&self, mut f: impl FnMut(&K) -> bool) {
312         self.inner.retain(|k, _| f(k))
313     }
314 
315     /// Fetches the total number of keys stored in the set.
316     ///
317     /// # Examples
318     ///
319     /// ```
320     /// use dashmap::DashSet;
321     ///
322     /// let people = DashSet::new();
323     /// people.insert("Albin");
324     /// people.insert("Jones");
325     /// people.insert("Charlie");
326     /// assert_eq!(people.len(), 3);
327     /// ```
len(&self) -> usize328     pub fn len(&self) -> usize {
329         self.inner.len()
330     }
331 
332     /// Checks if the set is empty or not.
333     ///
334     /// # Examples
335     ///
336     /// ```
337     /// use dashmap::DashSet;
338     ///
339     /// let map = DashSet::<()>::new();
340     /// assert!(map.is_empty());
341     /// ```
is_empty(&self) -> bool342     pub fn is_empty(&self) -> bool {
343         self.inner.is_empty()
344     }
345 
346     /// Removes all keys in the set.
347     ///
348     /// # Examples
349     ///
350     /// ```
351     /// use dashmap::DashSet;
352     ///
353     /// let people = DashSet::new();
354     /// people.insert("Albin");
355     /// assert!(!people.is_empty());
356     /// people.clear();
357     /// assert!(people.is_empty());
358     /// ```
clear(&self)359     pub fn clear(&self) {
360         self.inner.clear()
361     }
362 
363     /// Returns how many keys the set can store without reallocating.
capacity(&self) -> usize364     pub fn capacity(&self) -> usize {
365         self.inner.capacity()
366     }
367 
368     /// Checks if the set contains a specific key.
369     ///
370     /// # Examples
371     ///
372     /// ```
373     /// use dashmap::DashSet;
374     ///
375     /// let people = DashSet::new();
376     /// people.insert("Dakota Cherries");
377     /// assert!(people.contains("Dakota Cherries"));
378     /// ```
contains<Q>(&self, key: &Q) -> bool where K: Borrow<Q>, Q: Hash + Eq + ?Sized,379     pub fn contains<Q>(&self, key: &Q) -> bool
380     where
381         K: Borrow<Q>,
382         Q: Hash + Eq + ?Sized,
383     {
384         self.inner.contains_key(key)
385     }
386 }
387 
388 impl<K: Eq + Hash, S: BuildHasher + Clone> IntoIterator for DashSet<K, S> {
389     type Item = K;
390 
391     type IntoIter = OwningIter<K, S>;
392 
into_iter(self) -> Self::IntoIter393     fn into_iter(self) -> Self::IntoIter {
394         OwningIter::new(self.inner.into_iter())
395     }
396 }
397 
398 impl<K: Eq + Hash, S: BuildHasher + Clone> Extend<K> for DashSet<K, S> {
extend<T: IntoIterator<Item = K>>(&mut self, iter: T)399     fn extend<T: IntoIterator<Item = K>>(&mut self, iter: T) {
400         let iter = iter.into_iter().map(|k| (k, ()));
401 
402         self.inner.extend(iter)
403     }
404 }
405 
406 impl<K: Eq + Hash, S: BuildHasher + Clone + Default> FromIterator<K> for DashSet<K, S> {
from_iter<I: IntoIterator<Item = K>>(iter: I) -> Self407     fn from_iter<I: IntoIterator<Item = K>>(iter: I) -> Self {
408         let mut set = DashSet::default();
409 
410         set.extend(iter);
411 
412         set
413     }
414 }
415 
416 #[cfg(test)]
417 mod tests {
418     use crate::DashSet;
419 
420     #[test]
test_basic()421     fn test_basic() {
422         let set = DashSet::new();
423 
424         set.insert(0);
425 
426         assert_eq!(set.get(&0).as_deref(), Some(&0));
427     }
428 
429     #[test]
test_default()430     fn test_default() {
431         let set: DashSet<u32> = DashSet::default();
432 
433         set.insert(0);
434 
435         assert_eq!(set.get(&0).as_deref(), Some(&0));
436     }
437 
438     #[test]
test_multiple_hashes()439     fn test_multiple_hashes() {
440         let set = DashSet::<u32>::default();
441 
442         for i in 0..100 {
443             assert!(set.insert(i));
444         }
445 
446         for i in 0..100 {
447             assert!(!set.insert(i));
448         }
449 
450         for i in 0..100 {
451             assert_eq!(Some(i), set.remove(&i));
452         }
453 
454         for i in 0..100 {
455             assert_eq!(None, set.remove(&i));
456         }
457     }
458 }
459