rune_alloc/hashbrown/set.rs
1use core::fmt;
2use core::hash::{BuildHasher, Hash};
3use core::iter::{Chain, FusedIterator};
4
5use super::Equivalent;
6
7use crate::alloc::{Allocator, Global};
8use crate::borrow::TryToOwned;
9use crate::clone::TryClone;
10use crate::error::Error;
11use crate::iter::{TryExtend, TryFromIteratorIn};
12#[cfg(test)]
13use crate::testing::*;
14
15use super::map::{self, DefaultHashBuilder, ExtractIfInner, HashMap, Keys};
16use super::raw::RawTable;
17
18// Future Optimization (FIXME!)
19// =============================
20//
21// Iteration over zero sized values is a noop. There is no need
22// for `bucket.val` in the case of HashSet. I suppose we would need HKT
23// to get rid of it properly.
24
25/// A hash set implemented as a `HashMap` where the value is `()`.
26///
27/// As with the [`HashMap`] type, a `HashSet` requires that the elements
28/// implement the [`Eq`] and [`Hash`] traits. This can frequently be achieved by
29/// using `#[derive(PartialEq, Eq, Hash)]`. If you implement these yourself,
30/// it is important that the following property holds:
31///
32/// ```text
33/// k1 == k2 -> hash(k1) == hash(k2)
34/// ```
35///
36/// In other words, if two keys are equal, their hashes must be equal.
37///
38///
39/// It is a logic error for an item to be modified in such a way that the
40/// item's hash, as determined by the [`Hash`] trait, or its equality, as
41/// determined by the [`Eq`] trait, changes while it is in the set. This is
42/// normally only possible through [`Cell`], [`RefCell`], global state, I/O, or
43/// unsafe code.
44///
45/// It is also a logic error for the [`Hash`] implementation of a key to panic.
46/// This is generally only possible if the trait is implemented manually. If a
47/// panic does occur then the contents of the `HashSet` may become corrupted and
48/// some items may be dropped from the table.
49///
50/// # Examples
51///
52/// ```
53/// use rune::alloc::HashSet;
54/// // Type inference lets us omit an explicit type signature (which
55/// // would be `HashSet<String>` in this example).
56/// let mut books = HashSet::new();
57///
58/// // Add some books.
59/// books.try_insert("A Dance With Dragons".to_string())?;
60/// books.try_insert("To Kill a Mockingbird".to_string())?;
61/// books.try_insert("The Odyssey".to_string())?;
62/// books.try_insert("The Great Gatsby".to_string())?;
63///
64/// // Check for a specific one.
65/// if !books.contains("The Winds of Winter") {
66/// println!("We have {} books, but The Winds of Winter ain't one.",
67/// books.len());
68/// }
69///
70/// // Remove a book.
71/// books.remove("The Odyssey");
72///
73/// // Iterate over everything.
74/// for book in &books {
75/// println!("{}", book);
76/// }
77/// # Ok::<_, rune::alloc::Error>(())
78/// ```
79///
80/// The easiest way to use `HashSet` with a custom type is to derive
81/// [`Eq`] and [`Hash`]. We must also derive [`PartialEq`]. This will in the
82/// future be implied by [`Eq`].
83///
84/// ```
85/// use rune::alloc::HashSet;
86///
87/// #[derive(Hash, Eq, PartialEq, Debug)]
88/// struct Viking {
89/// name: String,
90/// power: usize,
91/// }
92///
93/// let mut vikings = HashSet::new();
94///
95/// vikings.try_insert(Viking { name: "Einar".to_string(), power: 9 })?;
96/// vikings.try_insert(Viking { name: "Einar".to_string(), power: 9 })?;
97/// vikings.try_insert(Viking { name: "Olaf".to_string(), power: 4 })?;
98/// vikings.try_insert(Viking { name: "Harald".to_string(), power: 8 })?;
99///
100/// // Use derived implementation to print the vikings.
101/// for x in &vikings {
102/// println!("{:?}", x);
103/// }
104/// # Ok::<_, rune::alloc::Error>(())
105/// ```
106///
107/// A `HashSet` with fixed list of elements can be initialized from an array:
108///
109/// ```
110/// use rune::alloc::HashSet;
111/// use rune::alloc::prelude::*;
112///
113/// let viking_names: HashSet<&'static str> =
114/// [ "Einar", "Olaf", "Harald" ].iter().copied().try_collect()?;
115/// // use the values stored in the set
116/// # Ok::<_, rune::alloc::Error>(())
117/// ```
118///
119/// [`Cell`]: https://doc.rust-lang.org/std/cell/struct.Cell.html
120/// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html
121/// [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html
122/// [`HashMap`]: struct.HashMap.html
123/// [`PartialEq`]: https://doc.rust-lang.org/std/cmp/trait.PartialEq.html
124/// [`RefCell`]: https://doc.rust-lang.org/std/cell/struct.RefCell.html
125pub struct HashSet<T, S = DefaultHashBuilder, A: Allocator = Global> {
126 pub(crate) map: HashMap<T, (), S, A>,
127}
128
129impl<T, S, A: Allocator + Clone> TryClone for HashSet<T, S, A>
130where
131 T: TryClone,
132 S: Clone,
133{
134 fn try_clone(&self) -> Result<Self, Error> {
135 Ok(HashSet {
136 map: self.map.try_clone()?,
137 })
138 }
139
140 fn try_clone_from(&mut self, source: &Self) -> Result<(), Error> {
141 self.map.try_clone_from(&source.map)?;
142 Ok(())
143 }
144}
145
146#[cfg(test)]
147impl<T, S, A: Allocator + Clone> Clone for HashSet<T, S, A>
148where
149 T: TryClone,
150 S: Clone,
151{
152 fn clone(&self) -> Self {
153 self.try_clone().abort()
154 }
155
156 fn clone_from(&mut self, source: &Self) {
157 self.map.try_clone_from(&source.map).abort();
158 }
159}
160
161impl<T> HashSet<T, DefaultHashBuilder> {
162 /// Creates an empty `HashSet`.
163 ///
164 /// The hash set is initially created with a capacity of 0, so it will not allocate until it
165 /// is first inserted into.
166 ///
167 /// # HashDoS resistance
168 ///
169 /// The `hash_builder` normally use a fixed key by default and that does
170 /// not allow the `HashSet` to be protected against attacks such as [`HashDoS`].
171 /// Users who require HashDoS resistance should explicitly use
172 /// [`ahash::RandomState`] or [`std::collections::hash_map::RandomState`]
173 /// as the hasher when creating a [`HashSet`], for example with
174 /// [`with_hasher`](HashSet::with_hasher) method.
175 ///
176 /// [`HashDoS`]: https://en.wikipedia.org/wiki/Collision_attack
177 /// [`std::collections::hash_map::RandomState`]: https://doc.rust-lang.org/std/collections/hash_map/struct.RandomState.html
178 ///
179 /// # Examples
180 ///
181 /// ```
182 /// use rune::alloc::HashSet;
183 /// let set: HashSet<i32> = HashSet::new();
184 /// ```
185 #[cfg_attr(feature = "inline-more", inline)]
186 pub fn new() -> Self {
187 Self {
188 map: HashMap::new(),
189 }
190 }
191
192 /// Creates an empty `HashSet` with the specified capacity.
193 ///
194 /// The hash set will be able to hold at least `capacity` elements without
195 /// reallocating. If `capacity` is 0, the hash set will not allocate.
196 ///
197 /// # HashDoS resistance
198 ///
199 /// The `hash_builder` normally use a fixed key by default and that does not
200 /// allow the `HashSet` to be protected against attacks such as [`HashDoS`].
201 /// Users who require HashDoS resistance should explicitly use
202 /// [`ahash::RandomState`] or [`std::collections::hash_map::RandomState`] as
203 /// the hasher when creating a [`HashSet`], for example with
204 /// [`try_with_capacity_and_hasher`] method.
205 ///
206 /// [`try_with_capacity_and_hasher`]: HashSet::try_with_capacity_and_hasher
207 /// [`HashDoS`]: https://en.wikipedia.org/wiki/Collision_attack
208 /// [`std::collections::hash_map::RandomState`]: https://doc.rust-lang.org/std/collections/hash_map/struct.RandomState.html
209 ///
210 /// # Examples
211 ///
212 /// ```
213 /// use rune::alloc::HashSet;
214 /// let set: HashSet<i32> = HashSet::try_with_capacity(10)?;
215 /// assert!(set.capacity() >= 10);
216 /// # Ok::<_, rune::alloc::Error>(())
217 /// ```
218 #[cfg_attr(feature = "inline-more", inline)]
219 pub fn try_with_capacity(capacity: usize) -> Result<Self, Error> {
220 Ok(Self {
221 map: HashMap::try_with_capacity(capacity)?,
222 })
223 }
224
225 #[cfg(test)]
226 pub(crate) fn with_capacity(capacity: usize) -> Self {
227 Self::try_with_capacity(capacity).abort()
228 }
229}
230
231impl<T: Hash + Eq, A: Allocator> HashSet<T, DefaultHashBuilder, A> {
232 /// Creates an empty `HashSet`.
233 ///
234 /// The hash set is initially created with a capacity of 0, so it will not allocate until it
235 /// is first inserted into.
236 ///
237 /// # HashDoS resistance
238 ///
239 /// The `hash_builder` normally use a fixed key by default and that does
240 /// not allow the `HashSet` to be protected against attacks such as [`HashDoS`].
241 /// Users who require HashDoS resistance should explicitly use
242 /// [`ahash::RandomState`] or [`std::collections::hash_map::RandomState`]
243 /// as the hasher when creating a [`HashSet`], for example with
244 /// [`with_hasher_in`](HashSet::with_hasher_in) method.
245 ///
246 /// [`HashDoS`]: https://en.wikipedia.org/wiki/Collision_attack
247 /// [`std::collections::hash_map::RandomState`]: https://doc.rust-lang.org/std/collections/hash_map/struct.RandomState.html
248 ///
249 /// # Examples
250 ///
251 /// ```
252 /// use rune::alloc::HashSet;
253 /// use rune::alloc::alloc::Global;
254 ///
255 /// let set: HashSet<i32> = HashSet::new_in(Global);
256 /// ```
257 #[cfg_attr(feature = "inline-more", inline)]
258 pub fn new_in(alloc: A) -> Self {
259 Self {
260 map: HashMap::new_in(alloc),
261 }
262 }
263
264 /// Creates an empty `HashSet` with the specified capacity.
265 ///
266 /// The hash set will be able to hold at least `capacity` elements without
267 /// reallocating. If `capacity` is 0, the hash set will not allocate.
268 ///
269 /// # HashDoS resistance
270 ///
271 /// The `hash_builder` normally use a fixed key by default and that does not
272 /// allow the `HashSet` to be protected against attacks such as [`HashDoS`].
273 /// Users who require HashDoS resistance should explicitly use
274 /// [`ahash::RandomState`] or [`std::collections::hash_map::RandomState`] as
275 /// the hasher when creating a [`HashSet`], for example with
276 /// [`try_with_capacity_and_hasher_in`] method.
277 ///
278 /// [`try_with_capacity_and_hasher_in`]:
279 /// HashSet::try_with_capacity_and_hasher_in
280 /// [`HashDoS`]: https://en.wikipedia.org/wiki/Collision_attack
281 /// [`std::collections::hash_map::RandomState`]:
282 /// https://doc.rust-lang.org/std/collections/hash_map/struct.RandomState.html
283 ///
284 /// # Examples
285 ///
286 /// ```
287 /// use rune::alloc::HashSet;
288 /// let set: HashSet<i32> = HashSet::try_with_capacity(10)?;
289 /// assert!(set.capacity() >= 10);
290 /// # Ok::<_, rune::alloc::Error>(())
291 /// ```
292 #[cfg_attr(feature = "inline-more", inline)]
293 pub fn try_with_capacity_in(capacity: usize, alloc: A) -> Result<Self, Error> {
294 Ok(Self {
295 map: HashMap::try_with_capacity_in(capacity, alloc)?,
296 })
297 }
298}
299
300impl<T, S, A: Allocator> HashSet<T, S, A> {
301 /// Returns the number of elements the set can hold without reallocating.
302 ///
303 /// # Examples
304 ///
305 /// ```
306 /// use rune::alloc::HashSet;
307 ///
308 /// let set: HashSet<i32> = HashSet::try_with_capacity(100)?;
309 /// assert!(set.capacity() >= 100);
310 /// # Ok::<_, rune::alloc::Error>(())
311 /// ```
312 #[cfg_attr(feature = "inline-more", inline)]
313 pub fn capacity(&self) -> usize {
314 self.map.capacity()
315 }
316
317 /// An iterator visiting all elements in arbitrary order.
318 /// The iterator element type is `&'a T`.
319 ///
320 /// # Examples
321 ///
322 /// ```
323 /// use rune::alloc::HashSet;
324 ///
325 /// let mut set = HashSet::new();
326 /// set.try_insert("a")?;
327 /// set.try_insert("b")?;
328 ///
329 /// // Will print in an arbitrary order.
330 /// for x in set.iter() {
331 /// println!("{}", x);
332 /// }
333 /// # Ok::<_, rune::alloc::Error>(())
334 /// ```
335 #[cfg_attr(feature = "inline-more", inline)]
336 pub fn iter(&self) -> Iter<'_, T> {
337 Iter {
338 iter: self.map.keys(),
339 }
340 }
341
342 /// Returns the number of elements in the set.
343 ///
344 /// # Examples
345 ///
346 /// ```
347 /// use rune::alloc::HashSet;
348 ///
349 /// let mut v = HashSet::new();
350 /// assert_eq!(v.len(), 0);
351 /// v.try_insert(1)?;
352 /// assert_eq!(v.len(), 1);
353 /// # Ok::<_, rune::alloc::Error>(())
354 /// ```
355 #[cfg_attr(feature = "inline-more", inline)]
356 pub fn len(&self) -> usize {
357 self.map.len()
358 }
359
360 /// Returns `true` if the set contains no elements.
361 ///
362 /// # Examples
363 ///
364 /// ```
365 /// use rune::alloc::HashSet;
366 ///
367 /// let mut v = HashSet::new();
368 /// assert!(v.is_empty());
369 /// v.try_insert(1)?;
370 /// assert!(!v.is_empty());
371 /// # Ok::<_, rune::alloc::Error>(())
372 /// ```
373 #[cfg_attr(feature = "inline-more", inline)]
374 pub fn is_empty(&self) -> bool {
375 self.map.is_empty()
376 }
377
378 /// Clears the set, returning all elements in an iterator.
379 ///
380 /// # Examples
381 ///
382 /// ```
383 /// use rune::alloc::HashSet;
384 ///
385 /// let mut set: HashSet<_> = HashSet::try_from([1, 2, 3])?;
386 /// assert!(!set.is_empty());
387 ///
388 /// // print 1, 2, 3 in an arbitrary order
389 /// for i in set.drain() {
390 /// println!("{}", i);
391 /// }
392 ///
393 /// assert!(set.is_empty());
394 /// # Ok::<_, rune::alloc::Error>(())
395 /// ```
396 #[cfg_attr(feature = "inline-more", inline)]
397 pub fn drain(&mut self) -> Drain<'_, T, A> {
398 Drain {
399 iter: self.map.drain(),
400 }
401 }
402
403 /// Retains only the elements specified by the predicate.
404 ///
405 /// In other words, remove all elements `e` such that `f(&e)` returns `false`.
406 ///
407 /// # Examples
408 ///
409 /// ```
410 /// use rune::alloc::HashSet;
411 ///
412 /// let mut set: HashSet<i32> = HashSet::try_from([1, 2, 3, 4, 5, 6])?;
413 /// set.retain(|&k| k % 2 == 0);
414 /// assert_eq!(set.len(), 3);
415 /// # Ok::<_, rune::alloc::Error>(())
416 /// ```
417 pub fn retain<F>(&mut self, mut f: F)
418 where
419 F: FnMut(&T) -> bool,
420 {
421 self.map.retain(|k, _| f(k));
422 }
423
424 /// Drains elements which are true under the given predicate, and returns an
425 /// iterator over the removed items.
426 ///
427 /// In other words, move all elements `e` such that `f(&e)` returns `true`
428 /// out into another iterator.
429 ///
430 /// If the returned `ExtractIf` is not exhausted, e.g. because it is dropped
431 /// without iterating or the iteration short-circuits, then the remaining
432 /// elements will be retained. Use [`retain`] with a negated predicate if
433 /// you do not need the returned iterator.
434 ///
435 /// [`retain`]: Self::retain
436 ///
437 /// # Examples
438 ///
439 /// ```
440 /// use rune::alloc::{try_vec, HashSet, Vec};
441 /// use rune::alloc::prelude::*;
442 ///
443 /// let mut set: HashSet<i32> = (0..8).try_collect()?;
444 /// let drained: HashSet<i32> = set.extract_if(|v| v % 2 == 0).try_collect()?;
445 ///
446 /// let mut evens = drained.into_iter().try_collect::<Vec<_>>()?;
447 /// let mut odds = set.into_iter().try_collect::<Vec<_>>()?;
448 /// evens.sort();
449 /// odds.sort();
450 ///
451 /// assert_eq!(evens, try_vec![0, 2, 4, 6]);
452 /// assert_eq!(odds, try_vec![1, 3, 5, 7]);
453 /// # Ok::<_, rune::alloc::Error>(())
454 /// ```
455 #[cfg_attr(feature = "inline-more", inline)]
456 pub fn extract_if<F>(&mut self, f: F) -> ExtractIf<'_, T, F, A>
457 where
458 F: FnMut(&T) -> bool,
459 {
460 ExtractIf {
461 f,
462 inner: ExtractIfInner {
463 iter: unsafe { self.map.table.iter() },
464 table: &mut self.map.table,
465 },
466 }
467 }
468
469 /// Clears the set, removing all values.
470 ///
471 /// # Examples
472 ///
473 /// ```
474 /// use rune::alloc::HashSet;
475 ///
476 /// let mut v = HashSet::new();
477 /// v.try_insert(1)?;
478 /// v.clear();
479 /// assert!(v.is_empty());
480 /// # Ok::<_, rune::alloc::Error>(())
481 /// ```
482 #[cfg_attr(feature = "inline-more", inline)]
483 pub fn clear(&mut self) {
484 self.map.clear();
485 }
486}
487
488impl<T, S> HashSet<T, S, Global> {
489 /// Creates a new empty hash set which will use the given hasher to hash
490 /// keys.
491 ///
492 /// The hash set is initially created with a capacity of 0, so it will not
493 /// allocate until it is first inserted into.
494 ///
495 /// # HashDoS resistance
496 ///
497 /// The `hash_builder` normally use a fixed key by default and that does
498 /// not allow the `HashSet` to be protected against attacks such as [`HashDoS`].
499 /// Users who require HashDoS resistance should explicitly use
500 /// [`ahash::RandomState`] or [`std::collections::hash_map::RandomState`]
501 /// as the hasher when creating a [`HashSet`].
502 ///
503 /// The `hash_builder` passed should implement the [`BuildHasher`] trait for
504 /// the HashSet to be useful, see its documentation for details.
505 ///
506 /// [`HashDoS`]: https://en.wikipedia.org/wiki/Collision_attack
507 /// [`std::collections::hash_map::RandomState`]: https://doc.rust-lang.org/std/collections/hash_map/struct.RandomState.html
508 /// [`BuildHasher`]: https://doc.rust-lang.org/std/hash/trait.BuildHasher.html
509 ///
510 /// # Examples
511 ///
512 /// ```
513 /// use rune::alloc::HashSet;
514 /// use rune::alloc::hash_map::DefaultHashBuilder;
515 ///
516 /// let s = DefaultHashBuilder::default();
517 /// let mut set = HashSet::with_hasher(s);
518 /// set.try_insert(2)?;
519 /// # Ok::<_, rune::alloc::Error>(())
520 /// ```
521 #[cfg_attr(feature = "inline-more", inline)]
522 pub const fn with_hasher(hasher: S) -> Self {
523 Self {
524 map: HashMap::with_hasher(hasher),
525 }
526 }
527
528 /// Creates an empty `HashSet` with the specified capacity, using
529 /// `hasher` to hash the keys.
530 ///
531 /// The hash set will be able to hold at least `capacity` elements without
532 /// reallocating. If `capacity` is 0, the hash set will not allocate.
533 ///
534 /// # HashDoS resistance
535 ///
536 /// The `hash_builder` normally use a fixed key by default and that does
537 /// not allow the `HashSet` to be protected against attacks such as [`HashDoS`].
538 /// Users who require HashDoS resistance should explicitly use
539 /// [`ahash::RandomState`] or [`std::collections::hash_map::RandomState`]
540 /// as the hasher when creating a [`HashSet`].
541 ///
542 /// The `hash_builder` passed should implement the [`BuildHasher`] trait for
543 /// the HashSet to be useful, see its documentation for details.
544 ///
545 /// [`HashDoS`]: https://en.wikipedia.org/wiki/Collision_attack
546 /// [`std::collections::hash_map::RandomState`]: https://doc.rust-lang.org/std/collections/hash_map/struct.RandomState.html
547 /// [`BuildHasher`]: https://doc.rust-lang.org/std/hash/trait.BuildHasher.html
548 ///
549 /// # Examples
550 ///
551 /// ```
552 /// use rune::alloc::HashSet;
553 /// use rune::alloc::hash_map::DefaultHashBuilder;
554 ///
555 /// let s = DefaultHashBuilder::default();
556 /// let mut set = HashSet::try_with_capacity_and_hasher(10, s)?;
557 /// set.try_insert(1)?;
558 /// # Ok::<_, rune::alloc::Error>(())
559 /// ```
560 #[cfg_attr(feature = "inline-more", inline)]
561 pub fn try_with_capacity_and_hasher(capacity: usize, hasher: S) -> Result<Self, Error> {
562 Ok(Self {
563 map: HashMap::try_with_capacity_and_hasher(capacity, hasher)?,
564 })
565 }
566
567 #[cfg(test)]
568 pub(crate) fn with_capacity_and_hasher(capacity: usize, hasher: S) -> Self {
569 Self::try_with_capacity_and_hasher(capacity, hasher).abort()
570 }
571}
572
573impl<T, S, A> HashSet<T, S, A>
574where
575 A: Allocator,
576{
577 /// Returns a reference to the underlying allocator.
578 #[inline]
579 pub fn allocator(&self) -> &A {
580 self.map.allocator()
581 }
582
583 /// Creates a new empty hash set which will use the given hasher to hash
584 /// keys.
585 ///
586 /// The hash set is initially created with a capacity of 0, so it will not
587 /// allocate until it is first inserted into.
588 ///
589 /// # HashDoS resistance
590 ///
591 /// The `hash_builder` normally use a fixed key by default and that does
592 /// not allow the `HashSet` to be protected against attacks such as [`HashDoS`].
593 /// Users who require HashDoS resistance should explicitly use
594 /// [`ahash::RandomState`] or [`std::collections::hash_map::RandomState`]
595 /// as the hasher when creating a [`HashSet`].
596 ///
597 /// The `hash_builder` passed should implement the [`BuildHasher`] trait for
598 /// the HashSet to be useful, see its documentation for details.
599 ///
600 /// [`HashDoS`]: https://en.wikipedia.org/wiki/Collision_attack
601 /// [`std::collections::hash_map::RandomState`]: https://doc.rust-lang.org/std/collections/hash_map/struct.RandomState.html
602 /// [`BuildHasher`]: https://doc.rust-lang.org/std/hash/trait.BuildHasher.html
603 ///
604 /// # Examples
605 ///
606 /// ```
607 /// use rune::alloc::HashSet;
608 /// use rune::alloc::hash_map::DefaultHashBuilder;
609 ///
610 /// let s = DefaultHashBuilder::default();
611 /// let mut set = HashSet::with_hasher(s);
612 /// set.try_insert(2)?;
613 /// # Ok::<_, rune::alloc::Error>(())
614 /// ```
615 #[cfg_attr(feature = "inline-more", inline)]
616 pub const fn with_hasher_in(hasher: S, alloc: A) -> Self {
617 Self {
618 map: HashMap::with_hasher_in(hasher, alloc),
619 }
620 }
621
622 /// Creates an empty `HashSet` with the specified capacity, using
623 /// `hasher` to hash the keys.
624 ///
625 /// The hash set will be able to hold at least `capacity` elements without
626 /// reallocating. If `capacity` is 0, the hash set will not allocate.
627 ///
628 /// # HashDoS resistance
629 ///
630 /// The `hash_builder` normally use a fixed key by default and that does
631 /// not allow the `HashSet` to be protected against attacks such as [`HashDoS`].
632 /// Users who require HashDoS resistance should explicitly use
633 /// [`ahash::RandomState`] or [`std::collections::hash_map::RandomState`]
634 /// as the hasher when creating a [`HashSet`].
635 ///
636 /// The `hash_builder` passed should implement the [`BuildHasher`] trait for
637 /// the HashSet to be useful, see its documentation for details.
638 ///
639 /// [`HashDoS`]: https://en.wikipedia.org/wiki/Collision_attack
640 /// [`std::collections::hash_map::RandomState`]: https://doc.rust-lang.org/std/collections/hash_map/struct.RandomState.html
641 /// [`BuildHasher`]: https://doc.rust-lang.org/std/hash/trait.BuildHasher.html
642 ///
643 /// # Examples
644 ///
645 /// ```
646 /// use rune::alloc::HashSet;
647 /// use rune::alloc::alloc::Global;
648 /// use rune::alloc::hash_map::DefaultHashBuilder;
649 ///
650 /// let s = DefaultHashBuilder::default();
651 /// let mut set = HashSet::try_with_capacity_and_hasher_in(10, s, Global)?;
652 /// set.try_insert(1)?;
653 /// # Ok::<_, rune::alloc::Error>(())
654 /// ```
655 #[cfg_attr(feature = "inline-more", inline)]
656 pub fn try_with_capacity_and_hasher_in(
657 capacity: usize,
658 hasher: S,
659 alloc: A,
660 ) -> Result<Self, Error> {
661 Ok(Self {
662 map: HashMap::try_with_capacity_and_hasher_in(capacity, hasher, alloc)?,
663 })
664 }
665
666 /// Returns a reference to the set's [`BuildHasher`].
667 ///
668 /// [`BuildHasher`]: https://doc.rust-lang.org/std/hash/trait.BuildHasher.html
669 ///
670 /// # Examples
671 ///
672 /// ```
673 /// use rune::alloc::HashSet;
674 /// use rune::alloc::hash_map::DefaultHashBuilder;
675 ///
676 /// let hasher = DefaultHashBuilder::default();
677 /// let set: HashSet<i32> = HashSet::with_hasher(hasher);
678 /// let hasher: &DefaultHashBuilder = set.hasher();
679 /// ```
680 #[cfg_attr(feature = "inline-more", inline)]
681 pub fn hasher(&self) -> &S {
682 self.map.hasher()
683 }
684}
685
686impl<T, S, A> HashSet<T, S, A>
687where
688 T: Eq + Hash,
689 S: BuildHasher,
690 A: Allocator,
691{
692 /// Tries to reserve capacity for at least `additional` more elements to be inserted
693 /// in the given `HashSet<K,V>`. The collection may reserve more space to avoid
694 /// frequent reallocations.
695 ///
696 /// # Errors
697 ///
698 /// If the capacity overflows, or the allocator reports a failure, then an error
699 /// is returned.
700 ///
701 /// # Examples
702 ///
703 /// ```
704 /// use rune::alloc::HashSet;
705 /// let mut set: HashSet<i32> = HashSet::new();
706 /// set.try_reserve(10).expect("why is the test harness OOMing on 10 bytes?");
707 /// ```
708 #[cfg_attr(feature = "inline-more", inline)]
709 pub fn try_reserve(&mut self, additional: usize) -> Result<(), Error> {
710 self.map.try_reserve(additional)
711 }
712
713 #[cfg(test)]
714 pub(crate) fn reserve(&mut self, additional: usize) {
715 self.try_reserve(additional).abort()
716 }
717
718 /// Shrinks the capacity of the set as much as possible. It will drop
719 /// down as much as possible while maintaining the internal rules
720 /// and possibly leaving some space in accordance with the resize policy.
721 ///
722 /// # Examples
723 ///
724 /// ```
725 /// use rune::alloc::HashSet;
726 ///
727 /// let mut set = HashSet::try_with_capacity(100)?;
728 /// set.try_insert(1)?;
729 /// set.try_insert(2)?;
730 /// assert!(set.capacity() >= 100);
731 /// set.try_shrink_to_fit()?;
732 /// assert!(set.capacity() >= 2);
733 /// # Ok::<_, rune::alloc::Error>(())
734 /// ```
735 #[cfg_attr(feature = "inline-more", inline)]
736 pub fn try_shrink_to_fit(&mut self) -> Result<(), Error> {
737 self.map.try_shrink_to_fit()
738 }
739
740 #[cfg(test)]
741 pub(crate) fn shrink_to_fit(&mut self) {
742 self.try_shrink_to_fit().abort();
743 }
744
745 /// Shrinks the capacity of the set with a lower limit. It will drop
746 /// down no lower than the supplied limit while maintaining the internal rules
747 /// and possibly leaving some space in accordance with the resize policy.
748 ///
749 /// Panics if the current capacity is smaller than the supplied
750 /// minimum capacity.
751 ///
752 /// # Examples
753 ///
754 /// ```
755 /// use rune::alloc::HashSet;
756 ///
757 /// let mut set = HashSet::try_with_capacity(100)?;
758 /// set.try_insert(1)?;
759 /// set.try_insert(2)?;
760 /// assert!(set.capacity() >= 100);
761 /// set.try_shrink_to(10)?;
762 /// assert!(set.capacity() >= 10);
763 /// set.try_shrink_to(0)?;
764 /// assert!(set.capacity() >= 2);
765 /// # Ok::<_, rune::alloc::Error>(())
766 /// ```
767 #[cfg_attr(feature = "inline-more", inline)]
768 pub fn try_shrink_to(&mut self, min_capacity: usize) -> Result<(), Error> {
769 self.map.try_shrink_to(min_capacity)
770 }
771
772 /// Visits the values representing the difference,
773 /// i.e., the values that are in `self` but not in `other`.
774 ///
775 /// # Examples
776 ///
777 /// ```
778 /// use rune::alloc::HashSet;
779 /// use rune::alloc::prelude::*;
780 ///
781 /// let a: HashSet<_> = HashSet::try_from([1, 2, 3])?;
782 /// let b: HashSet<_> = HashSet::try_from([4, 2, 3, 4])?;
783 ///
784 /// // Can be seen as `a - b`.
785 /// for x in a.difference(&b) {
786 /// println!("{}", x); // Print 1
787 /// }
788 ///
789 /// let diff: HashSet<_> = a.difference(&b).copied().try_collect()?;
790 /// assert_eq!(diff, HashSet::try_from([1])?);
791 ///
792 /// // Note that difference is not symmetric,
793 /// // and `b - a` means something else:
794 /// let diff: HashSet<_> = b.difference(&a).copied().try_collect()?;
795 /// assert_eq!(diff, HashSet::try_from([4])?);
796 /// # Ok::<_, rune::alloc::Error>(())
797 /// ```
798 #[cfg_attr(feature = "inline-more", inline)]
799 pub fn difference<'a>(&'a self, other: &'a Self) -> Difference<'a, T, S, A> {
800 Difference {
801 iter: self.iter(),
802 other,
803 }
804 }
805
806 /// Visits the values representing the symmetric difference,
807 /// i.e., the values that are in `self` or in `other` but not in both.
808 ///
809 /// # Examples
810 ///
811 /// ```
812 /// use rune::alloc::HashSet;
813 /// use rune::alloc::prelude::*;
814 ///
815 /// let a: HashSet<_> = HashSet::try_from([1, 2, 3])?;
816 /// let b: HashSet<_> = HashSet::try_from([4, 2, 3, 4])?;
817 ///
818 /// // Print 1, 4 in arbitrary order.
819 /// for x in a.symmetric_difference(&b) {
820 /// println!("{}", x);
821 /// }
822 ///
823 /// let diff1: HashSet<_> = a.symmetric_difference(&b).copied().try_collect()?;
824 /// let diff2: HashSet<_> = b.symmetric_difference(&a).copied().try_collect()?;
825 ///
826 /// assert_eq!(diff1, diff2);
827 /// assert_eq!(diff1, HashSet::try_from([1, 4])?);
828 /// # Ok::<_, rune::alloc::Error>(())
829 /// ```
830 #[cfg_attr(feature = "inline-more", inline)]
831 pub fn symmetric_difference<'a>(&'a self, other: &'a Self) -> SymmetricDifference<'a, T, S, A> {
832 SymmetricDifference {
833 iter: self.difference(other).chain(other.difference(self)),
834 }
835 }
836
837 /// Visits the values representing the intersection,
838 /// i.e., the values that are both in `self` and `other`.
839 ///
840 /// # Examples
841 ///
842 /// ```
843 /// use rune::alloc::HashSet;
844 /// use rune::alloc::prelude::*;
845 ///
846 /// let a: HashSet<_> = HashSet::try_from([1, 2, 3])?;
847 /// let b: HashSet<_> = HashSet::try_from([4, 2, 3, 4])?;
848 ///
849 /// // Print 2, 3 in arbitrary order.
850 /// for x in a.intersection(&b) {
851 /// println!("{}", x);
852 /// }
853 ///
854 /// let intersection: HashSet<_> = a.intersection(&b).copied().try_collect()?;
855 /// assert_eq!(intersection, HashSet::try_from([2, 3])?);
856 /// # Ok::<_, rune::alloc::Error>(())
857 /// ```
858 #[cfg_attr(feature = "inline-more", inline)]
859 pub fn intersection<'a>(&'a self, other: &'a Self) -> Intersection<'a, T, S, A> {
860 let (smaller, larger) = if self.len() <= other.len() {
861 (self, other)
862 } else {
863 (other, self)
864 };
865 Intersection {
866 iter: smaller.iter(),
867 other: larger,
868 }
869 }
870
871 /// Visits the values representing the union,
872 /// i.e., all the values in `self` or `other`, without duplicates.
873 ///
874 /// # Examples
875 ///
876 /// ```
877 /// use rune::alloc::HashSet;
878 /// use rune::alloc::prelude::*;
879 ///
880 /// let a: HashSet<_> = HashSet::try_from([1, 2, 3])?;
881 /// let b: HashSet<_> = HashSet::try_from([4, 2, 3, 4])?;
882 ///
883 /// // Print 1, 2, 3, 4 in arbitrary order.
884 /// for x in a.union(&b) {
885 /// println!("{}", x);
886 /// }
887 ///
888 /// let union: HashSet<_> = a.union(&b).copied().try_collect()?;
889 /// assert_eq!(union, HashSet::try_from([1, 2, 3, 4])?);
890 /// # Ok::<_, rune::alloc::Error>(())
891 /// ```
892 #[cfg_attr(feature = "inline-more", inline)]
893 pub fn union<'a>(&'a self, other: &'a Self) -> Union<'a, T, S, A> {
894 // We'll iterate one set in full, and only the remaining difference from the other.
895 // Use the smaller set for the difference in order to reduce hash lookups.
896 let (smaller, larger) = if self.len() <= other.len() {
897 (self, other)
898 } else {
899 (other, self)
900 };
901 Union {
902 iter: larger.iter().chain(smaller.difference(larger)),
903 }
904 }
905
906 /// Returns `true` if the set contains a value.
907 ///
908 /// The value may be any borrowed form of the set's value type, but
909 /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
910 /// the value type.
911 ///
912 /// # Examples
913 ///
914 /// ```
915 /// use rune::alloc::HashSet;
916 ///
917 /// let set: HashSet<_> = HashSet::try_from([1, 2, 3])?;
918 /// assert_eq!(set.contains(&1), true);
919 /// assert_eq!(set.contains(&4), false);
920 /// # Ok::<_, rune::alloc::Error>(())
921 /// ```
922 ///
923 /// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html
924 /// [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html
925 #[cfg_attr(feature = "inline-more", inline)]
926 pub fn contains<Q>(&self, value: &Q) -> bool
927 where
928 Q: ?Sized + Hash + Equivalent<T>,
929 {
930 self.map.contains_key(value)
931 }
932
933 /// Returns a reference to the value in the set, if any, that is equal to the given value.
934 ///
935 /// The value may be any borrowed form of the set's value type, but
936 /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
937 /// the value type.
938 ///
939 /// # Examples
940 ///
941 /// ```
942 /// use rune::alloc::HashSet;
943 ///
944 /// let set: HashSet<_> = HashSet::try_from([1, 2, 3])?;
945 /// assert_eq!(set.get(&2), Some(&2));
946 /// assert_eq!(set.get(&4), None);
947 /// # Ok::<_, rune::alloc::Error>(())
948 /// ```
949 ///
950 /// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html
951 /// [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html
952 #[cfg_attr(feature = "inline-more", inline)]
953 pub fn get<Q>(&self, value: &Q) -> Option<&T>
954 where
955 Q: ?Sized + Hash + Equivalent<T>,
956 {
957 // Avoid `Option::map` because it bloats LLVM IR.
958 match self.map.get_key_value(value) {
959 Some((k, _)) => Some(k),
960 None => None,
961 }
962 }
963
964 /// Inserts the given `value` into the set if it is not present, then
965 /// returns a reference to the value in the set.
966 ///
967 /// # Examples
968 ///
969 /// ```
970 /// use rune::alloc::HashSet;
971 ///
972 /// let mut set: HashSet<_> = HashSet::try_from([1, 2, 3])?;
973 /// assert_eq!(set.len(), 3);
974 /// assert_eq!(set.get_or_try_insert(2)?, &2);
975 /// assert_eq!(set.get_or_try_insert(100)?, &100);
976 /// assert_eq!(set.len(), 4); // 100 was inserted
977 /// # Ok::<_, rune::alloc::Error>(())
978 /// ```
979 #[cfg_attr(feature = "inline-more", inline)]
980 pub fn get_or_try_insert(&mut self, value: T) -> Result<&T, Error> {
981 // Although the raw entry gives us `&mut T`, we only return `&T` to be consistent with
982 // `get`. Key mutation is "raw" because you're not supposed to affect `Eq` or `Hash`.
983 Ok(self
984 .map
985 .raw_entry_mut()
986 .from_key(&value)
987 .or_try_insert(value, ())?
988 .0)
989 }
990
991 /// Inserts an owned copy of the given `value` into the set if it is not
992 /// present, then returns a reference to the value in the set.
993 ///
994 /// # Examples
995 ///
996 /// ```
997 /// use rune::alloc::{HashSet, String, Error};
998 /// use rune::alloc::prelude::*;
999 ///
1000 /// let mut set: HashSet<String> = ["cat", "dog", "horse"]
1001 /// .iter().map(|&pet| pet.try_to_owned()).try_collect::<Result<_, _>>()??;
1002 ///
1003 /// assert_eq!(set.len(), 3);
1004 /// for &pet in &["cat", "dog", "fish"] {
1005 /// let value = set.get_or_try_insert_owned(pet)?;
1006 /// assert_eq!(value, pet);
1007 /// }
1008 /// assert_eq!(set.len(), 4); // a new "fish" was inserted
1009 /// # Ok::<_, rune::alloc::Error>(())
1010 /// ```
1011 #[inline]
1012 pub fn get_or_try_insert_owned<Q>(&mut self, value: &Q) -> Result<&T, Error>
1013 where
1014 Q: ?Sized + Hash + Equivalent<T> + TryToOwned<Owned = T>,
1015 {
1016 // Although the raw entry gives us `&mut T`, we only return `&T` to be consistent with
1017 // `get`. Key mutation is "raw" because you're not supposed to affect `Eq` or `Hash`.
1018 let (key, _) = match self.map.raw_entry_mut().from_key(value) {
1019 map::RawEntryMut::Occupied(entry) => entry.into_key_value(),
1020 map::RawEntryMut::Vacant(entry) => entry.try_insert(value.try_to_owned()?, ())?,
1021 };
1022
1023 Ok(key)
1024 }
1025
1026 /// Inserts a value computed from `f` into the set if the given `value` is
1027 /// not present, then returns a reference to the value in the set.
1028 ///
1029 /// # Examples
1030 ///
1031 /// ```
1032 /// use rune::alloc::{HashSet, String, Error};
1033 /// use rune::alloc::prelude::*;
1034 ///
1035 /// let mut set: HashSet<String> = ["cat", "dog", "horse"]
1036 /// .iter().map(|&pet| pet.try_to_owned()).try_collect::<Result<_, _>>()??;
1037 ///
1038 /// assert_eq!(set.len(), 3);
1039 /// for &pet in &["cat", "dog", "fish"] {
1040 /// let value = set.get_or_try_insert_with(pet, str::try_to_owned)?;
1041 /// assert_eq!(value, pet);
1042 /// }
1043 /// assert_eq!(set.len(), 4); // a new "fish" was inserted
1044 /// # Ok::<_, rune::alloc::Error>(())
1045 /// ```
1046 #[cfg_attr(feature = "inline-more", inline)]
1047 pub fn get_or_try_insert_with<Q, F>(&mut self, value: &Q, f: F) -> Result<&T, Error>
1048 where
1049 Q: ?Sized + Hash + Equivalent<T>,
1050 F: FnOnce(&Q) -> Result<T, Error>,
1051 {
1052 // Although the raw entry gives us `&mut T`, we only return `&T` to be consistent with
1053 // `get`. Key mutation is "raw" because you're not supposed to affect `Eq` or `Hash`.
1054 let (key, _) = match self.map.raw_entry_mut().from_key(value) {
1055 map::RawEntryMut::Occupied(entry) => entry.into_key_value(),
1056 map::RawEntryMut::Vacant(entry) => entry.try_insert(f(value)?, ())?,
1057 };
1058
1059 Ok(key)
1060 }
1061
1062 /// Gets the given value's corresponding entry in the set for in-place manipulation.
1063 ///
1064 /// # Examples
1065 ///
1066 /// ```
1067 /// use rune::alloc::HashSet;
1068 /// use rune::alloc::hash_set::Entry::*;
1069 ///
1070 /// let mut singles = HashSet::new();
1071 /// let mut dupes = HashSet::new();
1072 ///
1073 /// for ch in "a short treatise on fungi".chars() {
1074 /// if let Vacant(dupe_entry) = dupes.entry(ch) {
1075 /// // We haven't already seen a duplicate, so
1076 /// // check if we've at least seen it once.
1077 /// match singles.entry(ch) {
1078 /// Vacant(single_entry) => {
1079 /// // We found a new character for the first time.
1080 /// single_entry.try_insert()?;
1081 /// }
1082 /// Occupied(single_entry) => {
1083 /// // We've already seen this once, "move" it to dupes.
1084 /// single_entry.remove();
1085 /// dupe_entry.try_insert()?;
1086 /// }
1087 /// }
1088 /// }
1089 /// }
1090 ///
1091 /// assert!(!singles.contains(&'t') && dupes.contains(&'t'));
1092 /// assert!(singles.contains(&'u') && !dupes.contains(&'u'));
1093 /// assert!(!singles.contains(&'v') && !dupes.contains(&'v'));
1094 /// # Ok::<_, rune::alloc::Error>(())
1095 /// ```
1096 #[cfg_attr(feature = "inline-more", inline)]
1097 pub fn entry(&mut self, value: T) -> Entry<'_, T, S, A> {
1098 match self.map.entry(value) {
1099 map::Entry::Occupied(entry) => Entry::Occupied(OccupiedEntry { inner: entry }),
1100 map::Entry::Vacant(entry) => Entry::Vacant(VacantEntry { inner: entry }),
1101 }
1102 }
1103
1104 /// Returns `true` if `self` has no elements in common with `other`.
1105 /// This is equivalent to checking for an empty intersection.
1106 ///
1107 /// # Examples
1108 ///
1109 /// ```
1110 /// use rune::alloc::HashSet;
1111 ///
1112 /// let a = HashSet::try_from([1, 2, 3])?;
1113 /// let mut b = HashSet::new();
1114 ///
1115 /// assert_eq!(a.is_disjoint(&b), true);
1116 /// b.try_insert(4)?;
1117 /// assert_eq!(a.is_disjoint(&b), true);
1118 /// b.try_insert(1)?;
1119 /// assert_eq!(a.is_disjoint(&b), false);
1120 /// # Ok::<_, rune::alloc::Error>(())
1121 /// ```
1122 pub fn is_disjoint(&self, other: &Self) -> bool {
1123 self.iter().all(|v| !other.contains(v))
1124 }
1125
1126 /// Returns `true` if the set is a subset of another,
1127 /// i.e., `other` contains at least all the values in `self`.
1128 ///
1129 /// # Examples
1130 ///
1131 /// ```
1132 /// use rune::alloc::HashSet;
1133 ///
1134 /// let sup = HashSet::try_from([1, 2, 3])?;
1135 /// let mut set = HashSet::new();
1136 ///
1137 /// assert_eq!(set.is_subset(&sup), true);
1138 /// set.try_insert(2)?;
1139 /// assert_eq!(set.is_subset(&sup), true);
1140 /// set.try_insert(4)?;
1141 /// assert_eq!(set.is_subset(&sup), false);
1142 /// # Ok::<_, rune::alloc::Error>(())
1143 /// ```
1144 pub fn is_subset(&self, other: &Self) -> bool {
1145 self.len() <= other.len() && self.iter().all(|v| other.contains(v))
1146 }
1147
1148 /// Returns `true` if the set is a superset of another,
1149 /// i.e., `self` contains at least all the values in `other`.
1150 ///
1151 /// # Examples
1152 ///
1153 /// ```
1154 /// use rune::alloc::HashSet;
1155 ///
1156 /// let sub = HashSet::try_from([1, 2])?;
1157 /// let mut set = HashSet::new();
1158 ///
1159 /// assert_eq!(set.is_superset(&sub), false);
1160 ///
1161 /// set.try_insert(0)?;
1162 /// set.try_insert(1)?;
1163 /// assert_eq!(set.is_superset(&sub), false);
1164 ///
1165 /// set.try_insert(2)?;
1166 /// assert_eq!(set.is_superset(&sub), true);
1167 /// # Ok::<_, rune::alloc::Error>(())
1168 /// ```
1169 #[cfg_attr(feature = "inline-more", inline)]
1170 pub fn is_superset(&self, other: &Self) -> bool {
1171 other.is_subset(self)
1172 }
1173
1174 /// Adds a value to the set.
1175 ///
1176 /// If the set did not have this value present, `true` is returned.
1177 ///
1178 /// If the set did have this value present, `false` is returned.
1179 ///
1180 /// # Examples
1181 ///
1182 /// ```
1183 /// use rune::alloc::HashSet;
1184 ///
1185 /// let mut set = HashSet::new();
1186 ///
1187 /// assert_eq!(set.try_insert(2)?, true);
1188 /// assert_eq!(set.try_insert(2)?, false);
1189 /// assert_eq!(set.len(), 1);
1190 /// # Ok::<_, rune::alloc::Error>(())
1191 /// ```
1192 #[cfg_attr(feature = "inline-more", inline)]
1193 pub fn try_insert(&mut self, value: T) -> Result<bool, Error> {
1194 Ok(self.map.try_insert(value, ())?.is_none())
1195 }
1196
1197 #[cfg(test)]
1198 pub(crate) fn insert(&mut self, value: T) -> bool {
1199 self.try_insert(value).abort()
1200 }
1201
1202 /// Insert a value the set without checking if the value already exists in the set.
1203 ///
1204 /// Returns a reference to the value just inserted.
1205 ///
1206 /// This operation is safe if a value does not exist in the set.
1207 ///
1208 /// However, if a value exists in the set already, the behavior is unspecified:
1209 /// this operation may panic, loop forever, or any following operation with the set
1210 /// may panic, loop forever or return arbitrary result.
1211 ///
1212 /// That said, this operation (and following operations) are guaranteed to
1213 /// not violate memory safety.
1214 ///
1215 /// This operation is faster than regular insert, because it does not perform
1216 /// lookup before insertion.
1217 ///
1218 /// This operation is useful during initial population of the set.
1219 /// For example, when constructing a set from another set, we know
1220 /// that values are unique.
1221 #[cfg_attr(feature = "inline-more", inline)]
1222 pub fn try_insert_unique_unchecked(&mut self, value: T) -> Result<&T, Error> {
1223 Ok(self.map.try_insert_unique_unchecked(value, ())?.0)
1224 }
1225
1226 /// Adds a value to the set, replacing the existing value, if any, that is equal to the given
1227 /// one. Returns the replaced value.
1228 ///
1229 /// # Examples
1230 ///
1231 /// ```
1232 /// use rune::alloc::HashSet;
1233 ///
1234 /// let mut set = HashSet::new();
1235 /// set.try_insert(Vec::<i32>::new())?;
1236 ///
1237 /// assert_eq!(set.get(&[][..]).unwrap().capacity(), 0);
1238 /// set.try_replace(Vec::with_capacity(10))?;
1239 /// assert_eq!(set.get(&[][..]).unwrap().capacity(), 10);
1240 /// # Ok::<_, rune::alloc::Error>(())
1241 /// ```
1242 #[cfg_attr(feature = "inline-more", inline)]
1243 pub fn try_replace(&mut self, value: T) -> Result<Option<T>, Error> {
1244 match self.map.entry(value) {
1245 map::Entry::Occupied(occupied) => Ok(Some(occupied.replace_key())),
1246 map::Entry::Vacant(vacant) => {
1247 vacant.try_insert(())?;
1248 Ok(None)
1249 }
1250 }
1251 }
1252
1253 #[cfg(test)]
1254 pub(crate) fn replace(&mut self, value: T) -> Option<T> {
1255 self.try_replace(value).abort()
1256 }
1257
1258 /// Removes a value from the set. Returns whether the value was
1259 /// present in the set.
1260 ///
1261 /// The value may be any borrowed form of the set's value type, but
1262 /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
1263 /// the value type.
1264 ///
1265 /// # Examples
1266 ///
1267 /// ```
1268 /// use rune::alloc::HashSet;
1269 ///
1270 /// let mut set = HashSet::new();
1271 ///
1272 /// set.try_insert(2)?;
1273 /// assert_eq!(set.remove(&2), true);
1274 /// assert_eq!(set.remove(&2), false);
1275 /// # Ok::<_, rune::alloc::Error>(())
1276 /// ```
1277 ///
1278 /// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html
1279 /// [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html
1280 #[cfg_attr(feature = "inline-more", inline)]
1281 pub fn remove<Q>(&mut self, value: &Q) -> bool
1282 where
1283 Q: ?Sized + Hash + Equivalent<T>,
1284 {
1285 self.map.remove(value).is_some()
1286 }
1287
1288 /// Removes and returns the value in the set, if any, that is equal to the given one.
1289 ///
1290 /// The value may be any borrowed form of the set's value type, but
1291 /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
1292 /// the value type.
1293 ///
1294 /// # Examples
1295 ///
1296 /// ```
1297 /// use rune::alloc::HashSet;
1298 ///
1299 /// let mut set: HashSet<_> = HashSet::try_from([1, 2, 3])?;
1300 /// assert_eq!(set.take(&2), Some(2));
1301 /// assert_eq!(set.take(&2), None);
1302 /// # Ok::<_, rune::alloc::Error>(())
1303 /// ```
1304 ///
1305 /// [`Eq`]: https://doc.rust-lang.org/std/cmp/trait.Eq.html
1306 /// [`Hash`]: https://doc.rust-lang.org/std/hash/trait.Hash.html
1307 #[cfg_attr(feature = "inline-more", inline)]
1308 pub fn take<Q>(&mut self, value: &Q) -> Option<T>
1309 where
1310 Q: ?Sized + Hash + Equivalent<T>,
1311 {
1312 // Avoid `Option::map` because it bloats LLVM IR.
1313 match self.map.remove_entry(value) {
1314 Some((k, _)) => Some(k),
1315 None => None,
1316 }
1317 }
1318}
1319
1320impl<T, S, A: Allocator> HashSet<T, S, A> {
1321 /// Returns a reference to the [`RawTable`] used underneath [`HashSet`].
1322 /// This function is only available if the `raw` feature of the crate is enabled.
1323 ///
1324 /// # Note
1325 ///
1326 /// Calling this function is safe, but using the raw hash table API may require
1327 /// unsafe functions or blocks.
1328 ///
1329 /// `RawTable` API gives the lowest level of control under the set that can be useful
1330 /// for extending the HashSet's API, but may lead to *[undefined behavior]*.
1331 ///
1332 /// [`RawTable`]: crate::hashbrown::raw::RawTable
1333 /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
1334 #[cfg_attr(feature = "inline-more", inline)]
1335 pub fn raw_table(&self) -> &RawTable<(T, ()), A> {
1336 self.map.raw_table()
1337 }
1338
1339 /// Returns a mutable reference to the [`RawTable`] used underneath
1340 /// [`HashSet`]. This function is only available if the `raw` feature of the
1341 /// crate is enabled.
1342 ///
1343 /// # Note
1344 ///
1345 /// Calling this function is safe, but using the raw hash table API may
1346 /// require unsafe functions or blocks.
1347 ///
1348 /// `RawTable` API gives the lowest level of control under the set that can
1349 /// be useful for extending the HashSet's API, but may lead to *[undefined
1350 /// behavior]*.
1351 ///
1352 /// [`RawTable`]: crate::hashbrown::raw::RawTable
1353 /// [undefined behavior]:
1354 /// https://doc.rust-lang.org/reference/behavior-considered-undefined.html
1355 #[cfg_attr(feature = "inline-more", inline)]
1356 pub fn raw_table_mut(&mut self) -> &mut RawTable<(T, ()), A> {
1357 self.map.raw_table_mut()
1358 }
1359}
1360
1361impl<T, S, A> PartialEq for HashSet<T, S, A>
1362where
1363 T: Eq + Hash,
1364 S: BuildHasher,
1365 A: Allocator,
1366{
1367 fn eq(&self, other: &Self) -> bool {
1368 if self.len() != other.len() {
1369 return false;
1370 }
1371
1372 self.iter().all(|key| other.contains(key))
1373 }
1374}
1375
1376impl<T, S, A> Eq for HashSet<T, S, A>
1377where
1378 T: Eq + Hash,
1379 S: BuildHasher,
1380 A: Allocator,
1381{
1382}
1383
1384impl<T, S, A> fmt::Debug for HashSet<T, S, A>
1385where
1386 T: fmt::Debug,
1387 A: Allocator,
1388{
1389 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1390 f.debug_set().entries(self.iter()).finish()
1391 }
1392}
1393
1394impl<T, S, A> From<HashMap<T, (), S, A>> for HashSet<T, S, A>
1395where
1396 A: Allocator,
1397{
1398 fn from(map: HashMap<T, (), S, A>) -> Self {
1399 Self { map }
1400 }
1401}
1402
1403impl<T, S, A: Allocator> TryFromIteratorIn<T, A> for HashSet<T, S, A>
1404where
1405 T: Eq + Hash,
1406 S: BuildHasher + Default,
1407{
1408 #[cfg_attr(feature = "inline-more", inline)]
1409 fn try_from_iter_in<I: IntoIterator<Item = T>>(iter: I, alloc: A) -> Result<Self, Error> {
1410 let mut set = Self::with_hasher_in(S::default(), alloc);
1411 set.try_extend(iter)?;
1412 Ok(set)
1413 }
1414}
1415
1416#[cfg(test)]
1417impl<T, S, A: Allocator + Default> FromIterator<T> for HashSet<T, S, A>
1418where
1419 T: Eq + Hash,
1420 S: BuildHasher + Default,
1421{
1422 #[inline]
1423 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
1424 Self::try_from_iter_in(iter, A::default()).abort()
1425 }
1426}
1427
1428// The default hasher is used to match the std implementation signature
1429impl<T, A: Allocator + Default, const N: usize> TryFrom<[T; N]>
1430 for HashSet<T, DefaultHashBuilder, A>
1431where
1432 T: Eq + Hash,
1433{
1434 type Error = Error;
1435
1436 /// # Examples
1437 ///
1438 /// ```
1439 /// use rune::alloc::HashSet;
1440 ///
1441 /// let set1: HashSet<_> = HashSet::try_from([1, 2, 3, 4])?;
1442 /// let set2: HashSet<_> = [1, 2, 3, 4].try_into()?;
1443 /// assert_eq!(set1, set2);
1444 /// # Ok::<_, rune::alloc::Error>(())
1445 /// ```
1446 fn try_from(arr: [T; N]) -> Result<Self, Self::Error> {
1447 Self::try_from_iter_in(arr, A::default())
1448 }
1449}
1450
1451impl<T, S, A> TryExtend<T> for HashSet<T, S, A>
1452where
1453 T: Eq + Hash,
1454 S: BuildHasher,
1455 A: Allocator,
1456{
1457 #[cfg_attr(feature = "inline-more", inline)]
1458 fn try_extend<I: IntoIterator<Item = T>>(&mut self, iter: I) -> Result<(), Error> {
1459 self.map.try_extend(iter.into_iter().map(|k| (k, ())))
1460 }
1461}
1462
1463#[cfg(test)]
1464impl<T, S, A> Extend<T> for HashSet<T, S, A>
1465where
1466 T: Eq + Hash,
1467 S: BuildHasher,
1468 A: Allocator,
1469{
1470 #[cfg_attr(feature = "inline-more", inline)]
1471 fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
1472 self.try_extend(iter).abort();
1473 }
1474}
1475
1476impl<'a, T, S, A> TryExtend<&'a T> for HashSet<T, S, A>
1477where
1478 T: 'a + Eq + Hash + Copy,
1479 S: BuildHasher,
1480 A: Allocator,
1481{
1482 #[cfg_attr(feature = "inline-more", inline)]
1483 fn try_extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) -> Result<(), Error> {
1484 self.try_extend(iter.into_iter().copied())
1485 }
1486}
1487
1488#[cfg(test)]
1489impl<'a, T, S, A> Extend<&'a T> for HashSet<T, S, A>
1490where
1491 T: 'a + Eq + Hash + Copy,
1492 S: BuildHasher,
1493 A: Allocator,
1494{
1495 #[cfg_attr(feature = "inline-more", inline)]
1496 fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {
1497 self.try_extend(iter).abort()
1498 }
1499}
1500
1501impl<T, S, A> Default for HashSet<T, S, A>
1502where
1503 S: Default,
1504 A: Default + Allocator,
1505{
1506 /// Creates an empty `HashSet<T, S>` with the `Default` value for the hasher.
1507 #[cfg_attr(feature = "inline-more", inline)]
1508 fn default() -> Self {
1509 Self {
1510 map: HashMap::default(),
1511 }
1512 }
1513}
1514
1515/// An iterator over the items of a `HashSet`.
1516///
1517/// This `struct` is created by the [`iter`] method on [`HashSet`].
1518/// See its documentation for more.
1519///
1520/// [`HashSet`]: struct.HashSet.html
1521/// [`iter`]: struct.HashSet.html#method.iter
1522pub struct Iter<'a, K> {
1523 iter: Keys<'a, K, ()>,
1524}
1525
1526/// An owning iterator over the items of a `HashSet`.
1527///
1528/// This `struct` is created by the [`into_iter`] method on [`HashSet`]
1529/// (provided by the `IntoIterator` trait). See its documentation for more.
1530///
1531/// [`HashSet`]: struct.HashSet.html
1532/// [`into_iter`]: struct.HashSet.html#method.into_iter
1533pub struct IntoIter<K, A: Allocator = Global> {
1534 iter: map::IntoIter<K, (), A>,
1535}
1536
1537/// A draining iterator over the items of a `HashSet`.
1538///
1539/// This `struct` is created by the [`drain`] method on [`HashSet`].
1540/// See its documentation for more.
1541///
1542/// [`HashSet`]: struct.HashSet.html
1543/// [`drain`]: struct.HashSet.html#method.drain
1544pub struct Drain<'a, K, A: Allocator = Global> {
1545 iter: map::Drain<'a, K, (), A>,
1546}
1547
1548/// A draining iterator over entries of a `HashSet` which don't satisfy the predicate `f`.
1549///
1550/// This `struct` is created by the [`extract_if`] method on [`HashSet`]. See its
1551/// documentation for more.
1552///
1553/// [`extract_if`]: struct.HashSet.html#method.extract_if
1554/// [`HashSet`]: struct.HashSet.html
1555#[must_use = "Iterators are lazy unless consumed"]
1556pub struct ExtractIf<'a, K, F, A: Allocator = Global>
1557where
1558 F: FnMut(&K) -> bool,
1559{
1560 f: F,
1561 inner: ExtractIfInner<'a, K, (), A>,
1562}
1563
1564/// A lazy iterator producing elements in the intersection of `HashSet`s.
1565///
1566/// This `struct` is created by the [`intersection`] method on [`HashSet`].
1567/// See its documentation for more.
1568///
1569/// [`HashSet`]: struct.HashSet.html
1570/// [`intersection`]: struct.HashSet.html#method.intersection
1571pub struct Intersection<'a, T, S, A: Allocator = Global> {
1572 // iterator of the first set
1573 iter: Iter<'a, T>,
1574 // the second set
1575 other: &'a HashSet<T, S, A>,
1576}
1577
1578/// A lazy iterator producing elements in the difference of `HashSet`s.
1579///
1580/// This `struct` is created by the [`difference`] method on [`HashSet`].
1581/// See its documentation for more.
1582///
1583/// [`HashSet`]: struct.HashSet.html
1584/// [`difference`]: struct.HashSet.html#method.difference
1585pub struct Difference<'a, T, S, A: Allocator = Global> {
1586 // iterator of the first set
1587 iter: Iter<'a, T>,
1588 // the second set
1589 other: &'a HashSet<T, S, A>,
1590}
1591
1592/// A lazy iterator producing elements in the symmetric difference of `HashSet`s.
1593///
1594/// This `struct` is created by the [`symmetric_difference`] method on
1595/// [`HashSet`]. See its documentation for more.
1596///
1597/// [`HashSet`]: struct.HashSet.html
1598/// [`symmetric_difference`]: struct.HashSet.html#method.symmetric_difference
1599pub struct SymmetricDifference<'a, T, S, A: Allocator = Global> {
1600 iter: Chain<Difference<'a, T, S, A>, Difference<'a, T, S, A>>,
1601}
1602
1603/// A lazy iterator producing elements in the union of `HashSet`s.
1604///
1605/// This `struct` is created by the [`union`] method on [`HashSet`].
1606/// See its documentation for more.
1607///
1608/// [`HashSet`]: struct.HashSet.html
1609/// [`union`]: struct.HashSet.html#method.union
1610pub struct Union<'a, T, S, A: Allocator = Global> {
1611 iter: Chain<Iter<'a, T>, Difference<'a, T, S, A>>,
1612}
1613
1614impl<'a, T, S, A: Allocator> IntoIterator for &'a HashSet<T, S, A> {
1615 type Item = &'a T;
1616 type IntoIter = Iter<'a, T>;
1617
1618 #[cfg_attr(feature = "inline-more", inline)]
1619 fn into_iter(self) -> Iter<'a, T> {
1620 self.iter()
1621 }
1622}
1623
1624impl<T, S, A: Allocator> IntoIterator for HashSet<T, S, A> {
1625 type Item = T;
1626 type IntoIter = IntoIter<T, A>;
1627
1628 /// Creates a consuming iterator, that is, one that moves each value out
1629 /// of the set in arbitrary order. The set cannot be used after calling
1630 /// this.
1631 ///
1632 /// # Examples
1633 ///
1634 /// ```
1635 /// use rune::alloc::prelude::*;
1636 /// use rune::alloc::HashSet;
1637 ///
1638 /// let mut set = HashSet::new();
1639 /// set.try_insert("a".try_to_string()?)?;
1640 /// set.try_insert("b".try_to_string()?)?;
1641 ///
1642 /// // Not possible to collect to a Vec<String> with a regular `.iter()`.
1643 /// let v: Vec<String> = set.into_iter().try_collect()?;
1644 ///
1645 /// // Will print in an arbitrary order.
1646 /// for x in &v {
1647 /// println!("{}", x);
1648 /// }
1649 /// # Ok::<_, rune::alloc::Error>(())
1650 /// ```
1651 #[cfg_attr(feature = "inline-more", inline)]
1652 fn into_iter(self) -> IntoIter<T, A> {
1653 IntoIter {
1654 iter: self.map.into_iter(),
1655 }
1656 }
1657}
1658
1659impl<K> Clone for Iter<'_, K> {
1660 #[cfg_attr(feature = "inline-more", inline)]
1661 fn clone(&self) -> Self {
1662 Iter {
1663 iter: self.iter.clone(),
1664 }
1665 }
1666}
1667impl<'a, K> Iterator for Iter<'a, K> {
1668 type Item = &'a K;
1669
1670 #[cfg_attr(feature = "inline-more", inline)]
1671 fn next(&mut self) -> Option<&'a K> {
1672 self.iter.next()
1673 }
1674 #[cfg_attr(feature = "inline-more", inline)]
1675 fn size_hint(&self) -> (usize, Option<usize>) {
1676 self.iter.size_hint()
1677 }
1678}
1679impl<K> ExactSizeIterator for Iter<'_, K> {
1680 #[cfg_attr(feature = "inline-more", inline)]
1681 fn len(&self) -> usize {
1682 self.iter.len()
1683 }
1684}
1685impl<K> FusedIterator for Iter<'_, K> {}
1686
1687impl<K: fmt::Debug> fmt::Debug for Iter<'_, K> {
1688 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1689 f.debug_list().entries(self.clone()).finish()
1690 }
1691}
1692
1693impl<K, A: Allocator> Iterator for IntoIter<K, A> {
1694 type Item = K;
1695
1696 #[cfg_attr(feature = "inline-more", inline)]
1697 fn next(&mut self) -> Option<K> {
1698 // Avoid `Option::map` because it bloats LLVM IR.
1699 match self.iter.next() {
1700 Some((k, _)) => Some(k),
1701 None => None,
1702 }
1703 }
1704 #[cfg_attr(feature = "inline-more", inline)]
1705 fn size_hint(&self) -> (usize, Option<usize>) {
1706 self.iter.size_hint()
1707 }
1708}
1709impl<K, A: Allocator> ExactSizeIterator for IntoIter<K, A> {
1710 #[cfg_attr(feature = "inline-more", inline)]
1711 fn len(&self) -> usize {
1712 self.iter.len()
1713 }
1714}
1715impl<K, A: Allocator> FusedIterator for IntoIter<K, A> {}
1716
1717impl<K: fmt::Debug, A: Allocator> fmt::Debug for IntoIter<K, A> {
1718 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1719 let entries_iter = self.iter.iter().map(|(k, _)| k);
1720 f.debug_list().entries(entries_iter).finish()
1721 }
1722}
1723
1724impl<K, A: Allocator> Iterator for Drain<'_, K, A> {
1725 type Item = K;
1726
1727 #[cfg_attr(feature = "inline-more", inline)]
1728 fn next(&mut self) -> Option<K> {
1729 // Avoid `Option::map` because it bloats LLVM IR.
1730 match self.iter.next() {
1731 Some((k, _)) => Some(k),
1732 None => None,
1733 }
1734 }
1735
1736 #[cfg_attr(feature = "inline-more", inline)]
1737 fn size_hint(&self) -> (usize, Option<usize>) {
1738 self.iter.size_hint()
1739 }
1740}
1741impl<K, A: Allocator> ExactSizeIterator for Drain<'_, K, A> {
1742 #[cfg_attr(feature = "inline-more", inline)]
1743 fn len(&self) -> usize {
1744 self.iter.len()
1745 }
1746}
1747impl<K, A: Allocator> FusedIterator for Drain<'_, K, A> {}
1748
1749impl<K: fmt::Debug, A: Allocator> fmt::Debug for Drain<'_, K, A> {
1750 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1751 let entries_iter = self.iter.iter().map(|(k, _)| k);
1752 f.debug_list().entries(entries_iter).finish()
1753 }
1754}
1755
1756impl<K, F, A: Allocator> Iterator for ExtractIf<'_, K, F, A>
1757where
1758 F: FnMut(&K) -> bool,
1759{
1760 type Item = K;
1761
1762 #[cfg_attr(feature = "inline-more", inline)]
1763 fn next(&mut self) -> Option<Self::Item> {
1764 let f = &mut self.f;
1765 let (k, _) = self.inner.next(&mut |k, _| f(k))?;
1766 Some(k)
1767 }
1768
1769 #[inline]
1770 fn size_hint(&self) -> (usize, Option<usize>) {
1771 (0, self.inner.iter.size_hint().1)
1772 }
1773}
1774
1775impl<K, F, A: Allocator> FusedIterator for ExtractIf<'_, K, F, A> where F: FnMut(&K) -> bool {}
1776
1777impl<T, S, A: Allocator> Clone for Intersection<'_, T, S, A> {
1778 #[cfg_attr(feature = "inline-more", inline)]
1779 fn clone(&self) -> Self {
1780 Intersection {
1781 iter: self.iter.clone(),
1782 ..*self
1783 }
1784 }
1785}
1786
1787impl<'a, T, S, A> Iterator for Intersection<'a, T, S, A>
1788where
1789 T: Eq + Hash,
1790 S: BuildHasher,
1791 A: Allocator,
1792{
1793 type Item = &'a T;
1794
1795 #[cfg_attr(feature = "inline-more", inline)]
1796 fn next(&mut self) -> Option<&'a T> {
1797 loop {
1798 let elt = self.iter.next()?;
1799 if self.other.contains(elt) {
1800 return Some(elt);
1801 }
1802 }
1803 }
1804
1805 #[cfg_attr(feature = "inline-more", inline)]
1806 fn size_hint(&self) -> (usize, Option<usize>) {
1807 let (_, upper) = self.iter.size_hint();
1808 (0, upper)
1809 }
1810}
1811
1812impl<T, S, A> fmt::Debug for Intersection<'_, T, S, A>
1813where
1814 T: fmt::Debug + Eq + Hash,
1815 S: BuildHasher,
1816 A: Allocator,
1817{
1818 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1819 f.debug_list().entries(self.clone()).finish()
1820 }
1821}
1822
1823impl<T, S, A> FusedIterator for Intersection<'_, T, S, A>
1824where
1825 T: Eq + Hash,
1826 S: BuildHasher,
1827 A: Allocator,
1828{
1829}
1830
1831impl<T, S, A: Allocator> Clone for Difference<'_, T, S, A> {
1832 #[cfg_attr(feature = "inline-more", inline)]
1833 fn clone(&self) -> Self {
1834 Difference {
1835 iter: self.iter.clone(),
1836 ..*self
1837 }
1838 }
1839}
1840
1841impl<'a, T, S, A> Iterator for Difference<'a, T, S, A>
1842where
1843 T: Eq + Hash,
1844 S: BuildHasher,
1845 A: Allocator,
1846{
1847 type Item = &'a T;
1848
1849 #[cfg_attr(feature = "inline-more", inline)]
1850 fn next(&mut self) -> Option<&'a T> {
1851 loop {
1852 let elt = self.iter.next()?;
1853 if !self.other.contains(elt) {
1854 return Some(elt);
1855 }
1856 }
1857 }
1858
1859 #[cfg_attr(feature = "inline-more", inline)]
1860 fn size_hint(&self) -> (usize, Option<usize>) {
1861 let (_, upper) = self.iter.size_hint();
1862 (0, upper)
1863 }
1864}
1865
1866impl<T, S, A> FusedIterator for Difference<'_, T, S, A>
1867where
1868 T: Eq + Hash,
1869 S: BuildHasher,
1870 A: Allocator,
1871{
1872}
1873
1874impl<T, S, A> fmt::Debug for Difference<'_, T, S, A>
1875where
1876 T: fmt::Debug + Eq + Hash,
1877 S: BuildHasher,
1878 A: Allocator,
1879{
1880 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1881 f.debug_list().entries(self.clone()).finish()
1882 }
1883}
1884
1885impl<T, S, A: Allocator> Clone for SymmetricDifference<'_, T, S, A> {
1886 #[cfg_attr(feature = "inline-more", inline)]
1887 fn clone(&self) -> Self {
1888 SymmetricDifference {
1889 iter: self.iter.clone(),
1890 }
1891 }
1892}
1893
1894impl<'a, T, S, A> Iterator for SymmetricDifference<'a, T, S, A>
1895where
1896 T: Eq + Hash,
1897 S: BuildHasher,
1898 A: Allocator,
1899{
1900 type Item = &'a T;
1901
1902 #[cfg_attr(feature = "inline-more", inline)]
1903 fn next(&mut self) -> Option<&'a T> {
1904 self.iter.next()
1905 }
1906 #[cfg_attr(feature = "inline-more", inline)]
1907 fn size_hint(&self) -> (usize, Option<usize>) {
1908 self.iter.size_hint()
1909 }
1910}
1911
1912impl<T, S, A> FusedIterator for SymmetricDifference<'_, T, S, A>
1913where
1914 T: Eq + Hash,
1915 S: BuildHasher,
1916 A: Allocator,
1917{
1918}
1919
1920impl<T, S, A> fmt::Debug for SymmetricDifference<'_, T, S, A>
1921where
1922 T: fmt::Debug + Eq + Hash,
1923 S: BuildHasher,
1924 A: Allocator,
1925{
1926 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1927 f.debug_list().entries(self.clone()).finish()
1928 }
1929}
1930
1931impl<T, S, A: Allocator> Clone for Union<'_, T, S, A> {
1932 #[cfg_attr(feature = "inline-more", inline)]
1933 fn clone(&self) -> Self {
1934 Union {
1935 iter: self.iter.clone(),
1936 }
1937 }
1938}
1939
1940impl<T, S, A> FusedIterator for Union<'_, T, S, A>
1941where
1942 T: Eq + Hash,
1943 S: BuildHasher,
1944 A: Allocator,
1945{
1946}
1947
1948impl<T, S, A> fmt::Debug for Union<'_, T, S, A>
1949where
1950 T: fmt::Debug + Eq + Hash,
1951 S: BuildHasher,
1952 A: Allocator,
1953{
1954 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1955 f.debug_list().entries(self.clone()).finish()
1956 }
1957}
1958
1959impl<'a, T, S, A> Iterator for Union<'a, T, S, A>
1960where
1961 T: Eq + Hash,
1962 S: BuildHasher,
1963 A: Allocator,
1964{
1965 type Item = &'a T;
1966
1967 #[cfg_attr(feature = "inline-more", inline)]
1968 fn next(&mut self) -> Option<&'a T> {
1969 self.iter.next()
1970 }
1971 #[cfg_attr(feature = "inline-more", inline)]
1972 fn size_hint(&self) -> (usize, Option<usize>) {
1973 self.iter.size_hint()
1974 }
1975}
1976
1977/// A view into a single entry in a set, which may either be vacant or occupied.
1978///
1979/// This `enum` is constructed from the [`entry`] method on [`HashSet`].
1980///
1981/// [`HashSet`]: struct.HashSet.html
1982/// [`entry`]: struct.HashSet.html#method.entry
1983///
1984/// # Examples
1985///
1986/// ```
1987/// use rune::alloc::{HashSet, Vec};
1988/// use rune::alloc::hash_set::{Entry, OccupiedEntry};
1989/// use rune::alloc::prelude::*;
1990///
1991/// let mut set = HashSet::new();
1992/// set.try_extend(["a", "b", "c"])?;
1993/// assert_eq!(set.len(), 3);
1994///
1995/// // Existing value (insert)
1996/// let entry: Entry<_, _> = set.entry("a");
1997/// let _raw_o: OccupiedEntry<_, _> = entry.try_insert()?;
1998/// assert_eq!(set.len(), 3);
1999/// // Nonexistent value (insert)
2000/// set.entry("d").try_insert()?;
2001///
2002/// // Existing value (or_try_insert)
2003/// set.entry("b").or_try_insert()?;
2004/// // Nonexistent value (or_try_insert)
2005/// set.entry("e").or_try_insert()?;
2006///
2007/// println!("Our HashSet: {:?}", set);
2008///
2009/// let mut vec: Vec<_> = set.iter().copied().try_collect()?;
2010/// // The `Iter` iterator produces items in arbitrary order, so the
2011/// // items must be sorted to test them against a sorted array.
2012/// vec.sort_unstable();
2013/// assert_eq!(vec, ["a", "b", "c", "d", "e"]);
2014/// # Ok::<_, rune::alloc::Error>(())
2015/// ```
2016pub enum Entry<'a, T, S, A = Global>
2017where
2018 A: Allocator,
2019{
2020 /// An occupied entry.
2021 ///
2022 /// # Examples
2023 ///
2024 /// ```
2025 /// use rune::alloc::hash_set::Entry;
2026 /// use rune::alloc::HashSet;
2027 ///
2028 /// let mut set: HashSet<_> = HashSet::try_from(["a", "b"])?;
2029 ///
2030 /// match set.entry("a") {
2031 /// Entry::Vacant(_) => unreachable!(),
2032 /// Entry::Occupied(_) => { }
2033 /// }
2034 /// # Ok::<_, rune::alloc::Error>(())
2035 /// ```
2036 Occupied(OccupiedEntry<'a, T, S, A>),
2037
2038 /// A vacant entry.
2039 ///
2040 /// # Examples
2041 ///
2042 /// ```
2043 /// use rune::alloc::hash_set::{Entry, HashSet};
2044 /// let mut set = HashSet::new();
2045 ///
2046 /// match set.entry("a") {
2047 /// Entry::Occupied(_) => unreachable!(),
2048 /// Entry::Vacant(_) => { }
2049 /// }
2050 /// # Ok::<_, rune::alloc::Error>(())
2051 /// ```
2052 Vacant(VacantEntry<'a, T, S, A>),
2053}
2054
2055impl<T: fmt::Debug, S, A: Allocator> fmt::Debug for Entry<'_, T, S, A> {
2056 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2057 match *self {
2058 Entry::Vacant(ref v) => f.debug_tuple("Entry").field(v).finish(),
2059 Entry::Occupied(ref o) => f.debug_tuple("Entry").field(o).finish(),
2060 }
2061 }
2062}
2063
2064/// A view into an occupied entry in a `HashSet`.
2065/// It is part of the [`Entry`] enum.
2066///
2067/// [`Entry`]: enum.Entry.html
2068///
2069/// # Examples
2070///
2071/// ```
2072/// use rune::alloc::hash_set::{Entry, HashSet, OccupiedEntry};
2073/// use rune::alloc::prelude::*;
2074///
2075/// let mut set = HashSet::new();
2076/// set.try_extend(["a", "b", "c"])?;
2077///
2078/// let _entry_o: OccupiedEntry<_, _> = set.entry("a").try_insert()?;
2079/// assert_eq!(set.len(), 3);
2080///
2081/// // Existing key
2082/// match set.entry("a") {
2083/// Entry::Vacant(_) => unreachable!(),
2084/// Entry::Occupied(view) => {
2085/// assert_eq!(view.get(), &"a");
2086/// }
2087/// }
2088///
2089/// assert_eq!(set.len(), 3);
2090///
2091/// // Existing key (take)
2092/// match set.entry("c") {
2093/// Entry::Vacant(_) => unreachable!(),
2094/// Entry::Occupied(view) => {
2095/// assert_eq!(view.remove(), "c");
2096/// }
2097/// }
2098/// assert_eq!(set.get(&"c"), None);
2099/// assert_eq!(set.len(), 2);
2100/// # Ok::<_, rune::alloc::Error>(())
2101/// ```
2102pub struct OccupiedEntry<'a, T, S, A: Allocator = Global> {
2103 inner: map::OccupiedEntry<'a, T, (), S, A>,
2104}
2105
2106impl<T: fmt::Debug, S, A: Allocator> fmt::Debug for OccupiedEntry<'_, T, S, A> {
2107 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2108 f.debug_struct("OccupiedEntry")
2109 .field("value", self.get())
2110 .finish()
2111 }
2112}
2113
2114/// A view into a vacant entry in a `HashSet`.
2115/// It is part of the [`Entry`] enum.
2116///
2117/// [`Entry`]: enum.Entry.html
2118///
2119/// # Examples
2120///
2121/// ```
2122/// use rune::alloc::hash_set::{Entry, HashSet, VacantEntry};
2123///
2124/// let mut set = HashSet::<&str>::new();
2125///
2126/// let entry_v: VacantEntry<_, _> = match set.entry("a") {
2127/// Entry::Vacant(view) => view,
2128/// Entry::Occupied(_) => unreachable!(),
2129/// };
2130/// entry_v.try_insert()?;
2131/// assert!(set.contains("a") && set.len() == 1);
2132///
2133/// // Nonexistent key (try_insert)
2134/// match set.entry("b") {
2135/// Entry::Vacant(view) => view.try_insert()?,
2136/// Entry::Occupied(_) => unreachable!(),
2137/// }
2138/// assert!(set.contains("b") && set.len() == 2);
2139/// # Ok::<_, rune::alloc::Error>(())
2140/// ```
2141pub struct VacantEntry<'a, T, S, A: Allocator = Global> {
2142 inner: map::VacantEntry<'a, T, (), S, A>,
2143}
2144
2145impl<T: fmt::Debug, S, A: Allocator> fmt::Debug for VacantEntry<'_, T, S, A> {
2146 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2147 f.debug_tuple("VacantEntry").field(self.get()).finish()
2148 }
2149}
2150
2151impl<'a, T, S, A: Allocator> Entry<'a, T, S, A> {
2152 /// Sets the value of the entry, and returns an OccupiedEntry.
2153 ///
2154 /// # Examples
2155 ///
2156 /// ```
2157 /// use rune::alloc::HashSet;
2158 ///
2159 /// let mut set: HashSet<&str> = HashSet::new();
2160 /// let entry = set.entry("horseyland").try_insert()?;
2161 ///
2162 /// assert_eq!(entry.get(), &"horseyland");
2163 /// # Ok::<_, rune::alloc::Error>(())
2164 /// ```
2165 #[cfg_attr(feature = "inline-more", inline)]
2166 pub fn try_insert(self) -> Result<OccupiedEntry<'a, T, S, A>, Error>
2167 where
2168 T: Hash,
2169 S: BuildHasher,
2170 {
2171 match self {
2172 Entry::Occupied(entry) => Ok(entry),
2173 Entry::Vacant(entry) => entry.try_insert_entry(),
2174 }
2175 }
2176
2177 /// Ensures a value is in the entry by inserting if it was vacant.
2178 ///
2179 /// # Examples
2180 ///
2181 /// ```
2182 /// use rune::alloc::HashSet;
2183 ///
2184 /// let mut set: HashSet<&str> = HashSet::new();
2185 ///
2186 /// // nonexistent key
2187 /// set.entry("poneyland").or_try_insert()?;
2188 /// assert!(set.contains("poneyland"));
2189 ///
2190 /// // existing key
2191 /// set.entry("poneyland").or_try_insert()?;
2192 /// assert!(set.contains("poneyland"));
2193 /// assert_eq!(set.len(), 1);
2194 /// # Ok::<_, rune::alloc::Error>(())
2195 /// ```
2196 #[cfg_attr(feature = "inline-more", inline)]
2197 pub fn or_try_insert(self) -> Result<(), Error>
2198 where
2199 T: Hash,
2200 S: BuildHasher,
2201 {
2202 if let Entry::Vacant(entry) = self {
2203 entry.try_insert()?;
2204 }
2205
2206 Ok(())
2207 }
2208
2209 /// Returns a reference to this entry's value.
2210 ///
2211 /// # Examples
2212 ///
2213 /// ```
2214 /// use rune::alloc::HashSet;
2215 ///
2216 /// let mut set: HashSet<&str> = HashSet::new();
2217 /// set.entry("poneyland").or_try_insert()?;
2218 /// // existing key
2219 /// assert_eq!(set.entry("poneyland").get(), &"poneyland");
2220 /// // nonexistent key
2221 /// assert_eq!(set.entry("horseland").get(), &"horseland");
2222 /// # Ok::<_, rune::alloc::Error>(())
2223 /// ```
2224 #[cfg_attr(feature = "inline-more", inline)]
2225 pub fn get(&self) -> &T {
2226 match *self {
2227 Entry::Occupied(ref entry) => entry.get(),
2228 Entry::Vacant(ref entry) => entry.get(),
2229 }
2230 }
2231}
2232
2233impl<T, S, A: Allocator> OccupiedEntry<'_, T, S, A> {
2234 /// Gets a reference to the value in the entry.
2235 ///
2236 /// # Examples
2237 ///
2238 /// ```
2239 /// use rune::alloc::hash_set::{Entry, HashSet};
2240 ///
2241 /// let mut set: HashSet<&str> = HashSet::new();
2242 /// set.entry("poneyland").or_try_insert()?;
2243 ///
2244 /// match set.entry("poneyland") {
2245 /// Entry::Vacant(_) => panic!(),
2246 /// Entry::Occupied(entry) => assert_eq!(entry.get(), &"poneyland"),
2247 /// }
2248 /// # Ok::<_, rune::alloc::Error>(())
2249 /// ```
2250 #[cfg_attr(feature = "inline-more", inline)]
2251 pub fn get(&self) -> &T {
2252 self.inner.key()
2253 }
2254
2255 /// Takes the value out of the entry, and returns it.
2256 /// Keeps the allocated memory for reuse.
2257 ///
2258 /// # Examples
2259 ///
2260 /// ```
2261 /// use rune::alloc::HashSet;
2262 /// use rune::alloc::hash_set::Entry;
2263 ///
2264 /// let mut set: HashSet<&str> = HashSet::new();
2265 /// // The set is empty
2266 /// assert!(set.is_empty() && set.capacity() == 0);
2267 ///
2268 /// set.entry("poneyland").or_try_insert()?;
2269 /// let capacity_before_remove = set.capacity();
2270 ///
2271 /// if let Entry::Occupied(o) = set.entry("poneyland") {
2272 /// assert_eq!(o.remove(), "poneyland");
2273 /// }
2274 ///
2275 /// assert_eq!(set.contains("poneyland"), false);
2276 /// // Now set hold none elements but capacity is equal to the old one
2277 /// assert!(set.len() == 0 && set.capacity() == capacity_before_remove);
2278 /// # Ok::<_, rune::alloc::Error>(())
2279 /// ```
2280 #[cfg_attr(feature = "inline-more", inline)]
2281 pub fn remove(self) -> T {
2282 self.inner.remove_entry().0
2283 }
2284
2285 /// Replaces the entry, returning the old value. The new value in the hash
2286 /// map will be the value used to create this entry.
2287 ///
2288 /// # Panics
2289 ///
2290 /// Will panic if this OccupiedEntry was created through
2291 /// [`Entry::try_insert`].
2292 ///
2293 /// # Examples
2294 ///
2295 /// ```
2296 /// use rune::alloc::hash_set::{Entry, HashSet};
2297 /// use std::rc::Rc;
2298 ///
2299 /// let mut set: HashSet<Rc<String>> = HashSet::new();
2300 /// let key_one = Rc::new("Stringthing".to_string());
2301 /// let key_two = Rc::new("Stringthing".to_string());
2302 ///
2303 /// set.try_insert(key_one.clone())?;
2304 /// assert!(Rc::strong_count(&key_one) == 2 && Rc::strong_count(&key_two) == 1);
2305 ///
2306 /// match set.entry(key_two.clone()) {
2307 /// Entry::Occupied(entry) => {
2308 /// let old_key: Rc<String> = entry.replace();
2309 /// assert!(Rc::ptr_eq(&key_one, &old_key));
2310 /// }
2311 /// Entry::Vacant(_) => panic!(),
2312 /// }
2313 ///
2314 /// assert!(Rc::strong_count(&key_one) == 1 && Rc::strong_count(&key_two) == 2);
2315 /// assert!(set.contains(&"Stringthing".to_owned()));
2316 /// # Ok::<_, rune::alloc::Error>(())
2317 /// ```
2318 #[cfg_attr(feature = "inline-more", inline)]
2319 pub fn replace(self) -> T {
2320 self.inner.replace_key()
2321 }
2322}
2323
2324impl<'a, T, S, A: Allocator> VacantEntry<'a, T, S, A> {
2325 /// Gets a reference to the value that would be used when inserting
2326 /// through the `VacantEntry`.
2327 ///
2328 /// # Examples
2329 ///
2330 /// ```
2331 /// use rune::alloc::HashSet;
2332 ///
2333 /// let mut set: HashSet<&str> = HashSet::new();
2334 /// assert_eq!(set.entry("poneyland").get(), &"poneyland");
2335 /// ```
2336 #[cfg_attr(feature = "inline-more", inline)]
2337 pub fn get(&self) -> &T {
2338 self.inner.key()
2339 }
2340
2341 /// Take ownership of the value.
2342 ///
2343 /// # Examples
2344 ///
2345 /// ```
2346 /// use rune::alloc::hash_set::{Entry, HashSet};
2347 ///
2348 /// let mut set = HashSet::new();
2349 ///
2350 /// match set.entry("poneyland") {
2351 /// Entry::Occupied(_) => panic!(),
2352 /// Entry::Vacant(v) => assert_eq!(v.into_value(), "poneyland"),
2353 /// }
2354 /// ```
2355 #[cfg_attr(feature = "inline-more", inline)]
2356 pub fn into_value(self) -> T {
2357 self.inner.into_key()
2358 }
2359
2360 /// Sets the value of the entry with the VacantEntry's value.
2361 ///
2362 /// # Examples
2363 ///
2364 /// ```
2365 /// use rune::alloc::HashSet;
2366 /// use rune::alloc::hash_set::Entry;
2367 ///
2368 /// let mut set: HashSet<&str> = HashSet::new();
2369 ///
2370 /// if let Entry::Vacant(o) = set.entry("poneyland") {
2371 /// o.try_insert()?;
2372 /// }
2373 /// assert!(set.contains("poneyland"));
2374 /// # Ok::<_, rune::alloc::Error>(())
2375 /// ```
2376 #[cfg_attr(feature = "inline-more", inline)]
2377 pub fn try_insert(self) -> Result<(), Error>
2378 where
2379 T: Hash,
2380 S: BuildHasher,
2381 {
2382 self.inner.try_insert(())?;
2383 Ok(())
2384 }
2385
2386 #[cfg_attr(feature = "inline-more", inline)]
2387 fn try_insert_entry(self) -> Result<OccupiedEntry<'a, T, S, A>, Error>
2388 where
2389 T: Hash,
2390 S: BuildHasher,
2391 {
2392 Ok(OccupiedEntry {
2393 inner: self.inner.try_insert_entry(())?,
2394 })
2395 }
2396}
2397
2398#[allow(dead_code)]
2399fn assert_covariance() {
2400 fn set<'new>(v: HashSet<&'static str>) -> HashSet<&'new str> {
2401 v
2402 }
2403 fn iter<'a, 'new>(v: Iter<'a, &'static str>) -> Iter<'a, &'new str> {
2404 v
2405 }
2406 fn into_iter<'new, A: Allocator>(v: IntoIter<&'static str, A>) -> IntoIter<&'new str, A> {
2407 v
2408 }
2409 fn difference<'a, 'new, A: Allocator>(
2410 v: Difference<'a, &'static str, DefaultHashBuilder, A>,
2411 ) -> Difference<'a, &'new str, DefaultHashBuilder, A> {
2412 v
2413 }
2414 fn symmetric_difference<'a, 'new, A: Allocator>(
2415 v: SymmetricDifference<'a, &'static str, DefaultHashBuilder, A>,
2416 ) -> SymmetricDifference<'a, &'new str, DefaultHashBuilder, A> {
2417 v
2418 }
2419 fn intersection<'a, 'new, A: Allocator>(
2420 v: Intersection<'a, &'static str, DefaultHashBuilder, A>,
2421 ) -> Intersection<'a, &'new str, DefaultHashBuilder, A> {
2422 v
2423 }
2424 fn union<'a, 'new, A: Allocator>(
2425 v: Union<'a, &'static str, DefaultHashBuilder, A>,
2426 ) -> Union<'a, &'new str, DefaultHashBuilder, A> {
2427 v
2428 }
2429 fn drain<'new, A: Allocator>(d: Drain<'static, &'static str, A>) -> Drain<'new, &'new str, A> {
2430 d
2431 }
2432}
2433
2434#[cfg(test)]
2435mod test_set {
2436 use super::super::map::DefaultHashBuilder;
2437 use super::HashSet;
2438 use rust_alloc::vec::Vec;
2439 use rust_alloc::{format, vec};
2440
2441 #[test]
2442 fn test_zero_capacities() {
2443 type HS = HashSet<i32>;
2444
2445 let s = HS::new();
2446 assert_eq!(s.capacity(), 0);
2447
2448 let s = HS::default();
2449 assert_eq!(s.capacity(), 0);
2450
2451 let s = HS::with_hasher(DefaultHashBuilder::default());
2452 assert_eq!(s.capacity(), 0);
2453
2454 let s = HS::with_capacity(0);
2455 assert_eq!(s.capacity(), 0);
2456
2457 let s = HS::with_capacity_and_hasher(0, DefaultHashBuilder::default());
2458 assert_eq!(s.capacity(), 0);
2459
2460 let mut s = HS::new();
2461 s.insert(1);
2462 s.insert(2);
2463 s.remove(&1);
2464 s.remove(&2);
2465 s.shrink_to_fit();
2466 assert_eq!(s.capacity(), 0);
2467
2468 let mut s = HS::new();
2469 s.reserve(0);
2470 assert_eq!(s.capacity(), 0);
2471 }
2472
2473 #[test]
2474 fn test_disjoint() {
2475 let mut xs = HashSet::new();
2476 let mut ys = HashSet::new();
2477 assert!(xs.is_disjoint(&ys));
2478 assert!(ys.is_disjoint(&xs));
2479 assert!(xs.insert(5));
2480 assert!(ys.insert(11));
2481 assert!(xs.is_disjoint(&ys));
2482 assert!(ys.is_disjoint(&xs));
2483 assert!(xs.insert(7));
2484 assert!(xs.insert(19));
2485 assert!(xs.insert(4));
2486 assert!(ys.insert(2));
2487 assert!(ys.insert(-11));
2488 assert!(xs.is_disjoint(&ys));
2489 assert!(ys.is_disjoint(&xs));
2490 assert!(ys.insert(7));
2491 assert!(!xs.is_disjoint(&ys));
2492 assert!(!ys.is_disjoint(&xs));
2493 }
2494
2495 #[test]
2496 fn test_subset_and_superset() {
2497 let mut a = HashSet::new();
2498 assert!(a.insert(0));
2499 assert!(a.insert(5));
2500 assert!(a.insert(11));
2501 assert!(a.insert(7));
2502
2503 let mut b = HashSet::new();
2504 assert!(b.insert(0));
2505 assert!(b.insert(7));
2506 assert!(b.insert(19));
2507 assert!(b.insert(250));
2508 assert!(b.insert(11));
2509 assert!(b.insert(200));
2510
2511 assert!(!a.is_subset(&b));
2512 assert!(!a.is_superset(&b));
2513 assert!(!b.is_subset(&a));
2514 assert!(!b.is_superset(&a));
2515
2516 assert!(b.insert(5));
2517
2518 assert!(a.is_subset(&b));
2519 assert!(!a.is_superset(&b));
2520 assert!(!b.is_subset(&a));
2521 assert!(b.is_superset(&a));
2522 }
2523
2524 #[test]
2525 fn test_iterate() {
2526 let mut a = HashSet::new();
2527 for i in 0..32 {
2528 assert!(a.insert(i));
2529 }
2530 let mut observed: u32 = 0;
2531 for k in &a {
2532 observed |= 1 << *k;
2533 }
2534 assert_eq!(observed, 0xFFFF_FFFF);
2535 }
2536
2537 #[test]
2538 fn test_intersection() {
2539 let mut a = HashSet::new();
2540 let mut b = HashSet::new();
2541
2542 assert!(a.insert(11));
2543 assert!(a.insert(1));
2544 assert!(a.insert(3));
2545 assert!(a.insert(77));
2546 assert!(a.insert(103));
2547 assert!(a.insert(5));
2548 assert!(a.insert(-5));
2549
2550 assert!(b.insert(2));
2551 assert!(b.insert(11));
2552 assert!(b.insert(77));
2553 assert!(b.insert(-9));
2554 assert!(b.insert(-42));
2555 assert!(b.insert(5));
2556 assert!(b.insert(3));
2557
2558 let mut i = 0;
2559 let expected = [3, 5, 11, 77];
2560 for x in a.intersection(&b) {
2561 assert!(expected.contains(x));
2562 i += 1;
2563 }
2564 assert_eq!(i, expected.len());
2565 }
2566
2567 #[test]
2568 fn test_difference() {
2569 let mut a = HashSet::new();
2570 let mut b = HashSet::new();
2571
2572 assert!(a.insert(1));
2573 assert!(a.insert(3));
2574 assert!(a.insert(5));
2575 assert!(a.insert(9));
2576 assert!(a.insert(11));
2577
2578 assert!(b.insert(3));
2579 assert!(b.insert(9));
2580
2581 let mut i = 0;
2582 let expected = [1, 5, 11];
2583 for x in a.difference(&b) {
2584 assert!(expected.contains(x));
2585 i += 1;
2586 }
2587 assert_eq!(i, expected.len());
2588 }
2589
2590 #[test]
2591 fn test_symmetric_difference() {
2592 let mut a = HashSet::new();
2593 let mut b = HashSet::new();
2594
2595 assert!(a.insert(1));
2596 assert!(a.insert(3));
2597 assert!(a.insert(5));
2598 assert!(a.insert(9));
2599 assert!(a.insert(11));
2600
2601 assert!(b.insert(-2));
2602 assert!(b.insert(3));
2603 assert!(b.insert(9));
2604 assert!(b.insert(14));
2605 assert!(b.insert(22));
2606
2607 let mut i = 0;
2608 let expected = [-2, 1, 5, 11, 14, 22];
2609 for x in a.symmetric_difference(&b) {
2610 assert!(expected.contains(x));
2611 i += 1;
2612 }
2613 assert_eq!(i, expected.len());
2614 }
2615
2616 #[test]
2617 fn test_union() {
2618 let mut a = HashSet::new();
2619 let mut b = HashSet::new();
2620
2621 assert!(a.insert(1));
2622 assert!(a.insert(3));
2623 assert!(a.insert(5));
2624 assert!(a.insert(9));
2625 assert!(a.insert(11));
2626 assert!(a.insert(16));
2627 assert!(a.insert(19));
2628 assert!(a.insert(24));
2629
2630 assert!(b.insert(-2));
2631 assert!(b.insert(1));
2632 assert!(b.insert(5));
2633 assert!(b.insert(9));
2634 assert!(b.insert(13));
2635 assert!(b.insert(19));
2636
2637 let mut i = 0;
2638 let expected = [-2, 1, 3, 5, 9, 11, 13, 16, 19, 24];
2639 for x in a.union(&b) {
2640 assert!(expected.contains(x));
2641 i += 1;
2642 }
2643 assert_eq!(i, expected.len());
2644 }
2645
2646 #[test]
2647 fn test_from_map() {
2648 let mut a = crate::HashMap::new();
2649 a.insert(1, ());
2650 a.insert(2, ());
2651 a.insert(3, ());
2652 a.insert(4, ());
2653
2654 let a: HashSet<_> = a.into();
2655
2656 assert_eq!(a.len(), 4);
2657 assert!(a.contains(&1));
2658 assert!(a.contains(&2));
2659 assert!(a.contains(&3));
2660 assert!(a.contains(&4));
2661 }
2662
2663 #[test]
2664 fn test_from_iter() {
2665 let xs = [1, 2, 2, 3, 4, 5, 6, 7, 8, 9];
2666
2667 let set: HashSet<_> = xs.iter().copied().collect();
2668
2669 for x in &xs {
2670 assert!(set.contains(x));
2671 }
2672
2673 assert_eq!(set.iter().len(), xs.len() - 1);
2674 }
2675
2676 #[test]
2677 fn test_move_iter() {
2678 let hs = {
2679 let mut hs = HashSet::new();
2680
2681 hs.insert('a');
2682 hs.insert('b');
2683
2684 hs
2685 };
2686
2687 let v = hs.into_iter().collect::<Vec<char>>();
2688 assert!(v == ['a', 'b'] || v == ['b', 'a']);
2689 }
2690
2691 #[test]
2692 fn test_eq() {
2693 // These constants once happened to expose a bug in insert().
2694 // I'm keeping them around to prevent a regression.
2695 let mut s1 = HashSet::new();
2696
2697 s1.insert(1);
2698 s1.insert(2);
2699 s1.insert(3);
2700
2701 let mut s2 = HashSet::new();
2702
2703 s2.insert(1);
2704 s2.insert(2);
2705
2706 assert!(s1 != s2);
2707
2708 s2.insert(3);
2709
2710 assert_eq!(s1, s2);
2711 }
2712
2713 #[test]
2714 fn test_show() {
2715 let mut set = HashSet::new();
2716 let empty = HashSet::<i32>::new();
2717
2718 set.insert(1);
2719 set.insert(2);
2720
2721 let set_str = format!("{set:?}");
2722
2723 assert!(set_str == "{1, 2}" || set_str == "{2, 1}");
2724 assert_eq!(format!("{empty:?}"), "{}");
2725 }
2726
2727 #[test]
2728 fn test_trivial_drain() {
2729 let mut s = HashSet::<i32>::new();
2730 for _ in s.drain() {}
2731 assert!(s.is_empty());
2732 drop(s);
2733
2734 let mut s = HashSet::<i32>::new();
2735 drop(s.drain());
2736 assert!(s.is_empty());
2737 }
2738
2739 #[test]
2740 fn test_drain() {
2741 let mut s: HashSet<_> = (1..100).collect();
2742
2743 // try this a bunch of times to make sure we don't screw up internal state.
2744 for _ in 0..20 {
2745 assert_eq!(s.len(), 99);
2746
2747 {
2748 let mut last_i = 0;
2749 let mut d = s.drain();
2750 for (i, x) in d.by_ref().take(50).enumerate() {
2751 last_i = i;
2752 assert!(x != 0);
2753 }
2754 assert_eq!(last_i, 49);
2755 }
2756
2757 assert!(s.is_empty(), "s should be empty!");
2758 // reset to try again.
2759 s.extend(1..100);
2760 }
2761 }
2762
2763 #[test]
2764 fn test_replace() {
2765 use core::hash;
2766
2767 #[derive(Debug)]
2768 struct Foo(&'static str, #[allow(unused)] i32);
2769
2770 impl PartialEq for Foo {
2771 fn eq(&self, other: &Self) -> bool {
2772 self.0 == other.0
2773 }
2774 }
2775
2776 impl Eq for Foo {}
2777
2778 impl hash::Hash for Foo {
2779 fn hash<H: hash::Hasher>(&self, h: &mut H) {
2780 self.0.hash(h);
2781 }
2782 }
2783
2784 let mut s = HashSet::new();
2785 assert_eq!(s.replace(Foo("a", 1)), None);
2786 assert_eq!(s.len(), 1);
2787 assert_eq!(s.replace(Foo("a", 2)), Some(Foo("a", 1)));
2788 assert_eq!(s.len(), 1);
2789
2790 let mut it = s.iter();
2791 assert_eq!(it.next(), Some(&Foo("a", 2)));
2792 assert_eq!(it.next(), None);
2793 }
2794
2795 #[test]
2796 #[allow(clippy::needless_borrow)]
2797 fn test_extend_ref() {
2798 let mut a = HashSet::new();
2799 a.insert(1);
2800
2801 a.extend([2, 3, 4]);
2802
2803 assert_eq!(a.len(), 4);
2804 assert!(a.contains(&1));
2805 assert!(a.contains(&2));
2806 assert!(a.contains(&3));
2807 assert!(a.contains(&4));
2808
2809 let mut b = HashSet::new();
2810 b.insert(5);
2811 b.insert(6);
2812
2813 a.extend(&b);
2814
2815 assert_eq!(a.len(), 6);
2816 assert!(a.contains(&1));
2817 assert!(a.contains(&2));
2818 assert!(a.contains(&3));
2819 assert!(a.contains(&4));
2820 assert!(a.contains(&5));
2821 assert!(a.contains(&6));
2822 }
2823
2824 #[test]
2825 fn test_retain() {
2826 let xs = [1, 2, 3, 4, 5, 6];
2827 let mut set: HashSet<i32> = xs.iter().copied().collect();
2828 set.retain(|&k| k % 2 == 0);
2829 assert_eq!(set.len(), 3);
2830 assert!(set.contains(&2));
2831 assert!(set.contains(&4));
2832 assert!(set.contains(&6));
2833 }
2834
2835 #[test]
2836 fn test_extract_if() {
2837 {
2838 let mut set: HashSet<i32> = (0..8).collect();
2839 let drained = set.extract_if(|&k| k % 2 == 0);
2840 let mut out = drained.collect::<Vec<_>>();
2841 out.sort_unstable();
2842 assert_eq!(vec![0, 2, 4, 6], out);
2843 assert_eq!(set.len(), 4);
2844 }
2845 {
2846 let mut set: HashSet<i32> = (0..8).collect();
2847 set.extract_if(|&k| k % 2 == 0).for_each(drop);
2848 assert_eq!(set.len(), 4, "Removes non-matching items on drop");
2849 }
2850 }
2851
2852 #[test]
2853 fn test_const_with_hasher() {
2854 use core::hash::BuildHasher;
2855 use std::collections::hash_map::DefaultHasher;
2856
2857 #[derive(Clone)]
2858 struct MyHasher;
2859 impl BuildHasher for MyHasher {
2860 type Hasher = DefaultHasher;
2861
2862 fn build_hasher(&self) -> DefaultHasher {
2863 DefaultHasher::new()
2864 }
2865 }
2866
2867 const EMPTY_SET: HashSet<u32, MyHasher> = HashSet::with_hasher(MyHasher);
2868
2869 let mut set = EMPTY_SET;
2870 set.insert(19);
2871 assert!(set.contains(&19));
2872 }
2873
2874 #[test]
2875 fn rehash_in_place() {
2876 let mut set = HashSet::new();
2877
2878 for i in 0..224 {
2879 set.insert(i);
2880 }
2881
2882 assert_eq!(
2883 set.capacity(),
2884 224,
2885 "The set must be at or close to capacity to trigger a re hashing"
2886 );
2887
2888 for i in 100..1400 {
2889 set.remove(&(i - 100));
2890 set.insert(i);
2891 }
2892 }
2893
2894 #[test]
2895 fn collect() {
2896 // At the time of writing, this hits the ZST case in from_base_index
2897 // (and without the `map`, it does not).
2898 let mut _set: HashSet<_> = (0..3).map(|_| ()).collect();
2899 }
2900}