fallacy_hash/
hash_set.rs

1//! A hash set implemented as a `HashMap` where the value is `()`.
2
3pub use std::collections::hash_set::{Drain, IntoIter, Iter};
4
5use crate::AllocError;
6use crate::FxBuildHasher;
7use std::borrow::Borrow;
8use std::collections::HashSet as StdHashSet;
9use std::fmt;
10use std::hash::{BuildHasher, Hash};
11
12/// A hash set implemented as a `HashMap` where the value is `()`.
13#[repr(transparent)]
14pub struct HashSet<T, S = FxBuildHasher>(StdHashSet<T, S>);
15
16impl<T> HashSet<T, FxBuildHasher> {
17    /// Creates an empty `HashSet`.
18    ///
19    /// The hash set is initially created with a capacity of 0, so it will not allocate until it
20    /// is first inserted into.
21    #[must_use]
22    #[inline]
23    pub fn new() -> HashSet<T, FxBuildHasher> {
24        HashSet::default()
25    }
26}
27
28impl<T, S> HashSet<T, S> {
29    #[inline]
30    pub fn from_std(hash_set: StdHashSet<T, S>) -> Self {
31        HashSet(hash_set)
32    }
33
34    #[inline]
35    pub fn into_std(self) -> StdHashSet<T, S> {
36        self.0
37    }
38
39    /// Returns the number of elements the set can hold without reallocating.
40    #[inline]
41    pub fn capacity(&self) -> usize {
42        self.0.capacity()
43    }
44
45    /// An iterator visiting all elements in arbitrary order.
46    /// The iterator element type is `&'a T`.
47    #[inline]
48    pub fn iter(&self) -> Iter<'_, T> {
49        self.0.iter()
50    }
51
52    /// Returns the number of elements in the set.
53    #[inline]
54    pub fn len(&self) -> usize {
55        self.0.len()
56    }
57
58    /// Returns `true` if the set contains no elements.
59    #[inline]
60    pub fn is_empty(&self) -> bool {
61        self.0.is_empty()
62    }
63
64    /// Clears the set, returning all elements as an iterator. Keeps the
65    /// allocated memory for reuse.
66    ///
67    /// If the returned iterator is dropped before being fully consumed, it
68    /// drops the remaining elements. The returned iterator keeps a mutable
69    /// borrow on the vector to optimize its implementation.
70    #[inline]
71    pub fn drain(&mut self) -> Drain<'_, T> {
72        self.0.drain()
73    }
74
75    /// Retains only the elements specified by the predicate.
76    ///
77    /// In other words, remove all elements `e` for which `f(&e)` returns `false`.
78    /// The elements are visited in unsorted (and unspecified) order.
79    #[inline]
80    pub fn retain<F>(&mut self, f: F)
81    where
82        F: FnMut(&T) -> bool,
83    {
84        self.0.retain(f)
85    }
86
87    /// Clears the set, removing all values.
88    #[inline]
89    pub fn clear(&mut self) {
90        self.0.clear()
91    }
92
93    /// Creates a new empty hash set which will use the given hasher to hash
94    /// keys.
95    ///
96    /// The hash set is also created with the default initial capacity.
97    ///
98    /// Warning: `hasher` is normally randomly generated, and
99    /// is designed to allow `HashSet`s to be resistant to attacks that
100    /// cause many collisions and very poor performance. Setting it
101    /// manually using this function can expose a DoS attack vector.
102    ///
103    /// The `hash_builder` passed should implement the [`BuildHasher`] trait for
104    /// the HashMap to be useful, see its documentation for details.
105    #[inline]
106    pub fn with_hasher(hasher: S) -> HashSet<T, S> {
107        HashSet(StdHashSet::with_hasher(hasher))
108    }
109
110    /// Returns a reference to the set's [`BuildHasher`].
111    #[inline]
112    pub fn hasher(&self) -> &S {
113        self.0.hasher()
114    }
115}
116
117impl<T, S> HashSet<T, S>
118where
119    T: Eq + Hash,
120    S: BuildHasher,
121{
122    /// Creates an empty `HashSet` with the specified capacity.
123    ///
124    /// The hash set will be able to hold at least `capacity` elements without
125    /// reallocating. If `capacity` is 0, the hash set will not allocate.
126    #[inline]
127    pub fn try_with_capacity(capacity: usize) -> Result<HashSet<T, S>, AllocError>
128    where
129        S: Default,
130    {
131        let mut set = StdHashSet::with_hasher(Default::default());
132        set.try_reserve(capacity)?;
133        Ok(HashSet(set))
134    }
135
136    /// Creates an empty `HashSet` with the specified capacity, using
137    /// `hasher` to hash the keys.
138    ///
139    /// The hash set will be able to hold at least `capacity` elements without
140    /// reallocating. If `capacity` is 0, the hash set will not allocate.
141    ///
142    /// Warning: `hasher` is normally randomly generated, and
143    /// is designed to allow `HashSet`s to be resistant to attacks that
144    /// cause many collisions and very poor performance. Setting it
145    /// manually using this function can expose a DoS attack vector.
146    ///
147    /// The `hash_builder` passed should implement the [`BuildHasher`] trait for
148    /// the HashMap to be useful, see its documentation for details.
149    #[inline]
150    pub fn try_with_capacity_and_hasher(capacity: usize, hasher: S) -> Result<HashSet<T, S>, AllocError> {
151        let mut set = StdHashSet::with_hasher(hasher);
152        set.try_reserve(capacity)?;
153        Ok(HashSet(set))
154    }
155
156    /// Tries to reserve capacity for at least `additional` more elements to be inserted
157    /// in the given `HashSet<K, V>`. The collection may reserve more space to avoid
158    /// frequent reallocations.
159    ///
160    /// # Errors
161    ///
162    /// If the capacity overflows, or the allocator reports a failure, then an error
163    /// is returned.
164    #[inline]
165    pub fn try_reserve(&mut self, additional: usize) -> Result<(), AllocError> {
166        self.0.try_reserve(additional)?;
167        Ok(())
168    }
169
170    /// Returns `true` if the set contains a value.
171    ///
172    /// The value may be any borrowed form of the set's value type, but
173    /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
174    /// the value type.
175    #[inline]
176    pub fn contains<Q: ?Sized>(&self, value: &Q) -> bool
177    where
178        T: Borrow<Q>,
179        Q: Hash + Eq,
180    {
181        self.0.contains(value)
182    }
183
184    /// Returns a reference to the value in the set, if any, that is equal to the given value.
185    ///
186    /// The value may be any borrowed form of the set's value type, but
187    /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
188    /// the value type.
189    #[inline]
190    pub fn get<Q: ?Sized>(&self, value: &Q) -> Option<&T>
191    where
192        T: Borrow<Q>,
193        Q: Hash + Eq,
194    {
195        self.0.get(value)
196    }
197
198    /// Adds a value to the set.
199    ///
200    /// If the set did not have this value present, `true` is returned.
201    ///
202    /// If the set did have this value present, `false` is returned.
203    #[inline]
204    pub fn try_insert(&mut self, value: T) -> Result<bool, AllocError> {
205        self.0.try_reserve(1)?;
206        Ok(self.0.insert(value))
207    }
208
209    /// Adds a value to the set, replacing the existing value, if any, that is equal to the given
210    /// one. Returns the replaced value.
211    #[inline]
212    pub fn replace(&mut self, value: T) -> Result<Option<T>, AllocError> {
213        self.0.try_reserve(1)?;
214        Ok(self.0.replace(value))
215    }
216
217    /// Removes a value from the set. Returns whether the value was
218    /// present in the set.
219    ///
220    /// The value may be any borrowed form of the set's value type, but
221    /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
222    /// the value type.
223    #[inline]
224    pub fn remove<Q: ?Sized>(&mut self, value: &Q) -> bool
225    where
226        T: Borrow<Q>,
227        Q: Hash + Eq,
228    {
229        self.0.remove(value)
230    }
231
232    /// Removes and returns the value in the set, if any, that is equal to the given one.
233    ///
234    /// The value may be any borrowed form of the set's value type, but
235    /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
236    /// the value type.
237    #[inline]
238    pub fn take<Q: ?Sized>(&mut self, value: &Q) -> Option<T>
239    where
240        T: Borrow<Q>,
241        Q: Hash + Eq,
242    {
243        self.0.take(value)
244    }
245}
246
247impl<T, S> PartialEq for HashSet<T, S>
248where
249    T: Eq + Hash,
250    S: BuildHasher,
251{
252    #[inline]
253    fn eq(&self, other: &HashSet<T, S>) -> bool {
254        self.0.eq(&other.0)
255    }
256}
257
258impl<T, S> Eq for HashSet<T, S>
259where
260    T: Eq + Hash,
261    S: BuildHasher,
262{
263}
264
265impl<T, S> fmt::Debug for HashSet<T, S>
266where
267    T: fmt::Debug,
268{
269    #[inline]
270    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
271        fmt::Debug::fmt(&self.0, f)
272    }
273}
274
275impl<T, S> Default for HashSet<T, S>
276where
277    S: Default,
278{
279    /// Creates an empty `HashSet<T, S>` with the `Default` value for the hasher.
280    #[inline]
281    fn default() -> HashSet<T, S> {
282        HashSet::with_hasher(Default::default())
283    }
284}
285
286impl<'a, T, S> IntoIterator for &'a HashSet<T, S> {
287    type Item = &'a T;
288    type IntoIter = Iter<'a, T>;
289
290    #[inline]
291    fn into_iter(self) -> Iter<'a, T> {
292        self.iter()
293    }
294}
295
296impl<T, S> IntoIterator for HashSet<T, S> {
297    type Item = T;
298    type IntoIter = IntoIter<T>;
299
300    /// Creates a consuming iterator, that is, one that moves each value out
301    /// of the set in arbitrary order. The set cannot be used after calling
302    /// this.
303    #[inline]
304    fn into_iter(self) -> IntoIter<T> {
305        self.0.into_iter()
306    }
307}
308
309#[cfg(feature = "serde")]
310mod serde {
311    use crate::HashSet;
312    use serde::de::{SeqAccess, Visitor};
313    use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer};
314    use std::fmt;
315    use std::hash::{BuildHasher, Hash};
316    use std::marker::PhantomData;
317
318    impl<T, H> Serialize for HashSet<T, H>
319    where
320        T: Eq + Hash + Serialize,
321        H: BuildHasher,
322    {
323        #[inline]
324        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
325        where
326            S: Serializer,
327        {
328            serializer.collect_seq(self)
329        }
330    }
331
332    impl<'de, T, H> Deserialize<'de> for HashSet<T, H>
333    where
334        T: Eq + Hash + Deserialize<'de>,
335        H: BuildHasher + Default + Deserialize<'de>,
336    {
337        #[inline]
338        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
339        where
340            D: Deserializer<'de>,
341        {
342            struct SeqVisitor<T, H> {
343                _marker: PhantomData<HashSet<T, H>>,
344            }
345
346            impl<'de, T, H> Visitor<'de> for SeqVisitor<T, H>
347            where
348                T: Eq + Hash + Deserialize<'de>,
349                H: BuildHasher + Default + Deserialize<'de>,
350            {
351                type Value = HashSet<T, H>;
352
353                #[inline]
354                fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
355                    formatter.write_str("a sequence")
356                }
357
358                #[inline]
359                fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
360                where
361                    A: SeqAccess<'de>,
362                {
363                    let cap = seq.size_hint().unwrap_or(8).min(4096);
364                    let mut values =
365                        HashSet::try_with_capacity_and_hasher(cap, H::default()).map_err(A::Error::custom)?;
366
367                    while let Some(value) = seq.next_element()? {
368                        values.try_insert(value).map_err(A::Error::custom)?;
369                    }
370
371                    Ok(values)
372                }
373            }
374
375            let visitor = SeqVisitor { _marker: PhantomData };
376            deserializer.deserialize_seq(visitor)
377        }
378    }
379}