use core::{
fmt::Debug,
hash::{BuildHasher, Hash},
ops::{
BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Deref, DerefMut, Sub,
SubAssign,
},
};
use hashbrown::{hash_set as hb, Equivalent};
use crate::hash::FixedHasher;
#[cfg(feature = "rayon")]
use rayon::prelude::{FromParallelIterator, IntoParallelIterator, ParallelExtend};
pub use hb::{Difference, Drain, Intersection, IntoIter, Iter, SymmetricDifference, Union};
pub use hb::{ExtractIf, OccupiedEntry, VacantEntry};
pub type Entry<'a, T, S = FixedHasher> = hb::Entry<'a, T, S>;
#[repr(transparent)]
pub struct HashSet<T, S = FixedHasher>(hb::HashSet<T, S>);
impl<T, S> Clone for HashSet<T, S>
where
hb::HashSet<T, S>: Clone,
{
#[inline]
fn clone(&self) -> Self {
Self(self.0.clone())
}
#[inline]
fn clone_from(&mut self, source: &Self) {
self.0.clone_from(&source.0);
}
}
impl<T, S> Debug for HashSet<T, S>
where
hb::HashSet<T, S>: Debug,
{
#[inline]
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
<hb::HashSet<T, S> as Debug>::fmt(&self.0, f)
}
}
impl<T, S> Default for HashSet<T, S>
where
hb::HashSet<T, S>: Default,
{
#[inline]
fn default() -> Self {
Self(Default::default())
}
}
impl<T, S> PartialEq for HashSet<T, S>
where
hb::HashSet<T, S>: PartialEq,
{
#[inline]
fn eq(&self, other: &Self) -> bool {
self.0.eq(&other.0)
}
}
impl<T, S> Eq for HashSet<T, S> where hb::HashSet<T, S>: Eq {}
impl<T, S, X> FromIterator<X> for HashSet<T, S>
where
hb::HashSet<T, S>: FromIterator<X>,
{
#[inline]
fn from_iter<U: IntoIterator<Item = X>>(iter: U) -> Self {
Self(FromIterator::from_iter(iter))
}
}
impl<T, S> IntoIterator for HashSet<T, S>
where
hb::HashSet<T, S>: IntoIterator,
{
type Item = <hb::HashSet<T, S> as IntoIterator>::Item;
type IntoIter = <hb::HashSet<T, S> as IntoIterator>::IntoIter;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
impl<'a, T, S> IntoIterator for &'a HashSet<T, S>
where
&'a hb::HashSet<T, S>: IntoIterator,
{
type Item = <&'a hb::HashSet<T, S> as IntoIterator>::Item;
type IntoIter = <&'a hb::HashSet<T, S> as IntoIterator>::IntoIter;
#[inline]
fn into_iter(self) -> Self::IntoIter {
(&self.0).into_iter()
}
}
impl<'a, T, S> IntoIterator for &'a mut HashSet<T, S>
where
&'a mut hb::HashSet<T, S>: IntoIterator,
{
type Item = <&'a mut hb::HashSet<T, S> as IntoIterator>::Item;
type IntoIter = <&'a mut hb::HashSet<T, S> as IntoIterator>::IntoIter;
#[inline]
fn into_iter(self) -> Self::IntoIter {
(&mut self.0).into_iter()
}
}
impl<T, S, X> Extend<X> for HashSet<T, S>
where
hb::HashSet<T, S>: Extend<X>,
{
#[inline]
fn extend<U: IntoIterator<Item = X>>(&mut self, iter: U) {
self.0.extend(iter);
}
}
impl<T, const N: usize> From<[T; N]> for HashSet<T, FixedHasher>
where
T: Eq + Hash,
{
fn from(value: [T; N]) -> Self {
value.into_iter().collect()
}
}
impl<T, S> From<crate::collections::HashMap<T, (), S>> for HashSet<T, S> {
#[inline]
fn from(value: crate::collections::HashMap<T, (), S>) -> Self {
Self(hb::HashSet::from(hashbrown::HashMap::from(value)))
}
}
impl<T, S> From<hb::HashSet<T, S>> for HashSet<T, S> {
#[inline]
fn from(value: hb::HashSet<T, S>) -> Self {
Self(value)
}
}
impl<T, S> From<HashSet<T, S>> for hb::HashSet<T, S> {
#[inline]
fn from(value: HashSet<T, S>) -> Self {
value.0
}
}
impl<T, S> Deref for HashSet<T, S> {
type Target = hb::HashSet<T, S>;
#[inline]
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T, S> DerefMut for HashSet<T, S> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
#[cfg(feature = "serialize")]
impl<T, S> serde::Serialize for HashSet<T, S>
where
hb::HashSet<T, S>: serde::Serialize,
{
#[inline]
fn serialize<U>(&self, serializer: U) -> Result<U::Ok, U::Error>
where
U: serde::Serializer,
{
self.0.serialize(serializer)
}
}
#[cfg(feature = "serialize")]
impl<'de, T, S> serde::Deserialize<'de> for HashSet<T, S>
where
hb::HashSet<T, S>: serde::Deserialize<'de>,
{
#[inline]
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
Ok(Self(serde::Deserialize::deserialize(deserializer)?))
}
}
#[cfg(feature = "rayon")]
impl<T, S, U> FromParallelIterator<U> for HashSet<T, S>
where
hb::HashSet<T, S>: FromParallelIterator<U>,
U: Send,
{
fn from_par_iter<P>(par_iter: P) -> Self
where
P: IntoParallelIterator<Item = U>,
{
Self(<hb::HashSet<T, S> as FromParallelIterator<U>>::from_par_iter(par_iter))
}
}
#[cfg(feature = "rayon")]
impl<T, S> IntoParallelIterator for HashSet<T, S>
where
hb::HashSet<T, S>: IntoParallelIterator,
{
type Item = <hb::HashSet<T, S> as IntoParallelIterator>::Item;
type Iter = <hb::HashSet<T, S> as IntoParallelIterator>::Iter;
fn into_par_iter(self) -> Self::Iter {
self.0.into_par_iter()
}
}
#[cfg(feature = "rayon")]
impl<'a, T: Sync, S> IntoParallelIterator for &'a HashSet<T, S>
where
&'a hb::HashSet<T, S>: IntoParallelIterator,
{
type Item = <&'a hb::HashSet<T, S> as IntoParallelIterator>::Item;
type Iter = <&'a hb::HashSet<T, S> as IntoParallelIterator>::Iter;
fn into_par_iter(self) -> Self::Iter {
(&self.0).into_par_iter()
}
}
#[cfg(feature = "rayon")]
impl<T, S, U> ParallelExtend<U> for HashSet<T, S>
where
hb::HashSet<T, S>: ParallelExtend<U>,
U: Send,
{
fn par_extend<I>(&mut self, par_iter: I)
where
I: IntoParallelIterator<Item = U>,
{
<hb::HashSet<T, S> as ParallelExtend<U>>::par_extend(&mut self.0, par_iter);
}
}
impl<T> HashSet<T, FixedHasher> {
#[inline]
pub const fn new() -> Self {
Self::with_hasher(FixedHasher)
}
#[inline]
pub fn with_capacity(capacity: usize) -> Self {
Self::with_capacity_and_hasher(capacity, FixedHasher)
}
}
impl<T, S> HashSet<T, S> {
#[inline]
pub fn capacity(&self) -> usize {
self.0.capacity()
}
#[inline]
pub fn iter(&self) -> Iter<'_, T> {
self.0.iter()
}
#[inline]
pub fn len(&self) -> usize {
self.0.len()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
#[inline]
pub fn drain(&mut self) -> Drain<'_, T> {
self.0.drain()
}
#[inline]
pub fn retain<F>(&mut self, f: F)
where
F: FnMut(&T) -> bool,
{
self.0.retain(f);
}
#[inline]
pub fn extract_if<F>(&mut self, f: F) -> ExtractIf<'_, T, F>
where
F: FnMut(&T) -> bool,
{
self.0.extract_if(f)
}
#[inline]
pub fn clear(&mut self) {
self.0.clear();
}
#[inline]
pub const fn with_hasher(hasher: S) -> Self {
Self(hb::HashSet::with_hasher(hasher))
}
#[inline]
pub fn with_capacity_and_hasher(capacity: usize, hasher: S) -> Self {
Self(hb::HashSet::with_capacity_and_hasher(capacity, hasher))
}
#[inline]
pub fn hasher(&self) -> &S {
self.0.hasher()
}
#[inline]
pub fn into_inner(self) -> hb::HashSet<T, S> {
self.0
}
}
impl<T, S> HashSet<T, S>
where
T: Eq + Hash,
S: BuildHasher,
{
#[inline]
pub fn reserve(&mut self, additional: usize) {
self.0.reserve(additional);
}
#[inline]
pub fn try_reserve(&mut self, additional: usize) -> Result<(), hashbrown::TryReserveError> {
self.0.try_reserve(additional)
}
#[inline]
pub fn shrink_to_fit(&mut self) {
self.0.shrink_to_fit();
}
#[inline]
pub fn shrink_to(&mut self, min_capacity: usize) {
self.0.shrink_to(min_capacity);
}
#[inline]
pub fn difference<'a>(&'a self, other: &'a Self) -> Difference<'a, T, S> {
self.0.difference(other)
}
#[inline]
pub fn symmetric_difference<'a>(&'a self, other: &'a Self) -> SymmetricDifference<'a, T, S> {
self.0.symmetric_difference(other)
}
#[inline]
pub fn intersection<'a>(&'a self, other: &'a Self) -> Intersection<'a, T, S> {
self.0.intersection(other)
}
#[inline]
pub fn union<'a>(&'a self, other: &'a Self) -> Union<'a, T, S> {
self.0.union(other)
}
#[inline]
pub fn contains<Q>(&self, value: &Q) -> bool
where
Q: Hash + Equivalent<T> + ?Sized,
{
self.0.contains(value)
}
#[inline]
pub fn get<Q>(&self, value: &Q) -> Option<&T>
where
Q: Hash + Equivalent<T> + ?Sized,
{
self.0.get(value)
}
#[inline]
pub fn get_or_insert(&mut self, value: T) -> &T {
self.0.get_or_insert(value)
}
#[inline]
pub fn get_or_insert_with<Q, F>(&mut self, value: &Q, f: F) -> &T
where
Q: Hash + Equivalent<T> + ?Sized,
F: FnOnce(&Q) -> T,
{
self.0.get_or_insert_with(value, f)
}
#[inline]
pub fn entry(&mut self, value: T) -> Entry<'_, T, S> {
self.0.entry(value)
}
#[inline]
pub fn is_disjoint(&self, other: &Self) -> bool {
self.0.is_disjoint(other)
}
#[inline]
pub fn is_subset(&self, other: &Self) -> bool {
self.0.is_subset(other)
}
#[inline]
pub fn is_superset(&self, other: &Self) -> bool {
self.0.is_superset(other)
}
#[inline]
pub fn insert(&mut self, value: T) -> bool {
self.0.insert(value)
}
#[inline]
pub fn replace(&mut self, value: T) -> Option<T> {
self.0.replace(value)
}
#[inline]
pub fn remove<Q>(&mut self, value: &Q) -> bool
where
Q: Hash + Equivalent<T> + ?Sized,
{
self.0.remove(value)
}
#[inline]
pub fn take<Q>(&mut self, value: &Q) -> Option<T>
where
Q: Hash + Equivalent<T> + ?Sized,
{
self.0.take(value)
}
#[inline]
pub fn allocation_size(&self) -> usize {
self.0.allocation_size()
}
#[expect(
unsafe_code,
reason = "re-exporting unsafe method from Hashbrown requires unsafe code"
)]
#[inline]
pub unsafe fn insert_unique_unchecked(&mut self, value: T) -> &T {
unsafe { self.0.insert_unique_unchecked(value) }
}
}
impl<T, S> BitOr<&HashSet<T, S>> for &HashSet<T, S>
where
for<'a> &'a hb::HashSet<T, S>: BitOr<&'a hb::HashSet<T, S>, Output = hb::HashSet<T, S>>,
{
type Output = HashSet<T, S>;
#[inline]
fn bitor(self, rhs: &HashSet<T, S>) -> HashSet<T, S> {
HashSet(self.0.bitor(&rhs.0))
}
}
impl<T, S> BitAnd<&HashSet<T, S>> for &HashSet<T, S>
where
for<'a> &'a hb::HashSet<T, S>: BitAnd<&'a hb::HashSet<T, S>, Output = hb::HashSet<T, S>>,
{
type Output = HashSet<T, S>;
#[inline]
fn bitand(self, rhs: &HashSet<T, S>) -> HashSet<T, S> {
HashSet(self.0.bitand(&rhs.0))
}
}
impl<T, S> BitXor<&HashSet<T, S>> for &HashSet<T, S>
where
for<'a> &'a hb::HashSet<T, S>: BitXor<&'a hb::HashSet<T, S>, Output = hb::HashSet<T, S>>,
{
type Output = HashSet<T, S>;
#[inline]
fn bitxor(self, rhs: &HashSet<T, S>) -> HashSet<T, S> {
HashSet(self.0.bitxor(&rhs.0))
}
}
impl<T, S> Sub<&HashSet<T, S>> for &HashSet<T, S>
where
for<'a> &'a hb::HashSet<T, S>: Sub<&'a hb::HashSet<T, S>, Output = hb::HashSet<T, S>>,
{
type Output = HashSet<T, S>;
#[inline]
fn sub(self, rhs: &HashSet<T, S>) -> HashSet<T, S> {
HashSet(self.0.sub(&rhs.0))
}
}
impl<T, S> BitOrAssign<&HashSet<T, S>> for HashSet<T, S>
where
hb::HashSet<T, S>: for<'a> BitOrAssign<&'a hb::HashSet<T, S>>,
{
#[inline]
fn bitor_assign(&mut self, rhs: &HashSet<T, S>) {
self.0.bitor_assign(&rhs.0);
}
}
impl<T, S> BitAndAssign<&HashSet<T, S>> for HashSet<T, S>
where
hb::HashSet<T, S>: for<'a> BitAndAssign<&'a hb::HashSet<T, S>>,
{
#[inline]
fn bitand_assign(&mut self, rhs: &HashSet<T, S>) {
self.0.bitand_assign(&rhs.0);
}
}
impl<T, S> BitXorAssign<&HashSet<T, S>> for HashSet<T, S>
where
hb::HashSet<T, S>: for<'a> BitXorAssign<&'a hb::HashSet<T, S>>,
{
#[inline]
fn bitxor_assign(&mut self, rhs: &HashSet<T, S>) {
self.0.bitxor_assign(&rhs.0);
}
}
impl<T, S> SubAssign<&HashSet<T, S>> for HashSet<T, S>
where
hb::HashSet<T, S>: for<'a> SubAssign<&'a hb::HashSet<T, S>>,
{
#[inline]
fn sub_assign(&mut self, rhs: &HashSet<T, S>) {
self.0.sub_assign(&rhs.0);
}
}