1use std::borrow::Borrow;
2use std::fmt::{self, Debug, Display, Formatter};
3use std::hash::{BuildHasher, Hash, RandomState};
4use std::iter::TrustedLen;
5use std::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Sub, SubAssign};
67use super::Iter;
8use crate::collections::contiguous::Vector;
9use crate::collections::hash::HashMap;
10#[doc(inline)]
11pub use crate::collections::hash::map::IndexNoCap;
12#[doc(inline)]
13pub use crate::collections::traits::set::{SetInterface, SetIterator};
14use crate::util::fmt::DebugRaw;
15use crate::util::result::ResultExtension;
1617/// A set of values that prevents duplicates with the help of the [`Hash`] trait.
18///
19/// Relies on [`HashMap`] internally, see documentation there for additional details.
20///
21/// A custom load factor is not supported at this point, with the default being 4/5.
22///
23/// It is a logic error for keys in a HashSet to be manipulated in a way that changes their hash.
24/// Because of this, HashSet's API prevents mutable access to its keys.
25///
26/// # Time Complexity
27/// See [`HashMap`] with the following additions.
28///
29/// Variables are defined as follows:
30/// - `n`: The number of items in the HashSet.
31/// - `m`: The number of items in the second HashSet.
32///
33/// | Method | Complexity |
34/// |-|-|
35/// | `difference`*, `-` | `O(n)` |
36/// | `-=` | `O(m)` |
37/// | `symmetric_difference`*, `^` | `O(n+m)` |
38/// | `^=` | `O(n+m)`**, `O(m)` |
39/// | `intersection`*, `&` | `O(n)` |
40/// | `&=` | `O(n)` |
41/// | `union`*, `\|` | `O(n+m)` |
42/// | `\|=` | `O(n+m)`**, `O(m)` |
43/// | `is_subset` | `O(m)` |
44/// | `is_superset` | `O(n)` |
45///
46/// In the event of a has collision, all methods will take additional time. This additional time is
47/// kept at a minimum and hash collisions are unlikely especially with a large capacity.
48///
49/// \* When exhausted.
50///
51/// \** If the HashMap already has capacity for the additional items, these methods will take `O(m)`
52/// instead.
53pub struct HashSet<T: Hash + Eq, B: BuildHasher = RandomState> {
54// Yay, we get to do the thing where unit type evaluates to a no-op.
55pub(crate) inner: HashMap<T, (), B>,
56}
5758impl<T: Hash + Eq, B: BuildHasher + Default> HashSet<T, B> {
59/// Creates a new HashSet with capacity 0 and the default value for `B`. Memory will be
60 /// allocated when the capacity changes.
61pub fn new() -> HashSet<T, B> {
62 HashSet {
63 inner: HashMap::new(),
64 }
65 }
6667/// Creates a new HashSet with the provided `cap`acity, allowing insertions without
68 /// reallocation. The default hasher will be used.
69pub fn with_cap(cap: usize) -> HashSet<T, B> {
70 HashSet {
71 inner: HashMap::with_cap(cap),
72 }
73 }
74}
7576impl<T: Hash + Eq, B: BuildHasher> HashSet<T, B> {
77/// Creates a new HashSet with capacity 0 and the provided `hasher`.
78pub fn with_hasher(hasher: B) -> HashSet<T, B> {
79 HashSet {
80 inner: HashMap::with_hasher(hasher),
81 }
82 }
8384/// Creates a new HashSet with the provided `cap`acity and `hasher`.
85pub fn with_cap_and_hasher(cap: usize, hasher: B) -> HashSet<T, B> {
86 HashSet {
87 inner: HashMap::with_cap_and_hasher(cap, hasher),
88 }
89 }
9091/// Returns the length of the HashSet (the number of elements it contains).
92pub const fn len(&self) -> usize {
93self.inner.len()
94 }
9596/// Returns true if the HashSet contains no elements.
97pub const fn is_empty(&self) -> bool {
98self.inner.is_empty()
99 }
100101/// Returns the current capacity of the HashSet.
102pub const fn cap(&self) -> usize {
103self.inner.cap()
104 }
105106/// Inserts the provided item into the HashSet, increasing its capacity if required. If the item
107 /// was already included, no change is made and the method returns false. In other words, the
108 /// method returns true if the insertion changes the HashSet.
109pub fn insert(&mut self, item: T) -> bool {
110if self.inner.should_grow() {
111self.inner.grow()
112 }
113114// SAFETY: We've just grown if necessary.
115let index = unsafe { self.inner.find_index_for_key(&item).unwrap_unchecked() };
116117// The Bucket at index is either empty or contains an equal item.
118match self.inner.arr[index] {
119Some(_) => false,
120None => {
121// Create a new Bucket with the provided values.
122self.inner.arr[index] = Some((item, ()));
123self.inner.len += 1;
124true
125},
126 }
127 }
128129/// Inserts the provided item, without checking if the HashSet has enough capacity. If the item
130 /// was already included, no change is made and the method returns false.
131 ///
132 /// # Safety
133 /// It is the responsibility of the caller to ensure that the HashSet has enough capacity to add
134 /// the provided item, using methods like [`reserve`][HashSet::reserve] or
135 /// [`with_cap`](HashSet::with_cap).
136 ///
137 /// # Panics
138 /// Panics if the HashSet has a capacity of 0, as it isn't possible to find a bucket associated
139 /// with the item.
140pub unsafe fn insert_unchecked(&mut self, item: T) -> bool {
141let index = self.inner.find_index_for_key(&item).ok_or(IndexNoCap).throw();
142143// The Bucket at index is either empty or contains an equal item.
144match &mut self.inner.arr[index] {
145Some(_) => true,
146None => {
147// Create a new Bucket with the provided values.
148self.inner.arr[index] = Some((item, ()));
149self.inner.len += 1;
150false
151},
152 }
153 }
154155/// Returns true if the HashSet contains `item`.
156#[inline(always)]
157pub fn contains<Q>(&self, item: &Q) -> bool
158where
159T: Borrow<Q>,
160 Q: Hash + Eq + ?Sized,
161 {
162 <HashSet<T, B> as SetInterface<T, Q>>::contains(self, item)
163 }
164165/// Returns a reference to the contained element equal to the provided `item` or None if there
166 /// isn't one.
167#[inline(always)]
168pub fn get<Q>(&self, item: &Q) -> Option<&T>
169where
170T: Borrow<Q>,
171 Q: Hash + Eq + ?Sized,
172 {
173 <HashSet<T, B> as SetInterface<T, Q>>::get(self, item)
174 }
175176/// Removes `item` from the HashSet, returning it if it exists.
177#[inline(always)]
178pub fn remove<Q>(&mut self, item: &Q) -> Option<T>
179where
180T: Borrow<Q>,
181 Q: Hash + Eq + ?Sized,
182 {
183 <HashSet<T, B> as SetInterface<T, Q>>::remove(self, item)
184 }
185186/// Increases the capacity of the HashSet to ensure that len + `extra` elements will fit without
187 /// exceeding the load factor.
188pub fn reserve(&mut self, extra: usize) {
189self.inner.reserve(extra)
190 }
191192/// Returns an iterator over all elements in the HashSet, as references.
193#[inline(always)]
194pub fn iter<'a>(&'a self) -> Iter<'a, T> {
195 <HashSet<T, B> as SetIterator<T>>::iter(self)
196 }
197}
198199impl<T: Hash + Eq + Borrow<Q>, B: BuildHasher, Q: Hash + Eq + ?Sized> SetInterface<T, Q> for HashSet<T, B> {
200fn contains(&self, item: &Q) -> bool {
201self.inner.contains(item)
202 }
203204fn get(&self, item: &Q) -> Option<&T> {
205self.inner.get_entry(item).map(|(k, _)| k)
206 }
207208fn remove(&mut self, item: &Q) -> Option<T> {
209self.inner.remove_entry(item).map(|(k, _)| k)
210 }
211}
212213impl<T: Hash + Eq, B: BuildHasher> SetIterator<T> for HashSet<T, B> {
214type Iter<'a> = Iter<'a, T> where Self: 'a;
215216fn iter<'a>(&'a self) -> Self::Iter<'a> {
217self.into_iter()
218 }
219}
220221impl<T: Hash + Eq + Clone, B: BuildHasher + Default> BitOr for HashSet<T, B> {
222type Output = HashSet<T, B>;
223224/// Returns the union of `self` and `rhs`, as a HashSet. (`self ∪ other`)
225fn bitor(self, rhs: Self) -> Self::Output {
226self.into_union(rhs).collect()
227 }
228}
229230impl<T: Hash + Eq, B: BuildHasher> BitOrAssign for HashSet<T, B> {
231/// Adds all items from `rhs` to `self` to form a union in place.
232fn bitor_assign(&mut self, rhs: Self) {
233self.reserve(rhs.cap());
234for item in rhs {
235// SAFETY: self has capacity for all items in rhs because we just called reserve.
236unsafe { self.insert_unchecked(item); }
237 }
238 }
239}
240241impl<T: Hash + Eq + Clone, B: BuildHasher + Default> BitAnd for HashSet<T, B> {
242type Output = HashSet<T, B>;
243244/// Returns the intersection of `self` and `rhs`, as a HashSet. (`self ∩ other`)
245fn bitand(self, rhs: Self) -> Self::Output {
246self.into_intersection(rhs).collect()
247 }
248}
249250impl<T: Hash + Eq, B: BuildHasher> BitAndAssign for HashSet<T, B> {
251/// Removes all items not in `rhs` from `self` to form an intersection in place.
252fn bitand_assign(&mut self, rhs: Self) {
253let mut to_remove = Vector::with_cap(self.cap());
254for item in self.iter() {
255if !rhs.contains(item) {
256 to_remove.push(
257// SAFETY: We are in a loop over self, so cap > 0.
258unsafe { self.inner.find_index_for_key(item).unwrap_unchecked() }
259 );
260 }
261 }
262for index in to_remove {
263if self.inner.arr[index].is_some() {
264self.inner.arr[index] = None;
265self.inner.len -= 1;
266 }
267 }
268 }
269}
270271impl<T: Hash + Eq + Clone, B: BuildHasher + Default> BitXor for HashSet<T, B> {
272type Output = HashSet<T, B>;
273274/// Returns the symmetric difference of `self` and `rhs`, as a HashSet. (`self △ other`)
275fn bitxor(self, rhs: Self) -> Self::Output {
276self.into_symmetric_difference(rhs).collect()
277 }
278}
279280impl<T: Hash + Eq, B: BuildHasher> BitXorAssign for HashSet<T, B> {
281/// Removes all items in both `rhs` and `self` from `self` to form the symmetric difference of
282 /// the two in place.
283fn bitxor_assign(&mut self, rhs: Self) {
284for item in rhs {
285if self.remove(&item).is_none() {
286self.insert(item);
287 }
288 }
289 }
290}
291292impl<T: Hash + Eq + Clone, B: BuildHasher + Default> Sub for HashSet<T, B> {
293type Output = HashSet<T, B>;
294295/// Returns the difference of `self` and `rhs`, as a HashSet. (`self \ other`)
296fn sub(self, rhs: Self) -> Self::Output {
297self.into_difference(rhs).collect()
298 }
299}
300301impl<T: Hash + Eq, B: BuildHasher> SubAssign for HashSet<T, B> {
302/// Removes all items in `rhs` from `self` to form the difference of the two in place.
303fn sub_assign(&mut self, rhs: Self) {
304for item in rhs {
305self.remove(&item);
306 }
307 }
308}
309310impl<T: Hash + Eq, B: BuildHasher + Default> Default for HashSet<T, B> {
311fn default() -> Self {
312Self::new()
313 }
314}
315316impl<T: Hash + Eq, B: BuildHasher> Extend<T> for HashSet<T, B> {
317fn extend<A: IntoIterator<Item = T>>(&mut self, iter: A) {
318for item in iter {
319self.insert(item);
320 }
321 }
322323fn extend_one(&mut self, item: T) {
324self.insert(item);
325 }
326327fn extend_reserve(&mut self, additional: usize) {
328self.reserve(additional);
329 }
330331unsafe fn extend_one_unchecked(&mut self, item: T)
332where
333Self: Sized,
334 {
335// SAFETY: extend_reserve is implemented correctly, so all other safety requirements are the
336 // responsibility of the caller.
337unsafe { self.insert_unchecked(item); }
338 }
339}
340341impl<T, B, I> From<I> for HashSet<T, B>
342where
343T: Hash + Eq,
344 B: BuildHasher + Default,
345 I: Iterator<Item = T> + ExactSizeIterator + TrustedLen,
346{
347fn from(value: I) -> Self {
348let iter = value.into_iter();
349let mut set = HashSet::with_cap(iter.len());
350351for item in iter {
352// SAFETY: HashSet has been created with the right capacity.
353unsafe { set.insert_unchecked(item); }
354 }
355356 set
357 }
358}
359360impl<T: Hash + Eq, B: BuildHasher + Default> FromIterator<T> for HashSet<T, B> {
361fn from_iter<I: IntoIterator<Item = T>>(value: I) -> Self {
362let iter = value.into_iter();
363let mut set = HashSet::with_cap(iter.size_hint().0);
364365for item in iter {
366 set.insert(item);
367 }
368369 set
370 }
371}
372373impl<T: Hash + Eq, B: BuildHasher> PartialEq for HashSet<T, B> {
374/// Two HashSets are considered equal if they contain exactly the same elements.
375fn eq(&self, other: &Self) -> bool {
376self.len() == other.len()
377 && self.is_subset(other)
378 && self.is_superset(other)
379 }
380}
381382impl<T: Hash + Eq, B: BuildHasher> Eq for HashSet<T, B> {}
383384impl<T: Hash + Eq + Debug, B: BuildHasher + Debug> Debug for HashSet<T, B> {
385fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
386 f.debug_struct("HashSet")
387 .field_with("buckets", |f| f.debug_list().entries(
388self.inner.arr.iter()
389 .map(|o| DebugRaw(match o {
390Some((t, _)) => ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0:?}", t))
})format!("{t:?}"),
391None => "_".into(),
392 }))
393 ).finish())
394 .field("len", &self.len())
395 .field("cap", &self.cap())
396 .field("hasher", &self.inner.hasher)
397 .finish()
398 }
399}
400401impl<T: Hash + Eq + Debug, B: BuildHasher> Display for HashSet<T, B> {
402fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
403f.write_fmt(format_args!("#"))write!(f, "#")?;
404 f.debug_set().entries(self.iter()).finish()
405 }
406}