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 len(&self) -> usize;
fn clear(&self);
fn entries(&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 len(&self) -> usize {
$map::len(self)
}
fn clear(&self) {
$map::clear(self)
}
fn entries(&self) -> Vec<(K, V)> {
$map::iter(self).collect()
}
}
};
}
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)
}
}