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