Skip to content

Instantly share code, notes, and snippets.

@Ratysz
Created December 7, 2020 08:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Ratysz/6c593581ac5a24003651a9d02a38a37b to your computer and use it in GitHub Desktop.
Save Ratysz/6c593581ac5a24003651a9d02a38a37b to your computer and use it in GitHub Desktop.
use std::{
any::Any,
collections::{hash_map::RandomState, HashMap},
fmt::{Debug, Formatter, Result as FmtResult},
hash::{BuildHasher, Hash, Hasher},
};
trait DynEq: Any {
fn as_any(&self) -> &dyn Any;
fn dyn_eq(&self, other: &dyn DynEq) -> bool;
}
impl<T> DynEq for T
where
T: Any + Eq,
{
fn as_any(&self) -> &dyn Any {
self
}
fn dyn_eq(&self, other: &dyn DynEq) -> bool {
if let Some(other) = other.as_any().downcast_ref::<T>() {
return self == other;
}
false
}
}
trait DynHash: DynEq {
fn as_dyn_eq(&self) -> &dyn DynEq;
fn dyn_hash(&self, state: &mut dyn Hasher);
}
impl<T> DynHash for T
where
T: DynEq + Hash,
{
fn as_dyn_eq(&self) -> &dyn DynEq {
self
}
fn dyn_hash(&self, mut state: &mut dyn Hasher) {
T::hash(self, &mut state);
self.type_id().hash(&mut state);
}
}
impl PartialEq for dyn DynHash {
fn eq(&self, other: &dyn DynHash) -> bool {
self.dyn_eq(other.as_dyn_eq())
}
}
impl Eq for dyn DynHash {}
impl Hash for dyn DynHash {
fn hash<H: Hasher>(&self, state: &mut H) {
self.dyn_hash(state);
}
}
trait AnyKey: DynHash + Debug {}
impl<T> AnyKey for T where T: DynHash + Debug {}
impl PartialEq for dyn AnyKey {
fn eq(&self, other: &Self) -> bool {
self.dyn_eq(other.as_dyn_eq())
}
}
impl Eq for dyn AnyKey {}
impl Hash for dyn AnyKey {
fn hash<H: Hasher>(&self, state: &mut H) {
self.dyn_hash(state);
}
}
pub struct AnyKeyHashMap<V, S = RandomState> {
inner: HashMap<Box<dyn AnyKey>, V, S>,
}
impl<V, S> Default for AnyKeyHashMap<V, S>
where
S: Default,
{
fn default() -> Self {
Self {
inner: Default::default(),
}
}
}
impl<V> AnyKeyHashMap<V, RandomState> {
pub fn new() -> Self {
Self::default()
}
pub fn with_capacity(capacity: usize) -> Self {
Self {
inner: HashMap::with_capacity(capacity),
}
}
}
impl<V, S> AnyKeyHashMap<V, S>
where
S: BuildHasher,
{
pub fn with_hasher(hash_builder: S) -> Self {
Self {
inner: HashMap::with_hasher(hash_builder),
}
}
pub fn with_capacity_and_hasher(capacity: usize, hash_builder: S) -> Self {
Self {
inner: HashMap::with_capacity_and_hasher(capacity, hash_builder),
}
}
pub fn debug_iter(&self) -> impl Iterator<Item = (&dyn Debug, &V)> {
self.inner
.iter()
.map(|(key, value)| (key as &dyn Debug, value))
}
pub fn values_mut(&mut self) -> impl Iterator<Item = &mut V> {
self.inner.values_mut()
}
pub fn get(&self, key: &(impl Any + Eq + Hash + Debug)) -> Option<&V> {
self.inner.get(key as &dyn AnyKey)
}
pub fn contains_key(&self, key: &(impl Any + Eq + Hash + Debug)) -> bool {
self.inner.contains_key(key as &dyn AnyKey)
}
pub fn insert(&mut self, key: impl Any + Eq + Hash + Debug, value: V) -> Option<V> {
self.inner.insert(Box::new(key) as Box<dyn AnyKey>, value)
}
pub fn remove(&mut self, key: &(impl Any + Eq + Hash + Debug)) -> Option<V> {
self.inner.remove(key as &dyn AnyKey)
}
}
impl<V, S> Debug for AnyKeyHashMap<V, S>
where
V: Debug,
S: BuildHasher,
{
fn fmt(&self, f: &mut Formatter) -> FmtResult {
self.inner.fmt(f)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment