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}