use crate::AsyncShardedHashMap;
use std::hash::{BuildHasher, Hash};
#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
pub enum AsyncEntry<'a, K, V, S>
where
K: Eq + Hash + Clone + Send + Sync + 'static,
V: Clone + Send + Sync + 'static,
S: BuildHasher + Clone + Send + Sync,
{
Occupied(AsyncOccupiedEntry<'a, K, V, S>),
Vacant(AsyncVacantEntry<'a, K, V, S>),
}
impl<'a, K, V, S> AsyncEntry<'a, K, V, S>
where
K: Eq + Hash + Clone + Send + Sync + 'static,
V: Clone + Send + Sync + 'static,
S: BuildHasher + Clone + Send + Sync,
{
pub(crate) fn occupied(map: &'a AsyncShardedHashMap<K, V, S>, key: K) -> Self {
Self::Occupied(AsyncOccupiedEntry { map, key })
}
pub(crate) fn vacant(map: &'a AsyncShardedHashMap<K, V, S>, key: K) -> Self {
Self::Vacant(AsyncVacantEntry { map, key })
}
pub fn key(&self) -> &K {
match self {
Self::Occupied(entry) => entry.key(),
Self::Vacant(entry) => entry.key(),
}
}
pub fn is_occupied(&self) -> bool {
matches!(self, Self::Occupied(_))
}
pub fn is_vacant(&self) -> bool {
matches!(self, Self::Vacant(_))
}
pub async fn or_insert(self, default: V) -> V {
self.or_insert_with(|| default).await
}
pub async fn or_insert_with<F>(self, default: F) -> V
where
F: FnOnce() -> V,
{
let (map, key) = self.into_parts();
map.get_or_insert_with(key, default).await
}
pub async fn and_modify<F>(self, f: F) -> Self
where
F: FnOnce(&mut V),
{
let (map, key) = self.into_parts();
let modified = map
.compute_if_present(&key, |old| {
let mut next = old;
f(&mut next);
Some(next)
})
.await
.is_some();
if modified {
Self::occupied(map, key)
} else {
Self::vacant(map, key)
}
}
pub async fn insert(self, value: V) -> Option<V> {
let (map, key) = self.into_parts();
map.insert(key, value).await
}
pub async fn remove(self) -> Option<V> {
let (map, key) = self.into_parts();
map.remove(&key).await
}
fn into_parts(self) -> (&'a AsyncShardedHashMap<K, V, S>, K) {
match self {
Self::Occupied(entry) => (entry.map, entry.key),
Self::Vacant(entry) => (entry.map, entry.key),
}
}
}
#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
pub struct AsyncOccupiedEntry<'a, K, V, S>
where
K: Eq + Hash + Clone + Send + Sync + 'static,
V: Clone + Send + Sync + 'static,
S: BuildHasher + Clone + Send + Sync,
{
map: &'a AsyncShardedHashMap<K, V, S>,
key: K,
}
impl<'a, K, V, S> AsyncOccupiedEntry<'a, K, V, S>
where
K: Eq + Hash + Clone + Send + Sync + 'static,
V: Clone + Send + Sync + 'static,
S: BuildHasher + Clone + Send + Sync,
{
pub fn key(&self) -> &K {
&self.key
}
pub async fn get(&self) -> Option<V> {
self.map.get(&self.key).await
}
pub async fn insert(self, value: V) -> Option<V> {
self.map.insert(self.key, value).await
}
pub async fn remove(self) -> Option<V> {
self.map.remove(&self.key).await
}
pub async fn remove_entry(self) -> Option<(K, V)> {
let value = self.map.remove(&self.key).await?;
Some((self.key, value))
}
}
#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
pub struct AsyncVacantEntry<'a, K, V, S>
where
K: Eq + Hash + Clone + Send + Sync + 'static,
V: Clone + Send + Sync + 'static,
S: BuildHasher + Clone + Send + Sync,
{
map: &'a AsyncShardedHashMap<K, V, S>,
key: K,
}
impl<'a, K, V, S> AsyncVacantEntry<'a, K, V, S>
where
K: Eq + Hash + Clone + Send + Sync + 'static,
V: Clone + Send + Sync + 'static,
S: BuildHasher + Clone + Send + Sync,
{
pub fn key(&self) -> &K {
&self.key
}
pub fn into_key(self) -> K {
self.key
}
pub async fn insert(self, value: V) -> V {
self.map.get_or_insert_with(self.key, || value).await
}
}