summaryrefslogtreecommitdiffstats
path: root/vendor/im-rc/src/hash/set.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/im-rc/src/hash/set.rs')
-rw-r--r--vendor/im-rc/src/hash/set.rs1134
1 files changed, 1134 insertions, 0 deletions
diff --git a/vendor/im-rc/src/hash/set.rs b/vendor/im-rc/src/hash/set.rs
new file mode 100644
index 000000000..edc4ad60c
--- /dev/null
+++ b/vendor/im-rc/src/hash/set.rs
@@ -0,0 +1,1134 @@
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+//! An unordered set.
+//!
+//! An immutable hash set using [hash array mapped tries] [1].
+//!
+//! Most operations on this set are O(log<sub>x</sub> n) for a
+//! suitably high *x* that it should be nearly O(1) for most sets.
+//! Because of this, it's a great choice for a generic set as long as
+//! you don't mind that values will need to implement
+//! [`Hash`][std::hash::Hash] and [`Eq`][std::cmp::Eq].
+//!
+//! Values will have a predictable order based on the hasher
+//! being used. Unless otherwise specified, this will be the standard
+//! [`RandomState`][std::collections::hash_map::RandomState] hasher.
+//!
+//! [1]: https://en.wikipedia.org/wiki/Hash_array_mapped_trie
+//! [std::cmp::Eq]: https://doc.rust-lang.org/std/cmp/trait.Eq.html
+//! [std::hash::Hash]: https://doc.rust-lang.org/std/hash/trait.Hash.html
+//! [std::collections::hash_map::RandomState]: https://doc.rust-lang.org/std/collections/hash_map/struct.RandomState.html
+
+use std::borrow::Borrow;
+use std::cmp::Ordering;
+use std::collections::hash_map::RandomState;
+use std::collections::{self, BTreeSet};
+use std::fmt::{Debug, Error, Formatter};
+use std::hash::{BuildHasher, Hash, Hasher};
+use std::iter::FusedIterator;
+use std::iter::{FromIterator, IntoIterator, Sum};
+use std::ops::{Add, Deref, Mul};
+
+use crate::nodes::hamt::{hash_key, Drain as NodeDrain, HashValue, Iter as NodeIter, Node};
+use crate::ordset::OrdSet;
+use crate::util::{Pool, PoolRef, Ref};
+use crate::Vector;
+
+/// Construct a set from a sequence of values.
+///
+/// # Examples
+///
+/// ```
+/// # #[macro_use] extern crate im_rc as im;
+/// # use im::hashset::HashSet;
+/// # fn main() {
+/// assert_eq!(
+/// hashset![1, 2, 3],
+/// HashSet::from(vec![1, 2, 3])
+/// );
+/// # }
+/// ```
+#[macro_export]
+macro_rules! hashset {
+ () => { $crate::hashset::HashSet::new() };
+
+ ( $($x:expr),* ) => {{
+ let mut l = $crate::hashset::HashSet::new();
+ $(
+ l.insert($x);
+ )*
+ l
+ }};
+
+ ( $($x:expr ,)* ) => {{
+ let mut l = $crate::hashset::HashSet::new();
+ $(
+ l.insert($x);
+ )*
+ l
+ }};
+}
+
+def_pool!(HashSetPool<A>, Node<Value<A>>);
+
+/// An unordered set.
+///
+/// An immutable hash set using [hash array mapped tries] [1].
+///
+/// Most operations on this set are O(log<sub>x</sub> n) for a
+/// suitably high *x* that it should be nearly O(1) for most sets.
+/// Because of this, it's a great choice for a generic set as long as
+/// you don't mind that values will need to implement
+/// [`Hash`][std::hash::Hash] and [`Eq`][std::cmp::Eq].
+///
+/// Values will have a predictable order based on the hasher
+/// being used. Unless otherwise specified, this will be the standard
+/// [`RandomState`][std::collections::hash_map::RandomState] hasher.
+///
+/// [1]: https://en.wikipedia.org/wiki/Hash_array_mapped_trie
+/// [std::cmp::Eq]: https://doc.rust-lang.org/std/cmp/trait.Eq.html
+/// [std::hash::Hash]: https://doc.rust-lang.org/std/hash/trait.Hash.html
+/// [std::collections::hash_map::RandomState]: https://doc.rust-lang.org/std/collections/hash_map/struct.RandomState.html
+pub struct HashSet<A, S = RandomState> {
+ hasher: Ref<S>,
+ pool: HashSetPool<A>,
+ root: PoolRef<Node<Value<A>>>,
+ size: usize,
+}
+
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
+struct Value<A>(A);
+
+impl<A> Deref for Value<A> {
+ type Target = A;
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+
+// FIXME lacking specialisation, we can't simply implement `HashValue`
+// for `A`, we have to use the `Value<A>` indirection.
+impl<A> HashValue for Value<A>
+where
+ A: Hash + Eq,
+{
+ type Key = A;
+
+ fn extract_key(&self) -> &Self::Key {
+ &self.0
+ }
+
+ fn ptr_eq(&self, _other: &Self) -> bool {
+ false
+ }
+}
+
+impl<A> HashSet<A, RandomState> {
+ /// Construct an empty set.
+ #[must_use]
+ pub fn new() -> Self {
+ Self::default()
+ }
+
+ /// Construct an empty set using a specific memory pool.
+ #[cfg(feature = "pool")]
+ #[must_use]
+ pub fn with_pool(pool: &HashSetPool<A>) -> Self {
+ Self {
+ pool: pool.clone(),
+ hasher: Default::default(),
+ size: 0,
+ root: PoolRef::default(&pool.0),
+ }
+ }
+}
+
+impl<A> HashSet<A, RandomState>
+where
+ A: Hash + Eq + Clone,
+{
+ /// Construct a set with a single value.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # #[macro_use] extern crate im_rc as im;
+ /// # use im::hashset::HashSet;
+ /// # use std::sync::Arc;
+ /// let set = HashSet::unit(123);
+ /// assert!(set.contains(&123));
+ /// ```
+ #[inline]
+ #[must_use]
+ pub fn unit(a: A) -> Self {
+ HashSet::new().update(a)
+ }
+}
+
+impl<A, S> HashSet<A, S> {
+ /// Test whether a set is empty.
+ ///
+ /// Time: O(1)
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # #[macro_use] extern crate im_rc as im;
+ /// # use im::hashset::HashSet;
+ /// assert!(
+ /// !hashset![1, 2, 3].is_empty()
+ /// );
+ /// assert!(
+ /// HashSet::<i32>::new().is_empty()
+ /// );
+ /// ```
+ #[inline]
+ #[must_use]
+ pub fn is_empty(&self) -> bool {
+ self.len() == 0
+ }
+
+ /// Get the size of a set.
+ ///
+ /// Time: O(1)
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # #[macro_use] extern crate im_rc as im;
+ /// # use im::hashset::HashSet;
+ /// assert_eq!(3, hashset![1, 2, 3].len());
+ /// ```
+ #[inline]
+ #[must_use]
+ pub fn len(&self) -> usize {
+ self.size
+ }
+
+ /// Test whether two sets refer to the same content in memory.
+ ///
+ /// This is true if the two sides are references to the same set,
+ /// or if the two sets refer to the same root node.
+ ///
+ /// This would return true if you're comparing a set to itself, or
+ /// if you're comparing a set to a fresh clone of itself.
+ ///
+ /// Time: O(1)
+ pub fn ptr_eq(&self, other: &Self) -> bool {
+ std::ptr::eq(self, other) || PoolRef::ptr_eq(&self.root, &other.root)
+ }
+
+ /// Get a reference to the memory pool used by this set.
+ ///
+ /// Note that if you didn't specifically construct it with a pool, you'll
+ /// get back a reference to a pool of size 0.
+ #[cfg(feature = "pool")]
+ pub fn pool(&self) -> &HashSetPool<A> {
+ &self.pool
+ }
+
+ /// Construct an empty hash set using the provided hasher.
+ #[inline]
+ #[must_use]
+ pub fn with_hasher<RS>(hasher: RS) -> Self
+ where
+ Ref<S>: From<RS>,
+ {
+ let pool = HashSetPool::default();
+ let root = PoolRef::default(&pool.0);
+ HashSet {
+ size: 0,
+ pool,
+ root,
+ hasher: From::from(hasher),
+ }
+ }
+
+ /// Construct an empty hash set using the provided memory pool and hasher.
+ #[cfg(feature = "pool")]
+ #[inline]
+ #[must_use]
+ pub fn with_pool_hasher<RS>(pool: &HashSetPool<A>, hasher: RS) -> Self
+ where
+ Ref<S>: From<RS>,
+ {
+ let root = PoolRef::default(&pool.0);
+ HashSet {
+ size: 0,
+ pool: pool.clone(),
+ root,
+ hasher: From::from(hasher),
+ }
+ }
+
+ /// Get a reference to the set's [`BuildHasher`][BuildHasher].
+ ///
+ /// [BuildHasher]: https://doc.rust-lang.org/std/hash/trait.BuildHasher.html
+ #[must_use]
+ pub fn hasher(&self) -> &Ref<S> {
+ &self.hasher
+ }
+
+ /// Construct an empty hash set using the same hasher as the current hash set.
+ #[inline]
+ #[must_use]
+ pub fn new_from<A1>(&self) -> HashSet<A1, S>
+ where
+ A1: Hash + Eq + Clone,
+ {
+ let pool = HashSetPool::default();
+ let root = PoolRef::default(&pool.0);
+ HashSet {
+ size: 0,
+ pool,
+ root,
+ hasher: self.hasher.clone(),
+ }
+ }
+
+ /// Discard all elements from the set.
+ ///
+ /// This leaves you with an empty set, and all elements that
+ /// were previously inside it are dropped.
+ ///
+ /// Time: O(n)
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # #[macro_use] extern crate im_rc as im;
+ /// # use im::HashSet;
+ /// let mut set = hashset![1, 2, 3];
+ /// set.clear();
+ /// assert!(set.is_empty());
+ /// ```
+ pub fn clear(&mut self) {
+ if !self.is_empty() {
+ self.root = PoolRef::default(&self.pool.0);
+ self.size = 0;
+ }
+ }
+
+ /// Get an iterator over the values in a hash set.
+ ///
+ /// Please note that the order is consistent between sets using
+ /// the same hasher, but no other ordering guarantee is offered.
+ /// Items will not come out in insertion order or sort order.
+ /// They will, however, come out in the same order every time for
+ /// the same set.
+ #[must_use]
+ pub fn iter(&self) -> Iter<'_, A> {
+ Iter {
+ it: NodeIter::new(&self.root, self.size),
+ }
+ }
+}
+
+impl<A, S> HashSet<A, S>
+where
+ A: Hash + Eq,
+ S: BuildHasher,
+{
+ fn test_eq(&self, other: &Self) -> bool {
+ if self.len() != other.len() {
+ return false;
+ }
+ let mut seen = collections::HashSet::new();
+ for value in self.iter() {
+ if !other.contains(value) {
+ return false;
+ }
+ seen.insert(value);
+ }
+ for value in other.iter() {
+ if !seen.contains(&value) {
+ return false;
+ }
+ }
+ true
+ }
+
+ /// Test if a value is part of a set.
+ ///
+ /// Time: O(log n)
+ #[must_use]
+ pub fn contains<BA>(&self, a: &BA) -> bool
+ where
+ BA: Hash + Eq + ?Sized,
+ A: Borrow<BA>,
+ {
+ self.root.get(hash_key(&*self.hasher, a), 0, a).is_some()
+ }
+
+ /// Test whether a set is a subset of another set, meaning that
+ /// all values in our set must also be in the other set.
+ ///
+ /// Time: O(n log n)
+ #[must_use]
+ pub fn is_subset<RS>(&self, other: RS) -> bool
+ where
+ RS: Borrow<Self>,
+ {
+ let o = other.borrow();
+ self.iter().all(|a| o.contains(a))
+ }
+
+ /// Test whether a set is a proper subset of another set, meaning
+ /// that all values in our set must also be in the other set. A
+ /// proper subset must also be smaller than the other set.
+ ///
+ /// Time: O(n log n)
+ #[must_use]
+ pub fn is_proper_subset<RS>(&self, other: RS) -> bool
+ where
+ RS: Borrow<Self>,
+ {
+ self.len() != other.borrow().len() && self.is_subset(other)
+ }
+}
+
+impl<A, S> HashSet<A, S>
+where
+ A: Hash + Eq + Clone,
+ S: BuildHasher,
+{
+ /// Insert a value into a set.
+ ///
+ /// Time: O(log n)
+ #[inline]
+ pub fn insert(&mut self, a: A) -> Option<A> {
+ let hash = hash_key(&*self.hasher, &a);
+ let root = PoolRef::make_mut(&self.pool.0, &mut self.root);
+ match root.insert(&self.pool.0, hash, 0, Value(a)) {
+ None => {
+ self.size += 1;
+ None
+ }
+ Some(Value(old_value)) => Some(old_value),
+ }
+ }
+
+ /// Remove a value from a set if it exists.
+ ///
+ /// Time: O(log n)
+ pub fn remove<BA>(&mut self, a: &BA) -> Option<A>
+ where
+ BA: Hash + Eq + ?Sized,
+ A: Borrow<BA>,
+ {
+ let root = PoolRef::make_mut(&self.pool.0, &mut self.root);
+ let result = root.remove(&self.pool.0, hash_key(&*self.hasher, a), 0, a);
+ if result.is_some() {
+ self.size -= 1;
+ }
+ result.map(|v| v.0)
+ }
+
+ /// Construct a new set from the current set with the given value
+ /// added.
+ ///
+ /// Time: O(log n)
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # #[macro_use] extern crate im_rc as im;
+ /// # use im::hashset::HashSet;
+ /// # use std::sync::Arc;
+ /// let set = hashset![123];
+ /// assert_eq!(
+ /// set.update(456),
+ /// hashset![123, 456]
+ /// );
+ /// ```
+ #[must_use]
+ pub fn update(&self, a: A) -> Self {
+ let mut out = self.clone();
+ out.insert(a);
+ out
+ }
+
+ /// Construct a new set with the given value removed if it's in
+ /// the set.
+ ///
+ /// Time: O(log n)
+ #[must_use]
+ pub fn without<BA>(&self, a: &BA) -> Self
+ where
+ BA: Hash + Eq + ?Sized,
+ A: Borrow<BA>,
+ {
+ let mut out = self.clone();
+ out.remove(a);
+ out
+ }
+
+ /// Filter out values from a set which don't satisfy a predicate.
+ ///
+ /// This is slightly more efficient than filtering using an
+ /// iterator, in that it doesn't need to rehash the retained
+ /// values, but it still needs to reconstruct the entire tree
+ /// structure of the set.
+ ///
+ /// Time: O(n log n)
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # #[macro_use] extern crate im_rc as im;
+ /// # use im::HashSet;
+ /// let mut set = hashset![1, 2, 3];
+ /// set.retain(|v| *v > 1);
+ /// let expected = hashset![2, 3];
+ /// assert_eq!(expected, set);
+ /// ```
+ pub fn retain<F>(&mut self, mut f: F)
+ where
+ F: FnMut(&A) -> bool,
+ {
+ let old_root = self.root.clone();
+ let root = PoolRef::make_mut(&self.pool.0, &mut self.root);
+ for (value, hash) in NodeIter::new(&old_root, self.size) {
+ if !f(value) && root.remove(&self.pool.0, hash, 0, value).is_some() {
+ self.size -= 1;
+ }
+ }
+ }
+
+ /// Construct the union of two sets.
+ ///
+ /// Time: O(n log n)
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # #[macro_use] extern crate im_rc as im;
+ /// # use im::hashset::HashSet;
+ /// let set1 = hashset!{1, 2};
+ /// let set2 = hashset!{2, 3};
+ /// let expected = hashset!{1, 2, 3};
+ /// assert_eq!(expected, set1.union(set2));
+ /// ```
+ #[must_use]
+ pub fn union(self, other: Self) -> Self {
+ let (mut to_mutate, to_consume) = if self.len() >= other.len() {
+ (self, other)
+ } else {
+ (other, self)
+ };
+ for value in to_consume {
+ to_mutate.insert(value);
+ }
+ to_mutate
+ }
+
+ /// Construct the union of multiple sets.
+ ///
+ /// Time: O(n log n)
+ #[must_use]
+ pub fn unions<I>(i: I) -> Self
+ where
+ I: IntoIterator<Item = Self>,
+ S: Default,
+ {
+ i.into_iter().fold(Self::default(), Self::union)
+ }
+
+ /// Construct the symmetric difference between two sets.
+ ///
+ /// This is an alias for the
+ /// [`symmetric_difference`][symmetric_difference] method.
+ ///
+ /// Time: O(n log n)
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # #[macro_use] extern crate im_rc as im;
+ /// # use im::hashset::HashSet;
+ /// let set1 = hashset!{1, 2};
+ /// let set2 = hashset!{2, 3};
+ /// let expected = hashset!{1, 3};
+ /// assert_eq!(expected, set1.difference(set2));
+ /// ```
+ ///
+ /// [symmetric_difference]: #method.symmetric_difference
+ #[must_use]
+ pub fn difference(self, other: Self) -> Self {
+ self.symmetric_difference(other)
+ }
+
+ /// Construct the symmetric difference between two sets.
+ ///
+ /// Time: O(n log n)
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # #[macro_use] extern crate im_rc as im;
+ /// # use im::hashset::HashSet;
+ /// let set1 = hashset!{1, 2};
+ /// let set2 = hashset!{2, 3};
+ /// let expected = hashset!{1, 3};
+ /// assert_eq!(expected, set1.symmetric_difference(set2));
+ /// ```
+ #[must_use]
+ pub fn symmetric_difference(mut self, other: Self) -> Self {
+ for value in other {
+ if self.remove(&value).is_none() {
+ self.insert(value);
+ }
+ }
+ self
+ }
+
+ /// Construct the relative complement between two sets, that is the set
+ /// of values in `self` that do not occur in `other`.
+ ///
+ /// Time: O(m log n) where m is the size of the other set
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # #[macro_use] extern crate im_rc as im;
+ /// # use im::ordset::OrdSet;
+ /// let set1 = ordset!{1, 2};
+ /// let set2 = ordset!{2, 3};
+ /// let expected = ordset!{1};
+ /// assert_eq!(expected, set1.relative_complement(set2));
+ /// ```
+ #[must_use]
+ pub fn relative_complement(mut self, other: Self) -> Self {
+ for value in other {
+ let _ = self.remove(&value);
+ }
+ self
+ }
+
+ /// Construct the intersection of two sets.
+ ///
+ /// Time: O(n log n)
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # #[macro_use] extern crate im_rc as im;
+ /// # use im::hashset::HashSet;
+ /// let set1 = hashset!{1, 2};
+ /// let set2 = hashset!{2, 3};
+ /// let expected = hashset!{2};
+ /// assert_eq!(expected, set1.intersection(set2));
+ /// ```
+ #[must_use]
+ pub fn intersection(self, other: Self) -> Self {
+ let mut out = self.new_from();
+ for value in other {
+ if self.contains(&value) {
+ out.insert(value);
+ }
+ }
+ out
+ }
+}
+
+// Core traits
+
+impl<A, S> Clone for HashSet<A, S>
+where
+ A: Clone,
+{
+ /// Clone a set.
+ ///
+ /// Time: O(1)
+ #[inline]
+ fn clone(&self) -> Self {
+ HashSet {
+ hasher: self.hasher.clone(),
+ pool: self.pool.clone(),
+ root: self.root.clone(),
+ size: self.size,
+ }
+ }
+}
+
+impl<A, S> PartialEq for HashSet<A, S>
+where
+ A: Hash + Eq,
+ S: BuildHasher + Default,
+{
+ fn eq(&self, other: &Self) -> bool {
+ self.test_eq(other)
+ }
+}
+
+impl<A, S> Eq for HashSet<A, S>
+where
+ A: Hash + Eq,
+ S: BuildHasher + Default,
+{
+}
+
+impl<A, S> PartialOrd for HashSet<A, S>
+where
+ A: Hash + Eq + Clone + PartialOrd,
+ S: BuildHasher + Default,
+{
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ if Ref::ptr_eq(&self.hasher, &other.hasher) {
+ return self.iter().partial_cmp(other.iter());
+ }
+ self.iter().partial_cmp(other.iter())
+ }
+}
+
+impl<A, S> Ord for HashSet<A, S>
+where
+ A: Hash + Eq + Clone + Ord,
+ S: BuildHasher + Default,
+{
+ fn cmp(&self, other: &Self) -> Ordering {
+ if Ref::ptr_eq(&self.hasher, &other.hasher) {
+ return self.iter().cmp(other.iter());
+ }
+ self.iter().cmp(other.iter())
+ }
+}
+
+impl<A, S> Hash for HashSet<A, S>
+where
+ A: Hash + Eq,
+ S: BuildHasher + Default,
+{
+ fn hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ for i in self.iter() {
+ i.hash(state);
+ }
+ }
+}
+
+impl<A, S> Default for HashSet<A, S>
+where
+ S: BuildHasher + Default,
+{
+ fn default() -> Self {
+ let pool = HashSetPool::default();
+ let root = PoolRef::default(&pool.0);
+ HashSet {
+ hasher: Ref::<S>::default(),
+ pool,
+ root,
+ size: 0,
+ }
+ }
+}
+
+impl<A, S> Add for HashSet<A, S>
+where
+ A: Hash + Eq + Clone,
+ S: BuildHasher,
+{
+ type Output = HashSet<A, S>;
+
+ fn add(self, other: Self) -> Self::Output {
+ self.union(other)
+ }
+}
+
+impl<A, S> Mul for HashSet<A, S>
+where
+ A: Hash + Eq + Clone,
+ S: BuildHasher,
+{
+ type Output = HashSet<A, S>;
+
+ fn mul(self, other: Self) -> Self::Output {
+ self.intersection(other)
+ }
+}
+
+impl<'a, A, S> Add for &'a HashSet<A, S>
+where
+ A: Hash + Eq + Clone,
+ S: BuildHasher,
+{
+ type Output = HashSet<A, S>;
+
+ fn add(self, other: Self) -> Self::Output {
+ self.clone().union(other.clone())
+ }
+}
+
+impl<'a, A, S> Mul for &'a HashSet<A, S>
+where
+ A: Hash + Eq + Clone,
+ S: BuildHasher,
+{
+ type Output = HashSet<A, S>;
+
+ fn mul(self, other: Self) -> Self::Output {
+ self.clone().intersection(other.clone())
+ }
+}
+
+impl<A, S> Sum for HashSet<A, S>
+where
+ A: Hash + Eq + Clone,
+ S: BuildHasher + Default,
+{
+ fn sum<I>(it: I) -> Self
+ where
+ I: Iterator<Item = Self>,
+ {
+ it.fold(Self::default(), |a, b| a + b)
+ }
+}
+
+impl<A, S, R> Extend<R> for HashSet<A, S>
+where
+ A: Hash + Eq + Clone + From<R>,
+ S: BuildHasher,
+{
+ fn extend<I>(&mut self, iter: I)
+ where
+ I: IntoIterator<Item = R>,
+ {
+ for value in iter {
+ self.insert(From::from(value));
+ }
+ }
+}
+
+#[cfg(not(has_specialisation))]
+impl<A, S> Debug for HashSet<A, S>
+where
+ A: Hash + Eq + Debug,
+ S: BuildHasher,
+{
+ fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
+ f.debug_set().entries(self.iter()).finish()
+ }
+}
+
+#[cfg(has_specialisation)]
+impl<A, S> Debug for HashSet<A, S>
+where
+ A: Hash + Eq + Debug,
+ S: BuildHasher,
+{
+ default fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
+ f.debug_set().entries(self.iter()).finish()
+ }
+}
+
+#[cfg(has_specialisation)]
+impl<A, S> Debug for HashSet<A, S>
+where
+ A: Hash + Eq + Debug + Ord,
+ S: BuildHasher,
+{
+ fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
+ f.debug_set().entries(self.iter()).finish()
+ }
+}
+
+// Iterators
+
+/// An iterator over the elements of a set.
+pub struct Iter<'a, A> {
+ it: NodeIter<'a, Value<A>>,
+}
+
+impl<'a, A> Iterator for Iter<'a, A>
+where
+ A: 'a,
+{
+ type Item = &'a A;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.it.next().map(|(v, _)| &v.0)
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.it.size_hint()
+ }
+}
+
+impl<'a, A> ExactSizeIterator for Iter<'a, A> {}
+
+impl<'a, A> FusedIterator for Iter<'a, A> {}
+
+/// A consuming iterator over the elements of a set.
+pub struct ConsumingIter<A>
+where
+ A: Hash + Eq + Clone,
+{
+ it: NodeDrain<Value<A>>,
+}
+
+impl<A> Iterator for ConsumingIter<A>
+where
+ A: Hash + Eq + Clone,
+{
+ type Item = A;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.it.next().map(|(v, _)| v.0)
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ self.it.size_hint()
+ }
+}
+
+impl<A> ExactSizeIterator for ConsumingIter<A> where A: Hash + Eq + Clone {}
+
+impl<A> FusedIterator for ConsumingIter<A> where A: Hash + Eq + Clone {}
+
+// Iterator conversions
+
+impl<A, RA, S> FromIterator<RA> for HashSet<A, S>
+where
+ A: Hash + Eq + Clone + From<RA>,
+ S: BuildHasher + Default,
+{
+ fn from_iter<T>(i: T) -> Self
+ where
+ T: IntoIterator<Item = RA>,
+ {
+ let mut set = Self::default();
+ for value in i {
+ set.insert(From::from(value));
+ }
+ set
+ }
+}
+
+impl<'a, A, S> IntoIterator for &'a HashSet<A, S>
+where
+ A: Hash + Eq,
+ S: BuildHasher,
+{
+ type Item = &'a A;
+ type IntoIter = Iter<'a, A>;
+
+ fn into_iter(self) -> Self::IntoIter {
+ self.iter()
+ }
+}
+
+impl<A, S> IntoIterator for HashSet<A, S>
+where
+ A: Hash + Eq + Clone,
+ S: BuildHasher,
+{
+ type Item = A;
+ type IntoIter = ConsumingIter<Self::Item>;
+
+ fn into_iter(self) -> Self::IntoIter {
+ ConsumingIter {
+ it: NodeDrain::new(&self.pool.0, self.root, self.size),
+ }
+ }
+}
+
+// Conversions
+
+impl<'s, 'a, A, OA, SA, SB> From<&'s HashSet<&'a A, SA>> for HashSet<OA, SB>
+where
+ A: ToOwned<Owned = OA> + Hash + Eq + ?Sized,
+ OA: Borrow<A> + Hash + Eq + Clone,
+ SA: BuildHasher,
+ SB: BuildHasher + Default,
+{
+ fn from(set: &HashSet<&A, SA>) -> Self {
+ set.iter().map(|a| (*a).to_owned()).collect()
+ }
+}
+
+impl<'a, A, S> From<&'a [A]> for HashSet<A, S>
+where
+ A: Hash + Eq + Clone,
+ S: BuildHasher + Default,
+{
+ fn from(slice: &'a [A]) -> Self {
+ slice.iter().cloned().collect()
+ }
+}
+
+impl<A, S> From<Vec<A>> for HashSet<A, S>
+where
+ A: Hash + Eq + Clone,
+ S: BuildHasher + Default,
+{
+ fn from(vec: Vec<A>) -> Self {
+ vec.into_iter().collect()
+ }
+}
+
+impl<'a, A, S> From<&'a Vec<A>> for HashSet<A, S>
+where
+ A: Hash + Eq + Clone,
+ S: BuildHasher + Default,
+{
+ fn from(vec: &Vec<A>) -> Self {
+ vec.iter().cloned().collect()
+ }
+}
+
+impl<A, S> From<Vector<A>> for HashSet<A, S>
+where
+ A: Hash + Eq + Clone,
+ S: BuildHasher + Default,
+{
+ fn from(vector: Vector<A>) -> Self {
+ vector.into_iter().collect()
+ }
+}
+
+impl<'a, A, S> From<&'a Vector<A>> for HashSet<A, S>
+where
+ A: Hash + Eq + Clone,
+ S: BuildHasher + Default,
+{
+ fn from(vector: &Vector<A>) -> Self {
+ vector.iter().cloned().collect()
+ }
+}
+
+impl<A, S> From<collections::HashSet<A>> for HashSet<A, S>
+where
+ A: Eq + Hash + Clone,
+ S: BuildHasher + Default,
+{
+ fn from(hash_set: collections::HashSet<A>) -> Self {
+ hash_set.into_iter().collect()
+ }
+}
+
+impl<'a, A, S> From<&'a collections::HashSet<A>> for HashSet<A, S>
+where
+ A: Eq + Hash + Clone,
+ S: BuildHasher + Default,
+{
+ fn from(hash_set: &collections::HashSet<A>) -> Self {
+ hash_set.iter().cloned().collect()
+ }
+}
+
+impl<'a, A, S> From<&'a BTreeSet<A>> for HashSet<A, S>
+where
+ A: Hash + Eq + Clone,
+ S: BuildHasher + Default,
+{
+ fn from(btree_set: &BTreeSet<A>) -> Self {
+ btree_set.iter().cloned().collect()
+ }
+}
+
+impl<A, S> From<OrdSet<A>> for HashSet<A, S>
+where
+ A: Ord + Hash + Eq + Clone,
+ S: BuildHasher + Default,
+{
+ fn from(ordset: OrdSet<A>) -> Self {
+ ordset.into_iter().collect()
+ }
+}
+
+impl<'a, A, S> From<&'a OrdSet<A>> for HashSet<A, S>
+where
+ A: Ord + Hash + Eq + Clone,
+ S: BuildHasher + Default,
+{
+ fn from(ordset: &OrdSet<A>) -> Self {
+ ordset.into_iter().cloned().collect()
+ }
+}
+
+// Proptest
+#[cfg(any(test, feature = "proptest"))]
+#[doc(hidden)]
+pub mod proptest {
+ #[deprecated(
+ since = "14.3.0",
+ note = "proptest strategies have moved to im::proptest"
+ )]
+ pub use crate::proptest::hash_set;
+}
+
+#[cfg(test)]
+mod test {
+ use super::proptest::*;
+ use super::*;
+ use crate::test::LolHasher;
+ use ::proptest::num::i16;
+ use ::proptest::proptest;
+ use std::hash::BuildHasherDefault;
+
+ #[test]
+ fn insert_failing() {
+ let mut set: HashSet<i16, BuildHasherDefault<LolHasher>> = Default::default();
+ set.insert(14658);
+ assert_eq!(1, set.len());
+ set.insert(-19198);
+ assert_eq!(2, set.len());
+ }
+
+ #[test]
+ fn match_strings_with_string_slices() {
+ let mut set: HashSet<String> = From::from(&hashset!["foo", "bar"]);
+ set = set.without("bar");
+ assert!(!set.contains("bar"));
+ set.remove("foo");
+ assert!(!set.contains("foo"));
+ }
+
+ #[test]
+ fn macro_allows_trailing_comma() {
+ let set1 = hashset! {"foo", "bar"};
+ let set2 = hashset! {
+ "foo",
+ "bar",
+ };
+ assert_eq!(set1, set2);
+ }
+
+ #[test]
+ fn issue_60_drain_iterator_memory_corruption() {
+ use crate::test::MetroHashBuilder;
+ for i in 0..1000 {
+ let mut lhs = vec![0, 1, 2];
+ lhs.sort_unstable();
+
+ let hasher = Ref::from(MetroHashBuilder::new(i));
+ let mut iset: HashSet<_, MetroHashBuilder> = HashSet::with_hasher(hasher.clone());
+ for &i in &lhs {
+ iset.insert(i);
+ }
+
+ let mut rhs: Vec<_> = iset.clone().into_iter().collect();
+ rhs.sort_unstable();
+
+ if lhs != rhs {
+ println!("iteration: {}", i);
+ println!("seed: {}", hasher.seed());
+ println!("lhs: {}: {:?}", lhs.len(), &lhs);
+ println!("rhs: {}: {:?}", rhs.len(), &rhs);
+ panic!();
+ }
+ }
+ }
+
+ proptest! {
+ #[test]
+ fn proptest_a_set(ref s in hash_set(".*", 10..100)) {
+ assert!(s.len() < 100);
+ assert!(s.len() >= 10);
+ }
+ }
+}