Skip to main content

scc/
hash_set.rs

1//! [`HashSet`] is an asynchronous/concurrent hash set.
2
3#![deny(unsafe_code)]
4
5use std::collections::hash_map::RandomState;
6use std::fmt::{self, Debug};
7use std::hash::{BuildHasher, Hash};
8use std::mem::swap;
9use std::ops::{Deref, RangeInclusive};
10
11use super::hash_map;
12use super::hash_table::HashTable;
13use super::{Equivalent, HashMap};
14
15/// Scalable asynchronous/concurrent hash set.
16///
17/// [`HashSet`] is an asynchronous/concurrent hash set based on [`HashMap`].
18pub struct HashSet<K, H = RandomState>
19where
20    H: BuildHasher,
21{
22    map: HashMap<K, (), H>,
23}
24
25/// [`ConsumableEntry`] is a view into an occupied entry in a [`HashSet`] when iterating over
26/// entries in it.
27pub struct ConsumableEntry<'w, K> {
28    consumable: hash_map::ConsumableEntry<'w, K, ()>,
29}
30
31/// [`Reserve`] keeps the capacity of the associated [`HashSet`] higher than a certain level.
32///
33/// The [`HashSet`] does not shrink the capacity below the reserved capacity.
34pub type Reserve<'h, K, H = RandomState> = super::hash_map::Reserve<'h, K, (), H>;
35
36impl<K, H> HashSet<K, H>
37where
38    H: BuildHasher,
39{
40    /// Creates an empty [`HashSet`] with the given [`BuildHasher`].
41    ///
42    /// # Examples
43    ///
44    /// ```
45    /// use scc::HashSet;
46    /// use std::collections::hash_map::RandomState;
47    ///
48    /// let hashset: HashSet<u64, RandomState> = HashSet::with_hasher(RandomState::new());
49    /// ```
50    #[cfg(not(feature = "loom"))]
51    #[inline]
52    pub const fn with_hasher(build_hasher: H) -> Self {
53        Self {
54            map: HashMap::with_hasher(build_hasher),
55        }
56    }
57
58    /// Creates an empty [`HashSet`] with the given [`BuildHasher`].
59    #[cfg(feature = "loom")]
60    #[inline]
61    pub fn with_hasher(build_hasher: H) -> Self {
62        Self {
63            map: HashMap::with_hasher(build_hasher),
64        }
65    }
66
67    /// Creates an empty [`HashSet`] with the specified capacity and [`BuildHasher`].
68    ///
69    /// The actual capacity is equal to or greater than `capacity` unless it is greater than
70    /// `1 << (usize::BITS - 1)`.
71    ///
72    /// # Examples
73    ///
74    /// ```
75    /// use scc::HashSet;
76    /// use std::collections::hash_map::RandomState;
77    ///
78    /// let hashset: HashSet<u64, RandomState> =
79    ///     HashSet::with_capacity_and_hasher(1000, RandomState::new());
80    ///
81    /// let result = hashset.capacity();
82    /// assert_eq!(result, 1024);
83    /// ```
84    #[inline]
85    pub fn with_capacity_and_hasher(capacity: usize, build_hasher: H) -> Self {
86        Self {
87            map: HashMap::with_capacity_and_hasher(capacity, build_hasher),
88        }
89    }
90}
91
92impl<K, H> HashSet<K, H>
93where
94    K: Eq + Hash,
95    H: BuildHasher,
96{
97    /// Temporarily increases the minimum capacity of the [`HashSet`].
98    ///
99    /// A [`Reserve`] is returned if the [`HashSet`] could increase the minimum capacity while the
100    /// increased capacity is not exclusively owned by the returned [`Reserve`], allowing others to
101    /// benefit from it. The memory for the additional space may not be immediately allocated if
102    /// the [`HashSet`] is empty or currently being resized, however once the memory is reserved
103    /// eventually, the capacity will not shrink below the additional capacity until the returned
104    /// [`Reserve`] is dropped.
105    ///
106    /// # Errors
107    ///
108    /// Returns `None` if a too large number is given.
109    ///
110    /// # Examples
111    ///
112    /// ```
113    /// use scc::HashSet;
114    ///
115    /// let hashset: HashSet<usize> = HashSet::with_capacity(1000);
116    /// assert_eq!(hashset.capacity(), 1024);
117    ///
118    /// let reserved = hashset.reserve(10000);
119    /// assert!(reserved.is_some());
120    /// assert_eq!(hashset.capacity(), 16384);
121    ///
122    /// assert!(hashset.reserve(usize::MAX).is_none());
123    /// assert_eq!(hashset.capacity(), 16384);
124    ///
125    /// for i in 0..16 {
126    ///     assert!(hashset.insert_sync(i).is_ok());
127    /// }
128    /// drop(reserved);
129    ///
130    /// assert_eq!(hashset.capacity(), 1024);
131    /// ```
132    #[inline]
133    pub fn reserve(&self, capacity: usize) -> Option<Reserve<'_, K, H>> {
134        self.map.reserve(capacity)
135    }
136
137    /// Inserts a key into the [`HashSet`].
138    ///
139    /// # Errors
140    ///
141    /// Returns an error along with the supplied key if the key exists.
142    ///
143    /// # Examples
144    ///
145    /// ```
146    /// use scc::HashSet;
147    ///
148    /// let hashset: HashSet<u64> = HashSet::default();
149    /// let future_insert = hashset.insert_async(11);
150    /// ```
151    #[inline]
152    pub async fn insert_async(&self, key: K) -> Result<(), K> {
153        self.map.insert_async(key, ()).await.map_err(|(k, ())| k)
154    }
155
156    /// Inserts a key into the [`HashSet`].
157    ///
158    /// # Errors
159    ///
160    /// Returns an error along with the supplied key if the key exists.
161    ///
162    /// # Examples
163    ///
164    /// ```
165    /// use scc::HashSet;
166    ///
167    /// let hashset: HashSet<u64> = HashSet::default();
168    ///
169    /// assert!(hashset.insert_sync(1).is_ok());
170    /// assert_eq!(hashset.insert_sync(1).unwrap_err(), 1);
171    /// ```
172    #[inline]
173    pub fn insert_sync(&self, key: K) -> Result<(), K> {
174        if let Err((k, ())) = self.map.insert_sync(key, ()) {
175            return Err(k);
176        }
177        Ok(())
178    }
179
180    /// Adds a key to the set, replacing the existing key, if any, that is equal to the given one.
181    ///
182    /// Returns the replaced key, if any.
183    ///
184    /// # Examples
185    ///
186    /// ```
187    /// use std::cmp::{Eq, PartialEq};
188    /// use std::hash::{Hash, Hasher};
189    ///
190    /// use scc::HashSet;
191    ///
192    /// #[derive(Debug)]
193    /// struct MaybeEqual(u64, u64);
194    ///
195    /// impl Eq for MaybeEqual {}
196    ///
197    /// impl Hash for MaybeEqual {
198    ///     fn hash<H: Hasher>(&self, state: &mut H) {
199    ///         // Do not read `self.1`.
200    ///         self.0.hash(state);
201    ///     }
202    /// }
203    ///
204    /// impl PartialEq for MaybeEqual {
205    ///     fn eq(&self, other: &Self) -> bool {
206    ///         // Do not compare `self.1`.
207    ///         self.0 == other.0
208    ///     }
209    /// }
210    ///
211    /// let hashset: HashSet<MaybeEqual> = HashSet::default();
212    ///
213    /// assert!(hashset.replace_sync(MaybeEqual(11, 7)).is_none());
214    /// assert_eq!(hashset.replace_sync(MaybeEqual(11, 11)), Some(MaybeEqual(11, 7)));
215    /// ```
216    #[inline]
217    pub async fn replace_async(&self, mut key: K) -> Option<K> {
218        let hash = self.map.hash(&key);
219        let mut locked_bucket = self.map.writer_async(hash).await;
220        let mut entry_ptr = locked_bucket.search(&key, hash);
221        if entry_ptr.is_valid() {
222            let k = locked_bucket.entry_mut(&mut entry_ptr).0;
223            swap(k, &mut key);
224            Some(key)
225        } else {
226            locked_bucket.insert(hash, (key, ()));
227            None
228        }
229    }
230
231    /// Adds a key to the set, replacing the existing key, if any, that is equal to the given one.
232    ///
233    /// Returns the replaced key, if any.
234    ///
235    /// # Examples
236    ///
237    /// ```
238    /// use std::cmp::{Eq, PartialEq};
239    /// use std::hash::{Hash, Hasher};
240    ///
241    /// use scc::HashSet;
242    ///
243    /// #[derive(Debug)]
244    /// struct MaybeEqual(u64, u64);
245    ///
246    /// impl Eq for MaybeEqual {}
247    ///
248    /// impl Hash for MaybeEqual {
249    ///     fn hash<H: Hasher>(&self, state: &mut H) {
250    ///         // Do not read `self.1`.
251    ///         self.0.hash(state);
252    ///     }
253    /// }
254    ///
255    /// impl PartialEq for MaybeEqual {
256    ///     fn eq(&self, other: &Self) -> bool {
257    ///         // Do not compare `self.1`.
258    ///         self.0 == other.0
259    ///     }
260    /// }
261    ///
262    /// let hashset: HashSet<MaybeEqual> = HashSet::default();
263    ///
264    /// async {
265    ///     assert!(hashset.replace_async(MaybeEqual(11, 7)).await.is_none());
266    ///     assert_eq!(hashset.replace_async(MaybeEqual(11, 11)).await, Some(MaybeEqual(11, 7)));
267    /// };
268    /// ```
269    #[inline]
270    pub fn replace_sync(&self, mut key: K) -> Option<K> {
271        let hash = self.map.hash(&key);
272        let mut locked_bucket = self.map.writer_sync(hash);
273        let mut entry_ptr = locked_bucket.search(&key, hash);
274        if entry_ptr.is_valid() {
275            let k = locked_bucket.entry_mut(&mut entry_ptr).0;
276            swap(k, &mut key);
277            Some(key)
278        } else {
279            locked_bucket.insert(hash, (key, ()));
280            None
281        }
282    }
283
284    /// Removes a key if the key exists.
285    ///
286    /// Returns `None` if the key does not exist.
287    ///
288    /// # Examples
289    ///
290    /// ```
291    /// use scc::HashSet;
292    ///
293    /// let hashset: HashSet<u64> = HashSet::default();
294    /// let future_insert = hashset.insert_async(11);
295    /// let future_remove = hashset.remove_async(&11);
296    /// ```
297    #[inline]
298    pub async fn remove_async<Q>(&self, key: &Q) -> Option<K>
299    where
300        Q: Equivalent<K> + Hash + ?Sized,
301    {
302        self.map
303            .remove_if_async(key, |()| true)
304            .await
305            .map(|(k, ())| k)
306    }
307
308    /// Removes a key if the key exists.
309    ///
310    /// Returns `None` if the key does not exist.
311    ///
312    /// # Examples
313    ///
314    /// ```
315    /// use scc::HashSet;
316    ///
317    /// let hashset: HashSet<u64> = HashSet::default();
318    ///
319    /// assert!(hashset.remove_sync(&1).is_none());
320    /// assert!(hashset.insert_sync(1).is_ok());
321    /// assert_eq!(hashset.remove_sync(&1).unwrap(), 1);
322    /// ```
323    #[inline]
324    pub fn remove_sync<Q>(&self, key: &Q) -> Option<K>
325    where
326        Q: Equivalent<K> + Hash + ?Sized,
327    {
328        self.map.remove_sync(key).map(|(k, ())| k)
329    }
330
331    /// Removes a key if the key exists and the given condition is met.
332    ///
333    /// Returns `None` if the key does not exist or the condition was not met.
334    ///
335    /// # Examples
336    ///
337    /// ```
338    /// use scc::HashSet;
339    ///
340    /// let hashset: HashSet<u64> = HashSet::default();
341    /// let future_insert = hashset.insert_async(11);
342    /// let future_remove = hashset.remove_if_async(&11, || true);
343    /// ```
344    #[inline]
345    pub async fn remove_if_async<Q, F: FnOnce() -> bool>(&self, key: &Q, condition: F) -> Option<K>
346    where
347        Q: Equivalent<K> + Hash + ?Sized,
348    {
349        self.map
350            .remove_if_async(key, |()| condition())
351            .await
352            .map(|(k, ())| k)
353    }
354
355    /// Removes a key if the key exists and the given condition is met.
356    ///
357    /// Returns `None` if the key does not exist or the condition was not met.
358    ///
359    /// # Examples
360    ///
361    /// ```
362    /// use scc::HashSet;
363    ///
364    /// let hashset: HashSet<u64> = HashSet::default();
365    ///
366    /// assert!(hashset.insert_sync(1).is_ok());
367    /// assert!(hashset.remove_if_sync(&1, || false).is_none());
368    /// assert_eq!(hashset.remove_if_sync(&1, || true).unwrap(), 1);
369    /// ```
370    #[inline]
371    pub fn remove_if_sync<Q, F: FnOnce() -> bool>(&self, key: &Q, condition: F) -> Option<K>
372    where
373        Q: Equivalent<K> + Hash + ?Sized,
374    {
375        self.map
376            .remove_if_sync(key, |()| condition())
377            .map(|(k, ())| k)
378    }
379
380    /// Reads a key.
381    ///
382    /// Returns `None` if the key does not exist.
383    ///
384    /// # Examples
385    ///
386    /// ```
387    /// use scc::HashSet;
388    ///
389    /// let hashset: HashSet<u64> = HashSet::default();
390    /// let future_insert = hashset.insert_async(11);
391    /// let future_read = hashset.read_async(&11, |k| *k);
392    /// ```
393    #[inline]
394    pub async fn read_async<Q, R, F: FnOnce(&K) -> R>(&self, key: &Q, reader: F) -> Option<R>
395    where
396        Q: Equivalent<K> + Hash + ?Sized,
397    {
398        self.map.read_async(key, |k, ()| reader(k)).await
399    }
400
401    /// Reads a key.
402    ///
403    /// Returns `None` if the key does not exist.
404    ///
405    /// # Examples
406    ///
407    /// ```
408    /// use scc::HashSet;
409    ///
410    /// let hashset: HashSet<u64> = HashSet::default();
411    ///
412    /// assert!(hashset.read_sync(&1, |_| true).is_none());
413    /// assert!(hashset.insert_sync(1).is_ok());
414    /// assert!(hashset.read_sync(&1, |_| true).unwrap());
415    /// ```
416    #[inline]
417    pub fn read_sync<Q, R, F: FnOnce(&K) -> R>(&self, key: &Q, reader: F) -> Option<R>
418    where
419        Q: Equivalent<K> + Hash + ?Sized,
420    {
421        self.map.read_sync(key, |k, ()| reader(k))
422    }
423
424    /// Returns `true` if the [`HashSet`] contains the specified key.
425    ///
426    /// # Examples
427    ///
428    /// ```
429    /// use scc::HashSet;
430    ///
431    /// let hashset: HashSet<u64> = HashSet::default();
432    ///
433    /// let future_contains = hashset.contains_async(&1);
434    /// ```
435    #[inline]
436    pub async fn contains_async<Q>(&self, key: &Q) -> bool
437    where
438        Q: Equivalent<K> + Hash + ?Sized,
439    {
440        self.map.contains_async(key).await
441    }
442
443    /// Returns `true` if the [`HashSet`] contains the specified key.
444    ///
445    /// # Examples
446    ///
447    /// ```
448    /// use scc::HashSet;
449    ///
450    /// let hashset: HashSet<u64> = HashSet::default();
451    ///
452    /// assert!(!hashset.contains_sync(&1));
453    /// assert!(hashset.insert_sync(1).is_ok());
454    /// assert!(hashset.contains_sync(&1));
455    /// ```
456    #[inline]
457    pub fn contains_sync<Q>(&self, key: &Q) -> bool
458    where
459        Q: Equivalent<K> + Hash + ?Sized,
460    {
461        self.read_sync(key, |_| ()).is_some()
462    }
463
464    /// Iterates over entries asynchronously for reading.
465    ///
466    /// Stops iterating when the closure returns `false`, and this method also returns `false`.
467    ///
468    /// # Examples
469    ///
470    /// ```
471    /// use scc::HashSet;
472    ///
473    /// let hashset: HashSet<u64> = HashSet::default();
474    ///
475    /// assert!(hashset.insert_sync(1).is_ok());
476    ///
477    /// async {
478    ///     let result = hashset.iter_async(|k| {
479    ///         true
480    ///     }).await;
481    ///     assert!(result);
482    /// };
483    /// ```
484    #[inline]
485    pub async fn iter_async<F: FnMut(&K) -> bool>(&self, mut f: F) -> bool {
486        self.map.iter_async(|k, ()| f(k)).await
487    }
488
489    /// Iterates over entries synchronously for reading.
490    ///
491    /// Stops iterating when the closure returns `false`, and this method also returns `false`.
492    ///
493    /// # Examples
494    ///
495    /// ```
496    /// use scc::HashSet;
497    ///
498    /// let hashset: HashSet<u64> = HashSet::default();
499    ///
500    /// assert!(hashset.insert_sync(1).is_ok());
501    /// assert!(hashset.insert_sync(2).is_ok());
502    ///
503    /// let mut acc = 0;
504    /// let result = hashset.iter_sync(|k| {
505    ///     acc += *k;
506    ///     true
507    /// });
508    ///
509    /// assert!(result);
510    /// assert_eq!(acc, 3);
511    /// ```
512    #[inline]
513    pub fn iter_sync<F: FnMut(&K) -> bool>(&self, mut f: F) -> bool {
514        self.map.iter_sync(|k, ()| f(k))
515    }
516
517    /// Iterates over entries asynchronously for modification.
518    ///
519    /// This method stops iterating when the closure returns `false`, and also returns `false` in
520    /// that case.
521    ///
522    /// # Examples
523    ///
524    /// ```
525    /// use scc::HashSet;
526    ///
527    /// let hashset: HashSet<u64> = HashSet::default();
528    ///
529    /// assert!(hashset.insert_sync(1).is_ok());
530    /// assert!(hashset.insert_sync(2).is_ok());
531    ///
532    /// async {
533    ///     let result = hashset.iter_mut_async(|e| {
534    ///         if *e == 1 {
535    ///             e.consume();
536    ///             return false;
537    ///         }
538    ///         true
539    ///     }).await;
540    ///
541    ///     assert!(!result);
542    ///     assert_eq!(hashset.len(), 1);
543    /// };
544    /// ```
545    #[inline]
546    pub async fn iter_mut_async<F: FnMut(ConsumableEntry<'_, K>) -> bool>(&self, mut f: F) -> bool {
547        self.map
548            .iter_mut_async(|consumable| f(ConsumableEntry { consumable }))
549            .await
550    }
551
552    /// Iterates over entries synchronously for modification.
553    ///
554    /// This method stops iterating when the closure returns `false`, and also returns `false` in
555    /// that case.
556    ///
557    /// # Examples
558    ///
559    /// ```
560    /// use scc::HashSet;
561    ///
562    /// let hashset: HashSet<u64> = HashSet::default();
563    ///
564    /// assert!(hashset.insert_sync(1).is_ok());
565    /// assert!(hashset.insert_sync(2).is_ok());
566    /// assert!(hashset.insert_sync(3).is_ok());
567    ///
568    /// let result = hashset.iter_mut_sync(|e| {
569    ///     if *e == 1 {
570    ///         e.consume();
571    ///         return false;
572    ///     }
573    ///     true
574    /// });
575    ///
576    /// assert!(!result);
577    /// assert!(!hashset.contains_sync(&1));
578    /// assert_eq!(hashset.len(), 2);
579    /// ```
580    #[inline]
581    pub fn iter_mut_sync<F: FnMut(ConsumableEntry<'_, K>) -> bool>(&self, mut f: F) -> bool {
582        self.map
583            .iter_mut_sync(|consumable| f(ConsumableEntry { consumable }))
584    }
585
586    /// Retains keys that satisfy the given predicate.
587    ///
588    /// # Examples
589    ///
590    /// ```
591    /// use scc::HashSet;
592    ///
593    /// let hashset: HashSet<u64> = HashSet::default();
594    ///
595    /// let future_insert = hashset.insert_async(1);
596    /// let future_retain = hashset.retain_async(|k| *k == 1);
597    /// ```
598    #[inline]
599    pub async fn retain_async<F: FnMut(&K) -> bool>(&self, mut filter: F) {
600        self.map.retain_async(|k, ()| filter(k)).await;
601    }
602
603    /// Retains keys that satisfy the given predicate.
604    ///
605    /// # Examples
606    ///
607    /// ```
608    /// use scc::HashSet;
609    ///
610    /// let hashset: HashSet<u64> = HashSet::default();
611    ///
612    /// assert!(hashset.insert_sync(1).is_ok());
613    /// assert!(hashset.insert_sync(2).is_ok());
614    /// assert!(hashset.insert_sync(3).is_ok());
615    ///
616    /// hashset.retain_sync(|k| *k == 1);
617    ///
618    /// assert!(hashset.contains_sync(&1));
619    /// assert!(!hashset.contains_sync(&2));
620    /// assert!(!hashset.contains_sync(&3));
621    /// ```
622    #[inline]
623    pub fn retain_sync<F: FnMut(&K) -> bool>(&self, mut pred: F) {
624        self.iter_mut_sync(|e| {
625            if !pred(&*e) {
626                drop(e.consume());
627            }
628            true
629        });
630    }
631
632    /// Clears the [`HashSet`] by removing all keys.
633    ///
634    /// # Examples
635    ///
636    /// ```
637    /// use scc::HashSet;
638    ///
639    /// let hashset: HashSet<u64> = HashSet::default();
640    ///
641    /// let future_insert = hashset.insert_async(1);
642    /// let future_clear = hashset.clear_async();
643    /// ```
644    #[inline]
645    pub async fn clear_async(&self) {
646        self.map.clear_async().await;
647    }
648
649    /// Clears the [`HashSet`] by removing all keys.
650    ///
651    /// # Examples
652    ///
653    /// ```
654    /// use scc::HashSet;
655    ///
656    /// let hashset: HashSet<u64> = HashSet::default();
657    ///
658    /// assert!(hashset.insert_sync(1).is_ok());
659    /// hashset.clear_sync();
660    ///
661    /// assert!(!hashset.contains_sync(&1));
662    /// ```
663    #[inline]
664    pub fn clear_sync(&self) {
665        self.map.clear_sync();
666    }
667
668    /// Returns the number of entries in the [`HashSet`].
669    ///
670    /// It reads the entire metadata area of the bucket array to calculate the number of valid
671    /// entries, making its time complexity `O(N)`. Furthermore, it may overcount entries if an old
672    /// bucket array has yet to be dropped.
673    ///
674    /// # Examples
675    ///
676    /// ```
677    /// use scc::HashSet;
678    ///
679    /// let hashset: HashSet<u64> = HashSet::default();
680    ///
681    /// assert!(hashset.insert_sync(1).is_ok());
682    /// assert_eq!(hashset.len(), 1);
683    /// ```
684    #[inline]
685    pub fn len(&self) -> usize {
686        self.map.len()
687    }
688
689    /// Returns `true` if the [`HashSet`] is empty.
690    ///
691    /// # Examples
692    ///
693    /// ```
694    /// use scc::HashSet;
695    ///
696    /// let hashset: HashSet<u64> = HashSet::default();
697    ///
698    /// assert!(hashset.is_empty());
699    /// assert!(hashset.insert_sync(1).is_ok());
700    /// assert!(!hashset.is_empty());
701    /// ```
702    #[inline]
703    pub fn is_empty(&self) -> bool {
704        self.map.is_empty()
705    }
706
707    /// Returns the capacity of the [`HashSet`].
708    ///
709    /// # Examples
710    ///
711    /// ```
712    /// use scc::HashSet;
713    ///
714    /// let hashset_default: HashSet<u64> = HashSet::default();
715    /// assert_eq!(hashset_default.capacity(), 0);
716    ///
717    /// assert!(hashset_default.insert_sync(1).is_ok());
718    /// assert_eq!(hashset_default.capacity(), 64);
719    ///
720    /// let hashset: HashSet<u64> = HashSet::with_capacity(1000);
721    /// assert_eq!(hashset.capacity(), 1024);
722    /// ```
723    #[inline]
724    pub fn capacity(&self) -> usize {
725        self.map.capacity()
726    }
727
728    /// Returns the current capacity range of the [`HashSet`].
729    ///
730    /// # Examples
731    ///
732    /// ```
733    /// use scc::HashSet;
734    ///
735    /// let hashset: HashSet<u64> = HashSet::default();
736    ///
737    /// assert_eq!(hashset.capacity_range(), 0..=(1_usize << (usize::BITS - 2)));
738    ///
739    /// let reserved = hashset.reserve(1000);
740    /// assert_eq!(hashset.capacity_range(), 1000..=(1_usize << (usize::BITS - 2)));
741    /// ```
742    #[inline]
743    pub fn capacity_range(&self) -> RangeInclusive<usize> {
744        self.map.capacity_range()
745    }
746
747    /// Returns the index of the bucket that may contain the key.
748    ///
749    /// The method returns the index of the bucket associated with the key. The number of buckets
750    /// can be calculated by dividing the capacity by `32`.
751    ///
752    /// # Examples
753    ///
754    /// ```
755    /// use scc::HashSet;
756    ///
757    /// let hashset: HashSet<u64> = HashSet::with_capacity(1024);
758    ///
759    /// let bucket_index = hashset.bucket_index(&11);
760    /// assert!(bucket_index < hashset.capacity() / 32);
761    /// ```
762    #[inline]
763    pub fn bucket_index<Q>(&self, key: &Q) -> usize
764    where
765        Q: Equivalent<K> + Hash + ?Sized,
766    {
767        self.map.bucket_index(key)
768    }
769}
770
771impl<K, H> Clone for HashSet<K, H>
772where
773    K: Clone + Eq + Hash,
774    H: BuildHasher + Clone,
775{
776    #[inline]
777    fn clone(&self) -> Self {
778        Self {
779            map: self.map.clone(),
780        }
781    }
782}
783
784impl<K, H> Debug for HashSet<K, H>
785where
786    K: Debug + Eq + Hash,
787    H: BuildHasher,
788{
789    #[inline]
790    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
791        let mut d = f.debug_set();
792        self.iter_sync(|k| {
793            d.entry(k);
794            true
795        });
796        d.finish()
797    }
798}
799
800impl<K: Eq + Hash> HashSet<K, RandomState> {
801    /// Creates an empty default [`HashSet`].
802    ///
803    /// # Examples
804    ///
805    /// ```
806    /// use scc::HashSet;
807    ///
808    /// let hashset: HashSet<u64> = HashSet::new();
809    ///
810    /// let result = hashset.capacity();
811    /// assert_eq!(result, 0);
812    /// ```
813    #[inline]
814    #[must_use]
815    pub fn new() -> Self {
816        Self::default()
817    }
818
819    /// Creates an empty [`HashSet`] with the specified capacity.
820    ///
821    /// The actual capacity is equal to or greater than `capacity` unless it is greater than
822    /// `1 << (usize::BITS - 1)`.
823    ///
824    /// # Examples
825    ///
826    /// ```
827    /// use scc::HashSet;
828    ///
829    /// let hashset: HashSet<u64> = HashSet::with_capacity(1000);
830    ///
831    /// let result = hashset.capacity();
832    /// assert_eq!(result, 1024);
833    /// ```
834    #[inline]
835    #[must_use]
836    pub fn with_capacity(capacity: usize) -> Self {
837        Self {
838            map: HashMap::with_capacity(capacity),
839        }
840    }
841}
842
843impl<K, H> Default for HashSet<K, H>
844where
845    H: BuildHasher + Default,
846{
847    /// Creates an empty default [`HashSet`].
848    ///
849    /// The default capacity is `0`.
850    ///
851    /// # Examples
852    ///
853    /// ```
854    /// use scc::HashSet;
855    ///
856    /// let hashset: HashSet<u64> = HashSet::default();
857    ///
858    /// let result = hashset.capacity();
859    /// assert_eq!(result, 0);
860    /// ```
861    #[inline]
862    fn default() -> Self {
863        Self {
864            map: HashMap::default(),
865        }
866    }
867}
868
869impl<K, H> FromIterator<K> for HashSet<K, H>
870where
871    K: Eq + Hash,
872    H: BuildHasher + Default,
873{
874    #[inline]
875    fn from_iter<T: IntoIterator<Item = K>>(iter: T) -> Self {
876        let into_iter = iter.into_iter();
877        let hashset = Self::with_capacity_and_hasher(
878            HashMap::<K, (), H>::capacity_from_size_hint(into_iter.size_hint()),
879            H::default(),
880        );
881        into_iter.for_each(|k| {
882            let _result = hashset.insert_sync(k);
883        });
884        hashset
885    }
886}
887
888impl<K, H> PartialEq for HashSet<K, H>
889where
890    K: Eq + Hash,
891    H: BuildHasher,
892{
893    /// Compares two [`HashSet`] instances.
894    ///
895    /// ### Locking behavior
896    ///
897    /// Shared locks on buckets are acquired when comparing two instances of [`HashSet`], therefore
898    /// it may lead to a deadlock if the instances are being modified by another thread.
899    #[inline]
900    fn eq(&self, other: &Self) -> bool {
901        if self.iter_sync(|k| other.contains_sync(k)) {
902            return other.iter_sync(|k| self.contains_sync(k));
903        }
904        false
905    }
906}
907
908impl<K> ConsumableEntry<'_, K> {
909    /// Consumes the entry by moving out the key.
910    ///
911    /// # Examples
912    ///
913    /// ```
914    /// use scc::HashSet;
915    ///
916    /// let hashset: HashSet<u64> = HashSet::default();
917    ///
918    /// assert!(hashset.insert_sync(1).is_ok());
919    /// assert!(hashset.insert_sync(2).is_ok());
920    /// assert!(hashset.insert_sync(3).is_ok());
921    ///
922    /// let mut consumed = None;
923    ///
924    /// hashset.iter_mut_sync(|e| {
925    ///     if *e == 1 {
926    ///         consumed.replace(e.consume());
927    ///     }
928    ///     true
929    /// });
930    ///
931    /// assert!(!hashset.contains_sync(&1));
932    /// assert_eq!(consumed, Some(1));
933    /// ```
934    #[inline]
935    #[must_use]
936    pub fn consume(self) -> K {
937        self.consumable.consume().0
938    }
939}
940
941impl<K> Deref for ConsumableEntry<'_, K> {
942    type Target = K;
943
944    #[inline]
945    fn deref(&self) -> &Self::Target {
946        self.consumable.key()
947    }
948}