use std::{borrow::Borrow, hash::Hash, ops::Deref};
use dashmap::DashMap;
use crate::Map;
pub struct RefVal<'a, K, V>(dashmap::mapref::one::Ref<'a, K, V>);
impl<'a, K, V> RefVal<'a, K, V>
where
K: Eq + Hash,
{
pub fn new(mapref: dashmap::mapref::one::Ref<'a, K, V>) -> Self {
Self(mapref)
}
}
impl<'a, K: Eq + Hash, V> Borrow<V> for RefVal<'a, K, V> {
fn borrow(&self) -> &V {
self.0.value()
}
}
impl<'a, K: Eq + Hash, V> AsRef<V> for RefVal<'a, K, V> {
fn as_ref(&self) -> &V {
self.0.value()
}
}
impl<'a, K: Eq + Hash, V> Deref for RefVal<'a, K, V> {
type Target = V;
fn deref(&self) -> &Self::Target {
self.0.value()
}
}
#[cfg(feature = "get_or_init_async")]
impl<K, V> crate::GetOrInitAsync for DashMap<K, V>
where
K: Eq + Hash + Send + Sync + 'static,
V: Send + Sync + 'static,
{
async fn get_or_init_async<'a, Q, E, Fut>(
&'a self,
key: &Q,
func: impl FnOnce(&Q) -> Fut,
) -> Result<Self::RefVal<'a>, E>
where
K: Borrow<Q>,
Q: ToOwned<Owned = K> + Hash + Eq + ?Sized,
Fut: std::future::Future<Output = Result<V, E>>,
{
if let Some(r) = DashMap::get(self, key) {
return Ok(RefVal::new(r));
}
let v = func(key).await?;
Ok(RefVal::new(
self.entry(key.to_owned()).or_insert(v).downgrade(),
))
}
}
#[cfg(feature = "get_or_init")]
impl<K, V> crate::GetOrInit for DashMap<K, V>
where
K: Eq + Hash + Send + Sync + 'static,
V: Send + Sync + 'static,
{
fn get_or_init<'a, Q, E>(
&'a self,
key: &Q,
func: impl FnOnce(&Q) -> Result<V, E>,
) -> Result<Self::RefVal<'a>, E>
where
K: Borrow<Q>,
Q: ToOwned<Owned = K> + Hash + Eq + ?Sized,
{
if let Some(r) = DashMap::get(self, key) {
return Ok(RefVal::new(r));
}
let v = func(key)?;
Ok(RefVal::new(
self.entry(key.to_owned()).or_insert(v).downgrade(),
))
}
}
impl<K, V> Map for DashMap<K, V>
where
K: Eq + Hash + Send + Sync + 'static,
V: Send + Sync + 'static,
{
type Key = K;
type Val = V;
type RefVal<'a> = RefVal<'a, K, V>;
fn clear(&self) {
self.clear();
}
fn insert(&self, key: Self::Key, val: Self::Val) {
self.insert(key, val);
}
fn get<'a, Q>(&'a self, key: &Q) -> Option<Self::RefVal<'a>>
where
K: Borrow<Q>,
Q: Hash + Eq + ?Sized,
{
let mapref = DashMap::get(self, key)?;
Some(RefVal::new(mapref))
}
}