use std::any::Any;
use std::hash::BuildHasher;
use std::marker::PhantomData;
use std::ops::Deref;
use std::{fmt::Debug, ops::DerefMut};
use dashmap::DashMap;
use crate::dashentry;
use crate::typedkey::{Key, SyncTypedKey, TypedKeyRef};
use crate::typedvalue::SyncTypedMapValue;
use crate::TypedMapKey;
use std::collections::hash_map::RandomState;
pub struct TypedDashMap<Marker = (), S = RandomState> {
state: DashMap<SyncTypedKey, SyncTypedMapValue, S>,
_phantom: std::marker::PhantomData<Marker>,
}
const INVALID_KEY: &str = "Broken TypedDashMap: invalid key type";
const INVALID_VALUE: &str = "Broken TypedDashMap: invalid value type";
impl<Marker> TypedDashMap<Marker> {
pub fn new() -> Self {
TypedDashMap {
state: Default::default(),
_phantom: PhantomData,
}
}
pub fn with_capacity(capacity: usize) -> Self {
TypedDashMap {
state: DashMap::with_capacity(capacity),
_phantom: PhantomData,
}
}
}
impl<Marker, S> TypedDashMap<Marker, S>
where
S: 'static + BuildHasher + Clone,
{
pub fn with_capacity_and_hasher(capacity: usize, hash_builder: S) -> Self {
TypedDashMap {
state: DashMap::with_capacity_and_hasher(capacity, hash_builder),
_phantom: PhantomData,
}
}
pub fn with_hasher(hash_builder: S) -> Self {
TypedDashMap {
state: DashMap::with_hasher(hash_builder),
_phantom: PhantomData,
}
}
pub fn insert<K: 'static + TypedMapKey<Marker> + Send + Sync>(
&self,
key: K,
value: K::Value,
) -> Option<K::Value>
where
K::Value: Send + Sync,
{
let typed_key = SyncTypedKey::from_key(key);
let value = SyncTypedMapValue::from_value(value);
let old_value = self.state.insert(typed_key, value)?;
Some(old_value.downcast::<K::Value>().expect(INVALID_VALUE))
}
pub fn get<K: 'static + TypedMapKey<Marker> + Send + Sync>(
&self,
key: &K,
) -> Option<Ref<'_, Marker, K, S>>
where
K::Value: Send + Sync,
{
let typed_key = TypedKeyRef::from_key_ref(key);
let value = self.state.get(&typed_key as &dyn Key)?;
Some(Ref(
value,
std::marker::PhantomData,
std::marker::PhantomData,
))
}
pub fn get_mut<K: 'static + TypedMapKey<Marker> + Send + Sync>(
&self,
key: &K,
) -> Option<RefMut<'_, Marker, K, S>>
where
K::Value: Send + Sync,
{
let typed_key = TypedKeyRef::from_key_ref(key);
let value = self.state.get_mut(&typed_key as &dyn Key)?;
Some(RefMut(
value,
std::marker::PhantomData,
std::marker::PhantomData,
))
}
pub fn contains_key<K: 'static + TypedMapKey<Marker> + Send + Sync>(&self, key: &K) -> bool
where
K::Value: Send + Sync,
{
let typed_key = TypedKeyRef::from_key_ref(key);
self.state.contains_key(&typed_key as &dyn Key)
}
pub fn remove<K: 'static + TypedMapKey<Marker> + Send + Sync>(
&self,
key: &K,
) -> Option<(K, K::Value)>
where
K::Value: Send + Sync,
{
let typed_key = TypedKeyRef::from_key_ref(key);
let (key, value) = self.state.remove(&typed_key as &dyn Key)?;
let key = key.downcast().ok().expect(INVALID_KEY);
let value = value.downcast().expect(INVALID_VALUE);
Some((key, value))
}
pub fn remove_if<K: 'static + TypedMapKey<Marker> + Send + Sync>(
&self,
key: &K,
f: impl FnOnce(&K, &K::Value) -> bool,
) -> Option<(K, K::Value)>
where
K::Value: Send + Sync,
{
let typed_key = TypedKeyRef::from_key_ref(key);
let f = move |typed_key: &SyncTypedKey, typed_value: &SyncTypedMapValue| {
let k = typed_key.downcast_ref().expect(INVALID_KEY);
let v = typed_value.downcast_ref().expect(INVALID_VALUE);
f(k, v)
};
let (key, value) = self.state.remove_if(&typed_key as &dyn Key, f)?;
let key = key.downcast().ok().expect(INVALID_KEY);
let value = value.downcast().expect(INVALID_VALUE);
Some((key, value))
}
pub fn len(&self) -> usize {
self.state.len()
}
pub fn is_empty(&self) -> bool {
self.state.is_empty()
}
pub fn clear(&self) {
self.state.clear();
}
pub fn iter(&self) -> Iter<'_, Marker, S> {
Iter(self.state.iter(), PhantomData)
}
pub fn entry<K: 'static + TypedMapKey<Marker> + Send + Sync>(
&mut self,
key: K,
) -> dashentry::Entry<'_, K, Marker, S>
where
K::Value: Send + Sync,
{
let typed_key = SyncTypedKey::from_key(key);
dashentry::map_entry(self.state.entry(typed_key))
}
pub fn retain(&self, mut predicate: impl FnMut(TypedKeyValueRef<Marker>) -> bool) {
let ff = move |key: &SyncTypedKey, value: &mut SyncTypedMapValue| {
let kv = TypedKeyValueRef {
key,
value,
_marker: PhantomData,
};
predicate(kv)
};
self.state.retain(ff);
}
}
impl<Marker> Default for TypedDashMap<Marker> {
fn default() -> Self {
TypedDashMap::new()
}
}
pub struct Iter<'a, Marker, S>(
dashmap::iter::Iter<'a, SyncTypedKey, SyncTypedMapValue, S>,
PhantomData<Marker>,
);
impl<'a, Marker, S: BuildHasher + Clone> Iterator for Iter<'a, Marker, S> {
type Item = TypedKeyValueGuard<'a, Marker, S>;
fn next(&mut self) -> Option<Self::Item> {
let key_value = self.0.next()?;
Some(TypedKeyValueGuard {
key_value,
_marker: PhantomData,
})
}
}
pub struct TypedKeyValueGuard<'a, Marker, S> {
key_value: dashmap::mapref::multiple::RefMulti<'a, SyncTypedKey, SyncTypedMapValue, S>,
_marker: PhantomData<Marker>,
}
impl<'a, Marker, S: BuildHasher> TypedKeyValueGuard<'a, Marker, S> {
pub fn downcast_key_ref<K: 'static + TypedMapKey<Marker>>(&self) -> Option<&'_ K> {
self.key_value.key().downcast_ref()
}
pub fn downcast_value_ref<V: 'static + Any>(&self) -> Option<&'_ V> {
self.key_value.value().downcast_ref()
}
pub fn downcast_pair_ref<K: 'static + TypedMapKey<Marker>>(
&self,
) -> Option<(&'_ K, &'_ K::Value)> {
let (key, value) = self.key_value.pair();
Some((key.downcast_ref()?, value.downcast_ref()?))
}
}
pub struct Ref<'a, Marker, K: 'static + TypedMapKey<Marker>, S>(
dashmap::mapref::one::Ref<'a, SyncTypedKey, SyncTypedMapValue, S>,
std::marker::PhantomData<K>,
std::marker::PhantomData<Marker>,
);
impl<'a, Marker, K: 'static + TypedMapKey<Marker>, S: BuildHasher> Ref<'a, Marker, K, S> {
pub fn key(&self) -> &K {
self.0.key().downcast_ref::<K>().expect(INVALID_KEY)
}
pub fn value(&self) -> &K::Value {
self.0
.value()
.downcast_ref::<K::Value>()
.expect(INVALID_VALUE)
}
pub fn pair(&self) -> (&K, &K::Value) {
(self.key(), self.value())
}
}
impl<'a, Marker, K: TypedMapKey<Marker>, S: BuildHasher> Deref for Ref<'a, Marker, K, S> {
type Target = K::Value;
fn deref(&self) -> &K::Value {
self.value()
}
}
impl<'a, Marker, K: TypedMapKey<Marker>, S> Debug for Ref<'a, Marker, K, S> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
f.write_str("Ref")
}
}
pub struct RefMut<'a, Marker, K: 'static + TypedMapKey<Marker>, S>(
pub(crate) dashmap::mapref::one::RefMut<'a, SyncTypedKey, SyncTypedMapValue, S>,
pub(crate) std::marker::PhantomData<K>,
pub(crate) std::marker::PhantomData<Marker>,
);
impl<'a, Marker, K: 'static + TypedMapKey<Marker>, S: BuildHasher> RefMut<'a, Marker, K, S> {
pub fn key(&self) -> &K {
self.0.key().downcast_ref::<K>().expect(INVALID_KEY)
}
pub fn value(&self) -> &K::Value {
self.0
.value()
.downcast_ref::<K::Value>()
.expect(INVALID_VALUE)
}
pub fn value_mut(&mut self) -> &mut K::Value {
self.0
.value_mut()
.downcast_mut::<K::Value>()
.expect(INVALID_VALUE)
}
pub fn pair(&self) -> (&K, &K::Value) {
(self.key(), self.value())
}
pub fn pair_mut(&mut self) -> (&K, &K::Value) {
let (key, value) = self.0.pair_mut();
let key = key.downcast_ref::<K>().expect(INVALID_KEY);
let value = value.downcast_mut::<K::Value>().expect(INVALID_VALUE);
(key, value)
}
}
impl<'a, Marker, K: TypedMapKey<Marker>, S: BuildHasher> Deref for RefMut<'a, Marker, K, S> {
type Target = K::Value;
fn deref(&self) -> &K::Value {
self.value()
}
}
impl<'a, Marker, K: TypedMapKey<Marker>, S: BuildHasher> DerefMut for RefMut<'a, Marker, K, S> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.value_mut()
}
}
impl<'a, Marker, K: TypedMapKey<Marker>, S> Debug for RefMut<'a, Marker, K, S> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
f.write_str("RefMut")
}
}
pub struct TypedKeyValueRef<'a, Marker> {
key: &'a SyncTypedKey,
value: &'a SyncTypedMapValue,
_marker: PhantomData<Marker>,
}
impl<'a, Marker> TypedKeyValueRef<'a, Marker> {
pub fn downcast_key_ref<K: 'static + TypedMapKey<Marker>>(&self) -> Option<&'a K> {
self.key.downcast_ref()
}
pub fn downcast_value_ref<V: 'static + Any>(&self) -> Option<&'a V> {
self.value.downcast_ref()
}
pub fn downcast_pair_ref<K: 'static + TypedMapKey<Marker>>(
&self,
) -> Option<(&'a K, &'a K::Value)> {
self.downcast_key_ref()
.and_then(move |key| self.downcast_value_ref().map(move |value| (key, value)))
}
}
#[cfg(test)]
mod tests {
use crate::TypedDashMap;
use crate::TypedMapKey;
use std::hash::Hash;
use std::sync::Arc;
#[test]
fn test_threads() {
let map: Arc<TypedDashMap> = Arc::new(TypedDashMap::new());
#[derive(Debug, Hash, PartialEq, Eq)]
struct Key(String);
impl TypedMapKey for Key {
type Value = String;
}
let map1 = map.clone();
let th1 = std::thread::spawn(move || {
map1.insert(Key("k1".to_owned()), "v1".to_owned());
});
let map2 = map.clone();
let th2 = std::thread::spawn(move || {
map2.insert(Key("k2".to_owned()), "v2".to_owned());
});
th1.join().unwrap();
th2.join().unwrap();
let k1 = Key("k1".to_owned());
let k2 = Key("k2".to_owned());
let r = map.get(&k1).unwrap();
assert_eq!(r.key(), &k1);
assert_eq!(r.value(), &"v1".to_owned());
let r = map.get(&k2).unwrap();
assert_eq!(r.pair(), (&k2, &"v2".to_owned()));
}
}