use std::borrow::Borrow;
use std::collections::{hash_map::RandomState, HashMap, HashSet};
use std::hash::{BuildHasher, BuildHasherDefault, Hash, Hasher};
use std::marker::PhantomData;
#[derive(Default)]
struct KnownHasher {
hash: Option<u64>,
}
impl Hasher for KnownHasher {
#[inline]
fn write(&mut self, _: &[u8]) {
panic!("KnownHasher must be called with known u64 hash values")
}
#[inline]
fn write_u64(&mut self, i: u64) {
debug_assert!(self.hash.is_none());
self.hash = Some(i);
}
#[inline]
fn finish(&self) -> u64 {
self.hash.expect("Nothing was hashed") as u64
}
}
#[derive(Copy, Clone, Hash, PartialEq, Eq)]
pub struct Trash(u64);
impl Trash {
pub fn get_hash(&self) -> u64 {
self.0
}
}
pub struct TrashMap<K: ?Sized, V, S = RandomState> {
hasher: S,
map: HashMap<Trash, V, BuildHasherDefault<KnownHasher>>,
key: PhantomData<*const K>,
}
impl<K: ?Sized, V, S> TrashMap<K, V, S>
where
K: Eq + Hash,
S: BuildHasher,
{
#[inline]
pub fn new() -> Self
where
S: Default,
{
Self {
hasher: Default::default(),
map: Default::default(),
key: PhantomData,
}
}
#[inline]
pub fn with_capacity_and_hasher(cap: usize, hasher: S) -> Self {
Self {
hasher,
map: HashMap::with_capacity_and_hasher(cap, Default::default()),
key: PhantomData,
}
}
#[inline]
pub fn insert<Q: ?Sized>(&mut self, k: &Q, v: V) -> Trash
where
K: Borrow<Q>,
Q: Hash + Eq,
{
let trash = self.trash(k);
self.map.insert(trash, v);
trash
}
#[inline]
pub fn insert_id(&mut self, k: Trash, v: V) -> Option<V>
{
self.map.insert(k, v)
}
#[inline]
pub fn insert_replace<Q: ?Sized>(&mut self, k: &Q, v: V) -> (Trash, Option<V>)
where
K: Borrow<Q>,
Q: Hash + Eq,
{
let trash = self.trash(k);
(trash, self.map.insert(trash, v))
}
#[inline]
pub fn get(&self, key: Trash) -> Option<&V> {
self.map.get(&key)
}
#[inline]
pub fn get_key<Q: ?Sized>(&self, key: &Q) -> Option<&V>
where
K: Borrow<Q>,
Q: Hash + Eq,
{
let trash = self.trash(key);
self.map.get(&trash)
}
#[inline]
pub fn remove(&mut self, key: Trash) -> Option<V> {
self.map.remove(&key)
}
#[inline]
pub fn remove_key<Q: ?Sized>(&mut self, key: &Q) -> Option<V>
where
K: Borrow<Q>,
Q: Hash + Eq,
{
let trash = self.trash(key);
self.map.remove(&trash)
}
#[inline]
pub fn trash<Q: ?Sized>(&self, k: &Q) -> Trash
where
K: Borrow<Q>,
Q: Hash + Eq,
{
let mut state = self.hasher.build_hasher();
k.hash(&mut state);
Trash(state.finish())
}
}
impl<K: ?Sized, V, S> Default for TrashMap<K, V, S>
where
K: Eq + Hash,
S: BuildHasher + Default,
{
fn default() -> Self {
Self::new()
}
}
pub struct TrashSet<K: ?Sized, S = RandomState> {
hasher: S,
set: HashSet<Trash, BuildHasherDefault<KnownHasher>>,
key: PhantomData<*const K>,
}
impl<K: ?Sized, S> TrashSet<K, S>
where
K: Eq + Hash,
S: BuildHasher,
{
#[inline]
pub fn new() -> Self
where
S: Default,
{
Self {
hasher: Default::default(),
set: Default::default(),
key: PhantomData,
}
}
#[inline]
pub fn with_capacity_and_hasher(cap: usize, hasher: S) -> Self {
Self {
hasher,
set: HashSet::with_capacity_and_hasher(cap, Default::default()),
key: PhantomData,
}
}
#[inline]
pub fn insert<Q: ?Sized>(&mut self, key: &Q) -> Trash
where
K: Borrow<Q>,
Q: Hash + Eq,
{
let trash = self.trash(key);
self.set.insert(trash);
trash
}
#[inline]
pub fn insert_check<Q: ?Sized>(&mut self, key: &Q) -> (Trash, bool)
where
K: Borrow<Q>,
Q: Hash + Eq,
{
let trash = self.trash(key);
(trash, self.set.insert(trash))
}
#[inline]
pub fn insert_id(&mut self, key: Trash) -> bool
{
self.set.insert(key)
}
#[inline]
pub fn contains(&self, key: Trash) -> bool {
self.set.contains(&key)
}
#[inline]
pub fn contains_key<Q: ?Sized>(&self, key: &Q) -> bool
where
K: Borrow<Q>,
Q: Hash + Eq,
{
let trash = self.trash(key);
self.set.contains(&trash)
}
#[inline]
pub fn remove(&mut self, key: Trash) -> bool {
self.set.remove(&key)
}
#[inline]
pub fn remove_key<Q: ?Sized>(&mut self, key: &Q) -> bool
where
K: Borrow<Q>,
Q: Hash + Eq,
{
self.set.remove(&self.trash(key))
}
#[inline]
pub fn trash<Q: ?Sized>(&self, k: &Q) -> Trash
where
K: Borrow<Q>,
Q: Hash + Eq,
{
let mut state = self.hasher.build_hasher();
k.hash(&mut state);
Trash(state.finish())
}
}
impl<K: ?Sized, S> Default for TrashSet<K, S>
where
K: Eq + Hash,
S: BuildHasher + Default,
{
fn default() -> Self {
Self::new()
}
}