use crate::ShardedHashMap;
use std::hash::{BuildHasher, Hash};
pub enum Entry<'a, K, V, S>
where
K: Eq + Hash + Clone + Send + Sync,
V: Clone + Send + Sync,
S: BuildHasher + Clone + Send + Sync,
{
Occupied(OccupiedEntry<'a, K, V, S>),
Vacant(VacantEntry<'a, K, V, S>),
}
impl<'a, K, V, S> Entry<'a, K, V, S>
where
K: Eq + Hash + Clone + Send + Sync,
V: Clone + Send + Sync,
S: BuildHasher + Clone + Send + Sync,
{
pub(crate) fn occupied(map: &'a ShardedHashMap<K, V, S>, key: K) -> Self {
Self::Occupied(OccupiedEntry { map, key })
}
pub(crate) fn vacant(map: &'a ShardedHashMap<K, V, S>, key: K) -> Self {
Self::Vacant(VacantEntry { 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 fn or_insert(self, default: V) -> V {
self.or_insert_with(|| default)
}
pub 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)
}
pub 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.clone();
f(&mut next);
Some(next)
})
.is_some();
if modified {
Self::occupied(map, key)
} else {
Self::vacant(map, key)
}
}
pub fn insert(self, value: V) -> Option<V> {
let (map, key) = self.into_parts();
map.insert(key, value)
}
pub fn remove(self) -> Option<V> {
let (map, key) = self.into_parts();
map.remove(&key)
}
fn into_parts(self) -> (&'a ShardedHashMap<K, V, S>, K) {
match self {
Self::Occupied(entry) => (entry.map, entry.key),
Self::Vacant(entry) => (entry.map, entry.key),
}
}
}
pub struct OccupiedEntry<'a, K, V, S>
where
K: Eq + Hash + Clone + Send + Sync,
V: Clone + Send + Sync,
S: BuildHasher + Clone + Send + Sync,
{
map: &'a ShardedHashMap<K, V, S>,
key: K,
}
impl<'a, K, V, S> OccupiedEntry<'a, K, V, S>
where
K: Eq + Hash + Clone + Send + Sync,
V: Clone + Send + Sync,
S: BuildHasher + Clone + Send + Sync,
{
pub fn key(&self) -> &K {
&self.key
}
pub fn get(&self) -> Option<V> {
self.map.get(&self.key)
}
pub fn insert(self, value: V) -> Option<V> {
self.map.insert(self.key, value)
}
pub fn remove(self) -> Option<V> {
self.map.remove(&self.key)
}
pub fn remove_entry(self) -> Option<(K, V)> {
let value = self.map.remove(&self.key)?;
Some((self.key, value))
}
}
pub struct VacantEntry<'a, K, V, S>
where
K: Eq + Hash + Clone + Send + Sync,
V: Clone + Send + Sync,
S: BuildHasher + Clone + Send + Sync,
{
map: &'a ShardedHashMap<K, V, S>,
key: K,
}
impl<'a, K, V, S> VacantEntry<'a, K, V, S>
where
K: Eq + Hash + Clone + Send + Sync,
V: Clone + Send + Sync,
S: BuildHasher + Clone + Send + Sync,
{
pub fn key(&self) -> &K {
&self.key
}
pub fn into_key(self) -> K {
self.key
}
pub fn insert(self, value: V) -> V {
self.map.get_or_insert_with(self.key, || value)
}
}