use core::hash::{BuildHasher, Hash, Hasher};
use kovan_map::{HashMap, HopscotchMap};
pub trait Map<K, V>: Send + Sync + 'static {
const NAME: &'static str;
fn with_capacity(capacity: usize) -> Self;
fn insert(&self, k: K, v: V) -> Option<V>;
fn insert_if_absent(&self, k: K, v: V) -> Option<V>;
fn get_or_insert(&self, k: K, v: V) -> V;
fn get(&self, k: &K) -> Option<V>;
fn contains_key(&self, k: &K) -> bool;
fn remove(&self, k: &K) -> Option<V>;
fn force_remove(&self, k: &K) -> Option<V>;
fn remove_if(&self, k: &K, pred: impl FnOnce(&V) -> bool) -> Option<V>;
fn compare_and_remove(&self, k: &K, expected: &V) -> Option<V>
where
V: PartialEq;
fn replace_if(&self, k: K, v: V, pred: impl FnOnce(&V) -> bool) -> Result<V, Option<V>>;
fn compare_and_swap(&self, k: K, expected: &V, v: V) -> Result<V, Option<V>>
where
V: PartialEq;
fn compute(&self, k: K, f: impl FnOnce(Option<&V>) -> Option<V>) -> Option<V>;
fn len(&self) -> usize;
fn clear(&self);
fn entries(&self) -> Vec<(K, V)>;
fn entries_by_fold(&self) -> Vec<(K, V)>;
}
macro_rules! impl_map {
($map:ident, $name:literal) => {
impl<K, V, S> Map<K, V> for $map<K, V, S>
where
K: Hash + Eq + Clone + Send + Sync + 'static,
V: Clone + Send + Sync + 'static,
S: BuildHasher + Default + Send + Sync + 'static,
{
const NAME: &'static str = $name;
fn with_capacity(capacity: usize) -> Self {
$map::with_capacity_and_hasher(capacity, S::default())
}
fn insert(&self, k: K, v: V) -> Option<V> {
$map::insert(self, k, v)
}
fn insert_if_absent(&self, k: K, v: V) -> Option<V> {
$map::insert_if_absent(self, k, v)
}
fn get_or_insert(&self, k: K, v: V) -> V {
$map::get_or_insert(self, k, v)
}
fn get(&self, k: &K) -> Option<V> {
$map::get(self, k)
}
fn contains_key(&self, k: &K) -> bool {
$map::contains_key(self, k)
}
fn remove(&self, k: &K) -> Option<V> {
$map::remove(self, k)
}
fn force_remove(&self, k: &K) -> Option<V> {
$map::force_remove(self, k)
}
fn remove_if(&self, k: &K, pred: impl FnOnce(&V) -> bool) -> Option<V> {
$map::remove_if(self, k, pred)
}
fn compare_and_remove(&self, k: &K, expected: &V) -> Option<V>
where
V: PartialEq,
{
$map::compare_and_remove(self, k, expected)
}
fn replace_if(
&self,
k: K,
v: V,
pred: impl FnOnce(&V) -> bool,
) -> Result<V, Option<V>> {
$map::replace_if(self, k, v, pred)
}
fn compare_and_swap(&self, k: K, expected: &V, v: V) -> Result<V, Option<V>>
where
V: PartialEq,
{
$map::compare_and_swap(self, k, expected, v)
}
fn compute(&self, k: K, f: impl FnOnce(Option<&V>) -> Option<V>) -> Option<V> {
$map::compute(self, k, f)
}
fn len(&self) -> usize {
$map::len(self)
}
fn clear(&self) {
$map::clear(self)
}
fn entries(&self) -> Vec<(K, V)> {
$map::iter(self).collect()
}
fn entries_by_fold(&self) -> Vec<(K, V)> {
let mut all = Vec::new();
$map::iter(self).for_each(|entry| all.push(entry));
all
}
}
};
}
impl_map!(HashMap, "HashMap");
impl_map!(HopscotchMap, "HopscotchMap");
#[derive(Clone, Copy, Default)]
pub struct Identity;
pub struct IdentityHasher(u64);
impl Hasher for IdentityHasher {
fn finish(&self) -> u64 {
self.0
}
fn write(&mut self, bytes: &[u8]) {
for b in bytes {
self.0 = (self.0 << 8) | u64::from(*b);
}
}
fn write_u64(&mut self, n: u64) {
self.0 = n;
}
}
impl BuildHasher for Identity {
type Hasher = IdentityHasher;
fn build_hasher(&self) -> IdentityHasher {
IdentityHasher(0)
}
}
pub struct ConstHasher;
impl Hasher for ConstHasher {
fn finish(&self) -> u64 {
7
}
fn write(&mut self, _: &[u8]) {}
}
#[derive(Clone, Copy, Default)]
pub struct Constant;
impl BuildHasher for Constant {
type Hasher = ConstHasher;
fn build_hasher(&self) -> ConstHasher {
ConstHasher
}
}
pub struct ShapedHasher<const SHAPE: u8>(u64);
impl<const SHAPE: u8> Hasher for ShapedHasher<SHAPE> {
fn finish(&self) -> u64 {
match SHAPE {
0 => self.0 / 16,
_ => self.0 / 16 * 64 + self.0 % 16,
}
}
fn write(&mut self, bytes: &[u8]) {
for b in bytes {
self.0 = (self.0 << 8) | u64::from(*b);
}
}
fn write_u64(&mut self, n: u64) {
self.0 = n;
}
}
#[derive(Clone, Copy, Default)]
pub struct Grouped;
impl BuildHasher for Grouped {
type Hasher = ShapedHasher<0>;
fn build_hasher(&self) -> ShapedHasher<0> {
ShapedHasher(0)
}
}
#[derive(Clone, Copy, Default)]
pub struct Clustered;
impl BuildHasher for Clustered {
type Hasher = ShapedHasher<1>;
fn build_hasher(&self) -> ShapedHasher<1> {
ShapedHasher(0)
}
}