use alloc::vec::Vec;
use core::marker::PhantomData;
use core::mem;
pub trait DenseHasher<K> {
fn hash(&self, key: &K) -> usize;
}
pub trait DenseEq<K> {
fn eq(&self, a: &K, b: &K) -> bool;
}
#[derive(Clone, Copy)]
pub struct DenseEqDefault<K>(PhantomData<K>);
impl<K> Default for DenseEqDefault<K> {
fn default() -> Self {
DenseEqDefault(PhantomData)
}
}
impl<K: PartialEq> DenseEq<K> for DenseEqDefault<K> {
fn eq(&self, a: &K, b: &K) -> bool {
a == b
}
}
pub trait DenseDefault {
fn dense_default() -> Self;
}
impl<T> DenseDefault for *mut T {
fn dense_default() -> Self {
core::ptr::null_mut()
}
}
impl<T> DenseDefault for *const T {
fn dense_default() -> Self {
core::ptr::null()
}
}
macro_rules! dense_default_via_default {
($($t:ty),* $(,)?) => {
$(
impl DenseDefault for $t {
fn dense_default() -> Self {
<$t as Default>::default()
}
}
)*
};
}
dense_default_via_default!(
bool, i8, i16, i32, i64, isize, u8, u16, u32, u64, usize, f32, f64, char,
);
impl DenseDefault for alloc::string::String {
fn dense_default() -> Self {
alloc::string::String::new()
}
}
impl<T> DenseDefault for alloc::vec::Vec<T> {
fn dense_default() -> Self {
alloc::vec::Vec::new()
}
}
impl<K: Ord, V> DenseDefault for alloc::collections::BTreeMap<K, V> {
fn dense_default() -> Self {
alloc::collections::BTreeMap::new()
}
}
impl<T: Ord> DenseDefault for alloc::collections::BTreeSet<T> {
fn dense_default() -> Self {
alloc::collections::BTreeSet::new()
}
}
impl<T> DenseDefault for Option<T> {
fn dense_default() -> Self {
None
}
}
impl<A: DenseDefault, B: DenseDefault> DenseDefault for (A, B) {
fn dense_default() -> Self {
(A::dense_default(), B::dense_default())
}
}
pub trait ItemInterface<K, I> {
fn get_key(item: &I) -> &K;
fn set_key(item: &mut I, key: K);
fn make_empty(empty_key: &K) -> I;
}
pub struct ItemInterfaceSet<K>(PhantomData<K>);
impl<K: Clone> ItemInterface<K, K> for ItemInterfaceSet<K> {
fn get_key(item: &K) -> &K {
item
}
fn set_key(item: &mut K, key: K) {
*item = key;
}
fn make_empty(empty_key: &K) -> K {
empty_key.clone()
}
}
pub struct ItemInterfaceMap<K, V>(PhantomData<(K, V)>);
impl<K: Clone, V: DenseDefault> ItemInterface<K, (K, V)> for ItemInterfaceMap<K, V> {
fn get_key(item: &(K, V)) -> &K {
&item.0
}
fn set_key(item: &mut (K, V), key: K) {
item.0 = key;
}
fn make_empty(empty_key: &K) -> (K, V) {
(empty_key.clone(), V::dense_default())
}
}
pub struct DenseHashTable<K, I, Iface, H, E> {
pub(crate) data: Vec<I>,
pub(crate) capacity: usize,
pub(crate) count: usize,
pub(crate) empty_key: K,
pub(crate) hasher: H,
pub(crate) eq: E,
pub(crate) _iface: PhantomData<Iface>,
}
impl<K: Clone, I: Clone, Iface, H: Clone, E: Clone> Clone for DenseHashTable<K, I, Iface, H, E> {
fn clone(&self) -> Self {
Self {
data: self.data.clone(),
capacity: self.capacity,
count: self.count,
empty_key: self.empty_key.clone(),
hasher: self.hasher.clone(),
eq: self.eq.clone(),
_iface: PhantomData,
}
}
}
impl<K: core::fmt::Debug, I: core::fmt::Debug, Iface, H, E> core::fmt::Debug
for DenseHashTable<K, I, Iface, H, E>
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("DenseHashTable")
.field("data", &self.data)
.field("capacity", &self.capacity)
.field("count", &self.count)
.field("empty_key", &self.empty_key)
.finish_non_exhaustive()
}
}
impl<K, I, Iface, H, E> DenseHashTable<K, I, Iface, H, E>
where
K: Clone,
Iface: ItemInterface<K, I>,
H: DenseHasher<K> + Default,
E: DenseEq<K> + Default,
{
pub fn new(empty_key: K, buckets: usize) -> Self {
let eq = E::default();
debug_assert!(eq.eq(&empty_key, &empty_key));
debug_assert!(buckets & buckets.wrapping_sub(1) == 0);
let data = if buckets > 0 {
(0..buckets)
.map(|_| Iface::make_empty(&empty_key))
.collect()
} else {
Vec::new()
};
DenseHashTable {
data,
capacity: buckets,
count: 0,
empty_key,
hasher: H::default(),
eq,
_iface: PhantomData,
}
}
pub(crate) fn insert_unsafe(&mut self, key: K) -> usize {
debug_assert!(!self.eq.eq(&key, &self.empty_key));
let hashmod = self.capacity - 1;
let mut bucket = self.hasher.hash(&key) & hashmod;
for probe in 0..=hashmod {
if self
.eq
.eq(Iface::get_key(&self.data[bucket]), &self.empty_key)
{
Iface::set_key(&mut self.data[bucket], key);
self.count += 1;
return bucket;
}
if self.eq.eq(Iface::get_key(&self.data[bucket]), &key) {
return bucket;
}
bucket = (bucket + probe + 1) & hashmod;
}
let occupied = self
.data
.iter()
.filter(|item| !self.eq.eq(Iface::get_key(item), &self.empty_key))
.count();
unreachable!(
"dense hash table is full: capacity={}, count={}, occupied={}",
self.capacity, self.count, occupied
);
}
pub(crate) fn find(&self, key: &K) -> Option<usize> {
if self.count == 0 {
return None;
}
if self.eq.eq(key, &self.empty_key) {
return None;
}
let hashmod = self.capacity - 1;
let mut bucket = self.hasher.hash(key) & hashmod;
for probe in 0..=hashmod {
let k = Iface::get_key(&self.data[bucket]);
if self.eq.eq(k, key) {
return Some(bucket);
}
if self.eq.eq(k, &self.empty_key) {
return None;
}
bucket = (bucket + probe + 1) & hashmod;
}
let occupied = self
.data
.iter()
.filter(|item| !self.eq.eq(Iface::get_key(item), &self.empty_key))
.count();
unreachable!(
"dense hash table is full: capacity={}, count={}, occupied={}",
self.capacity, self.count, occupied
);
}
pub(crate) fn rehash(&mut self) {
let newsize = if self.capacity == 0 {
16
} else {
self.capacity * 2
};
let mut newtable = Self::new(self.empty_key.clone(), newsize);
for i in 0..self.capacity {
if !self.eq.eq(Iface::get_key(&self.data[i]), &self.empty_key) {
let key = Iface::get_key(&self.data[i]).clone();
let idx = newtable.insert_unsafe(key);
newtable.data[idx] =
mem::replace(&mut self.data[i], Iface::make_empty(&self.empty_key));
}
}
debug_assert_eq!(self.count, newtable.count);
mem::swap(&mut self.data, &mut newtable.data);
mem::swap(&mut self.capacity, &mut newtable.capacity);
}
pub(crate) fn rehash_if_full(&mut self, key: &K) {
if self.count >= self.capacity * 3 / 4 && self.find(key).is_none() {
self.rehash();
}
}
pub(crate) fn clear(&mut self) {
if self.count == 0 {
return;
}
for slot in self.data.iter_mut() {
*slot = Iface::make_empty(&self.empty_key);
}
self.count = 0;
}
pub(crate) fn size(&self) -> usize {
self.count
}
pub(crate) fn first_occupied(&self) -> usize {
let mut start = 0;
while start < self.capacity
&& self
.eq
.eq(Iface::get_key(&self.data[start]), &self.empty_key)
{
start += 1;
}
start
}
pub(crate) fn next_occupied(&self, mut index: usize) -> usize {
loop {
index += 1;
if index >= self.capacity
|| !self
.eq
.eq(Iface::get_key(&self.data[index]), &self.empty_key)
{
break;
}
}
index
}
}