use core::{
fmt,
hash::{BuildHasher, Hash},
mem,
ops::{BitAnd, BitOr, BitXor, Index, Sub},
};
#[cfg(feature = "std")]
use std::hash::RandomState;
use hashbrown::{hash_table, Equivalent};
use crate::{map::make_hasher, HashSlabMap, KeyData, TryReserveError, ValueData};
mod iter;
pub use iter::{
Difference, Drain, Intersection, IntoIter, Iter, IterFull, SymmetricDifference, Union,
};
#[cfg(test)]
mod tests;
#[cfg(feature = "std")]
pub struct HashSlabSet<T, S = RandomState> {
pub(crate) map: HashSlabMap<T, (), S>,
}
#[cfg(not(feature = "std"))]
pub struct HashSlabSet<T, S> {
pub(crate) map: HashSlabMap<T, (), S>,
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl<T> HashSlabSet<T> {
pub fn new() -> Self {
HashSlabSet {
map: HashSlabMap::new(),
}
}
pub fn with_capacity(n: usize) -> Self {
HashSlabSet {
map: HashSlabMap::with_capacity(n),
}
}
}
impl<T, S> HashSlabSet<T, S> {
pub fn with_capacity_and_hasher(n: usize, hash_builder: S) -> Self {
HashSlabSet {
map: HashSlabMap::with_capacity_and_hasher(n, hash_builder),
}
}
pub const fn with_hasher(hash_builder: S) -> Self {
HashSlabSet {
map: HashSlabMap::with_hasher(hash_builder),
}
}
pub fn capacity(&self) -> usize {
self.map.capacity()
}
pub fn hasher(&self) -> &S {
self.map.hasher()
}
pub fn len(&self) -> usize {
self.map.len()
}
pub fn is_empty(&self) -> bool {
self.map.is_empty()
}
pub fn iter(&self) -> Iter<'_, T> {
Iter::new(self.map.keys())
}
pub fn iter_full(&self) -> IterFull<'_, T> {
IterFull::new(self.map.full_keys())
}
pub fn drain(&mut self) -> Drain<'_, T> {
Drain::new(self.map.drain())
}
pub fn clear(&mut self) {
self.map.clear();
}
}
impl<T, S> HashSlabSet<T, S>
where
T: Hash + Eq,
S: BuildHasher,
{
pub fn shrink_to_fit(&mut self) {
self.map.shrink_to_fit();
}
pub fn reserve(&mut self, additional: usize) {
self.map.reserve(additional);
}
pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
self.map.try_reserve(additional)
}
pub fn insert(&mut self, value: T) -> bool {
self.map.insert(value, ()).is_none()
}
pub fn insert_full(&mut self, value: T) -> (usize, bool) {
let (index, existing) = self.map.insert_full(value, ());
(index, existing.is_none())
}
pub fn replace(&mut self, value: T) -> Option<T> {
self.replace_full(value).1
}
pub fn replace_full(&mut self, value: T) -> (usize, Option<T>) {
let hash = self.map.builder.hash_one(&value);
match self.map.table.entry(
hash,
|KeyData { key, .. }| key == &value,
make_hasher(&self.map.builder),
) {
hash_table::Entry::Occupied(mut occupied_entry) => {
let KeyData { ref mut key, index } = occupied_entry.get_mut();
(*index, Some(mem::replace(key, value)))
}
hash_table::Entry::Vacant(vacant_entry) => {
let index = self.map.slab.insert(ValueData::new((), hash));
vacant_entry.insert(KeyData::new(value, index));
(index, None)
}
}
}
pub fn difference<'a, S2>(&'a self, other: &'a HashSlabSet<T, S2>) -> Difference<'a, T, S2> {
Difference::new(self.iter(), other)
}
pub fn symmetric_difference<'a, S2>(
&'a self,
other: &'a HashSlabSet<T, S2>,
) -> SymmetricDifference<'a, T, S, S2>
where
S2: BuildHasher,
{
SymmetricDifference::new(self, other)
}
pub fn intersection<'a, S2>(&'a self, other: &'a HashSlabSet<T, S2>) -> Intersection<'a, T, S2>
where
S2: BuildHasher,
{
Intersection::new(self, other)
}
pub fn union<'a, S2>(&'a self, other: &'a HashSlabSet<T, S2>) -> Union<'a, T, S>
where
S2: BuildHasher,
{
Union::new(self, other)
}
pub fn append<S2>(&mut self, other: &mut HashSlabSet<T, S2>) {
self.map.append(&mut other.map);
}
pub fn remove<Q>(&mut self, value: &Q) -> bool
where
Q: Hash + Equivalent<T> + ?Sized,
{
self.remove_full(value).is_some()
}
pub fn remove_full<Q>(&mut self, value: &Q) -> Option<(usize, T)>
where
Q: ?Sized + Hash + Equivalent<T>,
{
self.map.remove_full(value).map(|(i, x, ())| (i, x))
}
pub fn remove_index(&mut self, index: usize) -> Option<T> {
self.map.remove_index(index).map(|(x, ())| x)
}
pub fn contains<Q>(&self, value: &Q) -> bool
where
Q: Hash + Equivalent<T> + ?Sized,
{
self.map.contains_key(value)
}
pub fn get<Q>(&self, value: &Q) -> Option<&T>
where
Q: ?Sized + Hash + Equivalent<T>,
{
self.map.get_key_value(value).map(|(x, &())| x)
}
pub fn get_full<Q>(&self, value: &Q) -> Option<(usize, &T)>
where
Q: ?Sized + Hash + Equivalent<T>,
{
self.map.get_full(value).map(|(i, x, &())| (i, x))
}
pub fn get_index_of<Q>(&self, value: &Q) -> Option<usize>
where
Q: ?Sized + Hash + Equivalent<T>,
{
self.map.get_index_of(value)
}
pub fn take<Q>(&mut self, value: &Q) -> Option<T>
where
Q: Hash + Equivalent<T> + ?Sized,
{
self.map.remove_entry(value).map(|(k, _)| k)
}
pub fn is_subset<S2>(&self, other: &HashSlabSet<T, S2>) -> bool
where
S2: BuildHasher,
{
self.len() <= other.len() && self.iter().all(move |value| other.contains(value))
}
pub fn is_disjoint<S2>(&self, other: &HashSlabSet<T, S2>) -> bool
where
S2: BuildHasher,
{
if self.len() <= other.len() {
self.iter().all(move |value| !other.contains(value))
} else {
other.iter().all(move |value| !self.contains(value))
}
}
pub fn is_superset<S2>(&self, other: &HashSlabSet<T, S2>) -> bool
where
S2: BuildHasher,
{
other.is_subset(self)
}
}
impl<T, S> HashSlabSet<T, S> {
pub fn retain<F>(&mut self, mut f: F)
where
F: FnMut(&T) -> bool,
{
self.map.retain(|k, _| f(k));
}
pub fn get_index(&self, index: usize) -> Option<&T> {
self.map.get_index(index).map(|(k, _)| k)
}
}
impl<T, S> fmt::Debug for HashSlabSet<T, S>
where
T: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_set().entries(self.iter()).finish()
}
}
impl<T, S> Clone for HashSlabSet<T, S>
where
T: Clone,
S: Clone,
{
fn clone(&self) -> Self {
HashSlabSet {
map: self.map.clone(),
}
}
fn clone_from(&mut self, other: &Self) {
self.map.clone_from(&other.map);
}
}
impl<T, S> Index<usize> for HashSlabSet<T, S> {
type Output = T;
fn index(&self, index: usize) -> &T {
self.get_index(index)
.expect("HashSlabSet: index out of bounds")
}
}
impl<T, S> FromIterator<T> for HashSlabSet<T, S>
where
T: Hash + Eq,
S: BuildHasher + Default,
{
fn from_iter<I: IntoIterator<Item = T>>(iterable: I) -> Self {
let iter = iterable.into_iter().map(|x| (x, ()));
HashSlabSet {
map: HashSlabMap::from_iter(iter),
}
}
}
#[cfg(feature = "std")]
#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
impl<T, const N: usize> From<[T; N]> for HashSlabSet<T, RandomState>
where
T: Eq + Hash,
{
fn from(arr: [T; N]) -> Self {
Self::from_iter(arr)
}
}
impl<T, S> Extend<T> for HashSlabSet<T, S>
where
T: Hash + Eq,
S: BuildHasher,
{
fn extend<I: IntoIterator<Item = T>>(&mut self, iterable: I) {
let iter = iterable.into_iter().map(|x| (x, ()));
self.map.extend(iter);
}
}
impl<'a, T, S> Extend<&'a T> for HashSlabSet<T, S>
where
T: Hash + Eq + Copy + 'a,
S: BuildHasher,
{
fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iterable: I) {
let iter = iterable.into_iter().copied();
self.extend(iter);
}
}
impl<T, S> Default for HashSlabSet<T, S>
where
S: Default,
{
fn default() -> Self {
HashSlabSet {
map: HashSlabMap::default(),
}
}
}
impl<T, S1, S2> PartialEq<HashSlabSet<T, S2>> for HashSlabSet<T, S1>
where
T: Hash + Eq,
S1: BuildHasher,
S2: BuildHasher,
{
fn eq(&self, other: &HashSlabSet<T, S2>) -> bool {
self.len() == other.len() && self.is_subset(other)
}
}
impl<T, S> Eq for HashSlabSet<T, S>
where
T: Eq + Hash,
S: BuildHasher,
{
}
impl<T, S1, S2> BitAnd<&HashSlabSet<T, S2>> for &HashSlabSet<T, S1>
where
T: Eq + Hash + Clone,
S1: BuildHasher + Default,
S2: BuildHasher,
{
type Output = HashSlabSet<T, S1>;
fn bitand(self, other: &HashSlabSet<T, S2>) -> Self::Output {
self.intersection(other).cloned().collect()
}
}
impl<T, S1, S2> BitOr<&HashSlabSet<T, S2>> for &HashSlabSet<T, S1>
where
T: Eq + Hash + Clone,
S1: BuildHasher + Default,
S2: BuildHasher,
{
type Output = HashSlabSet<T, S1>;
fn bitor(self, other: &HashSlabSet<T, S2>) -> Self::Output {
self.union(other).cloned().collect()
}
}
impl<T, S1, S2> BitXor<&HashSlabSet<T, S2>> for &HashSlabSet<T, S1>
where
T: Eq + Hash + Clone,
S1: BuildHasher + Default,
S2: BuildHasher,
{
type Output = HashSlabSet<T, S1>;
fn bitxor(self, other: &HashSlabSet<T, S2>) -> Self::Output {
self.symmetric_difference(other).cloned().collect()
}
}
impl<T, S1, S2> Sub<&HashSlabSet<T, S2>> for &HashSlabSet<T, S1>
where
T: Eq + Hash + Clone,
S1: BuildHasher + Default,
S2: BuildHasher,
{
type Output = HashSlabSet<T, S1>;
fn sub(self, other: &HashSlabSet<T, S2>) -> Self::Output {
self.difference(other).cloned().collect()
}
}
impl<T, S> From<HashSlabMap<T, (), S>> for HashSlabSet<T, S> {
fn from(map: HashSlabMap<T, (), S>) -> Self {
Self { map }
}
}