use std::collections::hash_map::RandomState;
use std::fmt::Formatter;
use std::hash::BuildHasher;
use std::marker::PhantomData;
use std::ops::Deref;
use std::{fmt::Debug, ops::DerefMut};
use dashmap::DashMap;
use crate::bounds::{Bounds, HasBounds, SyncAnyBounds};
use crate::dashentry;
use crate::hashmap::TypedKeyValue;
use crate::typedkey::{Key, TypedKey, TypedKeyRef};
use crate::typedvalue::TypedMapValue;
use crate::TypedMapKey;
pub struct TypedDashMap<
Marker = (),
KB: Bounds = SyncAnyBounds,
VB: Bounds = SyncAnyBounds,
S = RandomState,
> {
state: DashMap<TypedKey<KB>, TypedMapValue<VB>, S>,
_phantom: 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, KB, VB> TypedDashMap<Marker, KB, VB>
where
KB: 'static + Bounds,
VB: 'static + Bounds,
{
pub fn new_with_bounds() -> Self {
TypedDashMap {
state: Default::default(),
_phantom: PhantomData,
}
}
}
impl<Marker, KB, VB, S> TypedDashMap<Marker, KB, VB, S>
where
S: 'static + BuildHasher + Clone,
KB: 'static + Bounds,
VB: 'static + Bounds,
{
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>(&self, key: K, value: K::Value) -> Option<K::Value>
where
K: 'static + TypedMapKey<Marker>,
KB: HasBounds<K>,
VB: HasBounds<K::Value>,
{
let typed_key = TypedKey::<KB>::from_key(key);
let value = TypedMapValue::<VB>::from_value(value);
let old_value = self.state.insert(typed_key, value)?;
Some(old_value.downcast::<K::Value>().expect(INVALID_VALUE))
}
pub fn insert_key_value(
&mut self,
key_value: TypedKeyValue<Marker, KB, VB>,
) -> Option<TypedKeyValue<Marker, KB, VB>> {
let entry = self.state.remove(&key_value.key);
self.state.insert(key_value.key, key_value.value);
let (key, value) = entry?;
Some(TypedKeyValue {
key,
value,
_marker: PhantomData,
})
}
pub fn get<K>(&self, key: &K) -> Option<Ref<'_, Marker, K, KB, VB>>
where
K: 'static + TypedMapKey<Marker>,
KB: HasBounds<K>,
VB: HasBounds<K::Value>,
{
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>(&self, key: &K) -> Option<RefMut<'_, Marker, K, KB, VB>>
where
K: 'static + TypedMapKey<Marker>,
KB: HasBounds<K>,
VB: HasBounds<K::Value>,
{
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>(&self, key: &K) -> bool
where
K: 'static + TypedMapKey<Marker>,
KB: HasBounds<K>,
{
let typed_key = TypedKeyRef::from_key_ref(key);
self.state.contains_key(&typed_key as &dyn Key)
}
pub fn remove<K>(&self, key: &K) -> Option<(K, K::Value)>
where
K: 'static + TypedMapKey<Marker>,
KB: HasBounds<K>,
VB: HasBounds<K::Value>,
{
let typed_key = TypedKeyRef::from_key_ref(key);
let (key, value) = self.state.remove(&typed_key as &dyn Key)?;
let key = key.downcast().expect(INVALID_KEY);
let value = value.downcast().expect(INVALID_VALUE);
Some((key, value))
}
pub fn remove_if<K>(
&self,
key: &K,
f: impl FnOnce(&K, &K::Value) -> bool,
) -> Option<(K, K::Value)>
where
K: 'static + TypedMapKey<Marker>,
KB: HasBounds<K>,
VB: HasBounds<K::Value>,
{
let typed_key = TypedKeyRef::from_key_ref(key);
let f = move |typed_key: &TypedKey<KB>, typed_value: &TypedMapValue<VB>| {
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().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, KB, VB, S> {
Iter(self.state.iter(), PhantomData)
}
pub fn iter_mut(&self) -> IterMut<'_, Marker, KB, VB, S> {
IterMut(self.state.iter_mut(), PhantomData)
}
pub fn entry<K>(&self, key: K) -> dashentry::Entry<'_, K, KB, VB, Marker>
where
K: 'static + TypedMapKey<Marker>,
KB: HasBounds<K>,
VB: HasBounds<K::Value>,
{
let typed_key = TypedKey::from_key(key);
dashentry::map_entry(self.state.entry(typed_key))
}
pub fn retain(&self, mut predicate: impl FnMut(TypedKeyValueRef<Marker, KB, VB>) -> bool) {
let ff = move |key: &TypedKey<KB>, value: &mut TypedMapValue<VB>| {
let kv = TypedKeyValueRef {
key,
value,
_marker: PhantomData,
};
predicate(kv)
};
self.state.retain(ff);
}
}
impl<Marker> Default for TypedDashMap<Marker> {
fn default() -> Self {
TypedDashMap::new()
}
}
impl<Marker, KB, VB, S> Debug for TypedDashMap<Marker, KB, VB, S>
where
KB: 'static + Bounds,
VB: 'static + Bounds,
{
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.write_str("TypedDashMap:40")
}
}
pub struct Iter<'a, Marker, KB: 'static + Bounds, VB: 'static + Bounds, S>(
dashmap::iter::Iter<'a, TypedKey<KB>, TypedMapValue<VB>, S>,
PhantomData<Marker>,
);
impl<'a, Marker, KB, VB, S> Iterator for Iter<'a, Marker, KB, VB, S>
where
KB: 'static + Bounds,
VB: 'static + Bounds,
S: BuildHasher + Clone,
{
type Item = TypedKeyValueGuard<'a, Marker, KB, VB>;
fn next(&mut self) -> Option<Self::Item> {
let key_value = self.0.next()?;
Some(TypedKeyValueGuard {
key_value,
_marker: PhantomData,
})
}
}
pub struct TypedKeyValueGuard<'a, Marker, KB: 'static + Bounds, VB: 'static + Bounds> {
key_value: dashmap::mapref::multiple::RefMulti<'a, TypedKey<KB>, TypedMapValue<VB>>,
_marker: PhantomData<Marker>,
}
impl<Marker, KB, VB> TypedKeyValueGuard<'_, Marker, KB, VB>
where
KB: 'static + Bounds,
VB: 'static + Bounds,
{
pub fn downcast_key_ref<K: 'static + TypedMapKey<Marker>>(&self) -> Option<&'_ K>
where
KB: HasBounds<K>,
{
self.key_value.key().downcast_ref()
}
pub fn downcast_value_ref<V: 'static>(&self) -> Option<&'_ V>
where
VB: HasBounds<V>,
{
self.key_value.value().downcast_ref()
}
pub fn downcast_pair_ref<K>(&self) -> Option<(&'_ K, &'_ K::Value)>
where
K: 'static + TypedMapKey<Marker>,
KB: HasBounds<K>,
VB: HasBounds<K::Value>,
{
let (key, value) = self.key_value.pair();
Some((key.downcast_ref()?, value.downcast_ref()?))
}
pub fn key_container_ref(&self) -> &KB::Container {
self.key_value.key().as_container()
}
pub fn value_container_ref(&self) -> &VB::Container {
self.key_value.value().as_container()
}
}
#[cfg(feature = "clone")]
impl<M, KB: Bounds, VB: Bounds> TypedKeyValueGuard<'_, M, KB, VB>
where
KB::KeyContainer: crate::clone::CloneAny,
VB::Container: crate::clone::CloneAny,
{
pub fn to_owned(&self) -> TypedKeyValue<M, KB, VB> {
let key = crate::clone::clone_box(&*self.key_value.key().0);
let value = crate::clone::clone_box(self.key_value.value().as_container());
TypedKeyValue {
key: TypedKey(key),
value: TypedMapValue(value),
_marker: self._marker,
}
}
}
impl<M, KB: Bounds, VB: Bounds, S: BuildHasher + Clone + Default>
FromIterator<TypedKeyValue<M, KB, VB>> for TypedDashMap<M, KB, VB, S>
{
fn from_iter<T: IntoIterator<Item = TypedKeyValue<M, KB, VB>>>(iter: T) -> Self {
let state = iter.into_iter().map(|i| (i.key, i.value)).collect();
TypedDashMap {
state,
_phantom: PhantomData,
}
}
}
pub struct IterMut<'a, Marker, KB: 'static + Bounds, VB: 'static + Bounds, S>(
dashmap::iter::IterMut<'a, TypedKey<KB>, TypedMapValue<VB>, S>,
PhantomData<Marker>,
);
impl<'a, Marker, KB, VB, S> Iterator for IterMut<'a, Marker, KB, VB, S>
where
KB: 'static + Bounds,
VB: 'static + Bounds,
S: BuildHasher + Clone,
{
type Item = TypedKeyValueMutGuard<'a, Marker, KB, VB>;
fn next(&mut self) -> Option<Self::Item> {
let key_value = self.0.next()?;
Some(TypedKeyValueMutGuard {
key_value,
_marker: PhantomData,
})
}
}
pub struct TypedKeyValueMutGuard<'a, Marker, KB: 'static + Bounds, VB: 'static + Bounds> {
key_value: dashmap::mapref::multiple::RefMutMulti<'a, TypedKey<KB>, TypedMapValue<VB>>,
_marker: PhantomData<Marker>,
}
impl<Marker, KB, VB> TypedKeyValueMutGuard<'_, Marker, KB, VB>
where
KB: 'static + Bounds,
VB: 'static + Bounds,
{
pub fn downcast_key_ref<K: 'static + TypedMapKey<Marker>>(&self) -> Option<&'_ K>
where
KB: HasBounds<K>,
{
self.key_value.key().downcast_ref()
}
pub fn downcast_value_ref<V: 'static>(&self) -> Option<&'_ V>
where
VB: HasBounds<V>,
{
self.key_value.value().downcast_ref()
}
pub fn downcast_value_mut<V: 'static>(&mut self) -> Option<&'_ mut V>
where
VB: HasBounds<V>,
{
self.key_value.value_mut().downcast_mut()
}
pub fn downcast_pair_ref<K>(&self) -> Option<(&'_ K, &'_ K::Value)>
where
K: 'static + TypedMapKey<Marker>,
KB: HasBounds<K>,
VB: HasBounds<K::Value>,
{
let (key, value) = self.key_value.pair();
Some((key.downcast_ref()?, value.downcast_ref()?))
}
pub fn downcast_pair_mut<K>(&mut self) -> Option<(&'_ K, &'_ mut K::Value)>
where
K: 'static + TypedMapKey<Marker>,
KB: HasBounds<K>,
VB: HasBounds<K::Value>,
{
let (key, value) = self.key_value.pair_mut();
Some((key.downcast_ref()?, value.downcast_mut()?))
}
pub fn key_container_ref(&self) -> &KB::Container {
self.key_value.key().as_container()
}
pub fn value_container_ref(&self) -> &VB::Container {
self.key_value.value().as_container()
}
pub fn value_container_mut(&mut self) -> &mut VB::Container {
self.key_value.value_mut().as_mut_container()
}
}
#[cfg(feature = "clone")]
impl<M, KB: Bounds, VB: Bounds> TypedKeyValueMutGuard<'_, M, KB, VB>
where
KB::KeyContainer: crate::clone::CloneAny,
VB::Container: crate::clone::CloneAny,
{
pub fn to_owned(&self) -> TypedKeyValue<M, KB, VB> {
let key = crate::clone::clone_box(&*self.key_value.key().0);
let value = crate::clone::clone_box(self.key_value.value().as_container());
TypedKeyValue {
key: TypedKey(key),
value: TypedMapValue(value),
_marker: self._marker,
}
}
}
pub struct Ref<'a, Marker, K, KB, VB>(
dashmap::mapref::one::Ref<'a, TypedKey<KB>, TypedMapValue<VB>>,
std::marker::PhantomData<K>,
std::marker::PhantomData<Marker>,
)
where
K: 'static + TypedMapKey<Marker>,
KB: 'static + Bounds + HasBounds<K>,
VB: 'static + Bounds + HasBounds<K::Value>;
impl<Marker, K, KB, VB> Ref<'_, Marker, K, KB, VB>
where
K: 'static + TypedMapKey<Marker>,
KB: 'static + Bounds + HasBounds<K>,
VB: 'static + Bounds + HasBounds<K::Value>,
{
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<Marker, K, KB, VB> Deref for Ref<'_, Marker, K, KB, VB>
where
K: 'static + TypedMapKey<Marker>,
KB: 'static + Bounds + HasBounds<K>,
VB: 'static + Bounds + HasBounds<K::Value>,
{
type Target = K::Value;
fn deref(&self) -> &K::Value {
self.value()
}
}
impl<Marker, K, KB, VB> Debug for Ref<'_, Marker, K, KB, VB>
where
K: 'static + TypedMapKey<Marker>,
KB: 'static + Bounds + HasBounds<K>,
VB: 'static + Bounds + HasBounds<K::Value>,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
f.write_str("Ref")
}
}
pub struct RefMut<'a, Marker, K, KB, VB>(
pub(crate) dashmap::mapref::one::RefMut<'a, TypedKey<KB>, TypedMapValue<VB>>,
pub(crate) PhantomData<K>,
pub(crate) PhantomData<Marker>,
)
where
K: 'static + TypedMapKey<Marker>,
KB: 'static + Bounds + HasBounds<K>,
VB: 'static + Bounds + HasBounds<K::Value>;
impl<Marker, K, KB, VB> RefMut<'_, Marker, K, KB, VB>
where
K: 'static + TypedMapKey<Marker>,
KB: 'static + Bounds + HasBounds<K>,
VB: 'static + Bounds + HasBounds<K::Value>,
{
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<Marker, K, KB, VB> Deref for RefMut<'_, Marker, K, KB, VB>
where
K: 'static + TypedMapKey<Marker>,
KB: 'static + Bounds + HasBounds<K>,
VB: 'static + Bounds + HasBounds<K::Value>,
{
type Target = K::Value;
fn deref(&self) -> &K::Value {
self.value()
}
}
impl<Marker, K, KB, VB> DerefMut for RefMut<'_, Marker, K, KB, VB>
where
K: 'static + TypedMapKey<Marker>,
KB: 'static + Bounds + HasBounds<K>,
VB: 'static + Bounds + HasBounds<K::Value>,
{
fn deref_mut(&mut self) -> &mut Self::Target {
self.value_mut()
}
}
impl<Marker, K, KB, VB> Debug for RefMut<'_, Marker, K, KB, VB>
where
K: 'static + TypedMapKey<Marker>,
KB: 'static + Bounds + HasBounds<K>,
VB: 'static + Bounds + HasBounds<K::Value>,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
f.write_str("RefMut")
}
}
pub struct TypedKeyValueRef<'a, Marker, KB: 'static + Bounds, VB: 'static + Bounds> {
key: &'a TypedKey<KB>,
value: &'a TypedMapValue<VB>,
_marker: PhantomData<Marker>,
}
impl<'a, Marker, KB: 'static + Bounds, VB: 'static + Bounds> TypedKeyValueRef<'a, Marker, KB, VB> {
pub fn downcast_key_ref<K: 'static + TypedMapKey<Marker>>(&self) -> Option<&'a K>
where
KB: HasBounds<K>,
{
self.key.downcast_ref()
}
pub fn downcast_value_ref<V: 'static>(&self) -> Option<&'a V>
where
VB: HasBounds<V>,
{
self.value.downcast_ref()
}
pub fn downcast_pair_ref<K>(&self) -> Option<(&'a K, &'a K::Value)>
where
K: 'static + TypedMapKey<Marker>,
KB: HasBounds<K>,
VB: HasBounds<K::Value>,
{
self.downcast_key_ref()
.and_then(move |key| self.downcast_value_ref().map(move |value| (key, value)))
}
pub fn key_container_ref(&self) -> &KB::Container {
self.key.as_container()
}
pub fn value_container_ref(&self) -> &VB::Container {
self.value.as_container()
}
}
#[cfg(test)]
mod tests {
use std::hash::Hash;
use std::sync::Arc;
use crate::TypedMapKey;
use crate::{SyncAnyBounds, TypedDashMap, TypedMap};
struct M;
impl TypedMapKey<M> for String {
type Value = String;
}
#[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()));
}
#[test]
fn test_from_iterator() {
let mut state: TypedMap<M, SyncAnyBounds, SyncAnyBounds> = TypedMap::new_with_bounds();
state.insert("key".to_owned(), "value".to_owned());
let new_map: TypedDashMap<M> = state.into_iter().collect();
assert_eq!(
new_map.get(&"key".to_owned()).unwrap().value(),
&"value".to_owned()
);
}
}