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, IterMut as NodeIterMut, Node,
};
use crate::ordset::OrdSet;
use crate::util::Ref;
#[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
}};
}
pub struct HashSet<A, S = RandomState> {
hasher: Ref<S>,
root: Ref<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
}
}
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> {
#[must_use]
pub fn new() -> Self {
Self::default()
}
}
impl<A> HashSet<A, RandomState>
where
A: Hash + Eq + Clone,
{
#[inline]
#[must_use]
pub fn unit(a: A) -> Self {
HashSet::new().update(a)
}
}
impl<A, S> HashSet<A, S> {
#[inline]
#[must_use]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
#[inline]
#[must_use]
pub fn len(&self) -> usize {
self.size
}
#[inline]
#[must_use]
pub fn with_hasher<RS>(hasher: RS) -> Self
where
Ref<S>: From<RS>,
{
HashSet {
size: 0,
root: Ref::new(Node::new()),
hasher: From::from(hasher),
}
}
#[must_use]
pub fn hasher(&self) -> &Ref<S> {
&self.hasher
}
#[inline]
#[must_use]
pub fn new_from<A1>(&self) -> HashSet<A1, S>
where
A1: Hash + Eq + Clone,
{
HashSet {
size: 0,
root: Ref::new(Node::new()),
hasher: self.hasher.clone(),
}
}
pub fn clear(&mut self) {
if !self.is_empty() {
self.root = Default::default();
self.size = 0;
}
}
#[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
}
#[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()
}
#[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))
}
#[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,
{
#[must_use]
pub fn iter_mut(&mut self) -> IterMut<'_, A> {
let root = Ref::make_mut(&mut self.root);
IterMut {
it: NodeIterMut::new(root, self.size),
}
}
#[inline]
pub fn insert(&mut self, a: A) -> Option<A> {
let hash = hash_key(&*self.hasher, &a);
let root = Ref::make_mut(&mut self.root);
match root.insert(hash, 0, Value(a)) {
None => {
self.size += 1;
None
}
Some(Value(old_value)) => Some(old_value),
}
}
pub fn remove<BA>(&mut self, a: &BA) -> Option<A>
where
BA: Hash + Eq + ?Sized,
A: Borrow<BA>,
{
let root = Ref::make_mut(&mut self.root);
let result = root.remove(hash_key(&*self.hasher, a), 0, a);
if result.is_some() {
self.size -= 1;
}
result.map(|v| v.0)
}
#[must_use]
pub fn update(&self, a: A) -> Self {
let mut out = self.clone();
out.insert(a);
out
}
#[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
}
pub fn retain<F>(&mut self, mut f: F)
where
F: FnMut(&A) -> bool,
{
let old_root = self.root.clone();
let root = Ref::make_mut(&mut self.root);
for (value, hash) in NodeIter::new(&old_root, self.size) {
if !f(value) && root.remove(hash, 0, value).is_some() {
self.size -= 1;
}
}
}
#[must_use]
pub fn union(mut self, other: Self) -> Self {
for value in other {
self.insert(value);
}
self
}
#[must_use]
pub fn unions<I>(i: I) -> Self
where
I: IntoIterator<Item = Self>,
S: Default,
{
i.into_iter().fold(Self::default(), Self::union)
}
#[must_use]
pub fn difference(self, other: Self) -> Self {
self.symmetric_difference(other)
}
#[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
}
#[must_use]
pub fn relative_complement(mut self, other: Self) -> Self {
for value in other {
let _ = self.remove(&value);
}
self
}
#[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
}
}
impl<A, S> Clone for HashSet<A, S>
where
A: Clone,
{
fn clone(&self) -> Self {
HashSet {
hasher: self.hasher.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());
}
let m1: ::std::collections::HashSet<A> = self.iter().cloned().collect();
let m2: ::std::collections::HashSet<A> = other.iter().cloned().collect();
m1.iter().partial_cmp(m2.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());
}
let m1: ::std::collections::HashSet<A> = self.iter().cloned().collect();
let m2: ::std::collections::HashSet<A> = other.iter().cloned().collect();
m1.iter().cmp(m2.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 {
HashSet {
hasher: Ref::<S>::default(),
root: Ref::new(Node::new()),
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()
}
}
pub struct Iter<'a, A>
where
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> {}
pub struct IterMut<'a, A>
where
A: 'a,
{
it: NodeIterMut<'a, Value<A>>,
}
impl<'a, A> Iterator for IterMut<'a, A>
where
A: 'a + Clone,
{
type Item = &'a mut A;
fn next(&mut self) -> Option<Self::Item> {
self.it.next().map(|(v, _)| &mut v.0)
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.it.size_hint()
}
}
impl<'a, A> ExactSizeIterator for IterMut<'a, A> where A: Clone {}
impl<'a, A> FusedIterator for IterMut<'a, A> where A: Clone {}
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 {}
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.root, self.size),
}
}
}
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<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()
}
}
#[cfg(all(threadsafe, feature = "quickcheck"))]
use quickcheck::{Arbitrary, Gen};
#[cfg(all(threadsafe, feature = "quickcheck"))]
impl<A, S> Arbitrary for HashSet<A, S>
where
A: Hash + Eq + Arbitrary + Sync,
S: BuildHasher + Default + Send + Sync + 'static,
{
fn arbitrary<G: Gen>(g: &mut G) -> Self {
HashSet::from_iter(Vec::<A>::arbitrary(g))
}
}
#[cfg(any(test, feature = "proptest"))]
pub mod proptest {
use super::*;
use ::proptest::strategy::{BoxedStrategy, Strategy, ValueTree};
use std::ops::Range;
pub fn hash_set<A: Strategy + 'static>(
element: A,
size: Range<usize>,
) -> BoxedStrategy<HashSet<<A::Tree as ValueTree>::Value>>
where
<A::Tree as ValueTree>::Value: Hash + Eq + Clone,
{
::proptest::collection::vec(element, size.clone())
.prop_map(HashSet::from)
.prop_filter("HashSet minimum size".to_owned(), move |s| {
s.len() >= size.start
})
.boxed()
}
}
#[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();
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();
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);
}
}
}