use crate::{
hashmap::{DefaultHash, HashMap},
Value,
};
use core::hash::{BuildHasher, BuildHasherDefault, Hash};
#[cfg(feature = "stable_alloc")]
use allocator_api2::alloc::{Allocator, Global};
#[cfg(not(feature = "stable_alloc"))]
use core::alloc::Allocator;
#[cfg(not(feature = "stable_alloc"))]
use std::alloc::Global;
pub enum Entry<'a, K, V, H = BuildHasherDefault<DefaultHash>, A: Allocator = Global> {
Occupied(OccupiedEntry<'a, K, V, H, A>),
Vacant(VacantEntry<'a, K, V, H, A>),
}
impl<'a, K, V, H, A> Entry<'a, K, V, H, A>
where
K: Eq + Hash + Clone + 'a,
V: Value + 'a,
H: BuildHasher + Default,
A: Allocator,
{
pub fn or_insert(self, default: V) -> &'a mut V {
match self {
Entry::Occupied(o) => o.into_mut(),
Entry::Vacant(mut v) => v.insert(default),
}
}
pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V {
match self {
Entry::Occupied(o) => o.into_mut(),
Entry::Vacant(mut v) => v.insert(default()),
}
}
pub fn or_insert_with_key<F: FnOnce(&K) -> V>(self, default: F) -> &'a mut V {
match self {
Entry::Occupied(o) => o.into_mut(),
Entry::Vacant(mut v) => v.insert(default(v.key())),
}
}
pub fn key(&self) -> &K {
match self {
Entry::Occupied(o) => o.key(),
Entry::Vacant(v) => v.key(),
}
}
pub fn and_modify<F: FnOnce(&mut V)>(self, f: F) -> Self {
match self {
Entry::Occupied(mut o) => {
f(o.get_mut());
Entry::Occupied(o)
}
Entry::Vacant(v) => Entry::Vacant(v),
}
}
pub fn insert_entry(self, value: V) -> OccupiedEntry<'a, K, V, H, A> {
match self {
Entry::Occupied(mut o) => {
let _old = o.insert(value);
o
}
Entry::Vacant(v) => v.insert_entry(value),
}
}
pub fn or_default(self) -> &'a mut V
where
V: Default,
{
self.or_insert(V::default())
}
}
pub struct OccupiedEntry<'a, K, V, H, A: Allocator> {
pub(crate) map: &'a mut HashMap<K, V, H, A>,
pub(crate) key: K,
pub(crate) value: &'a mut V,
}
impl<'a, K, V, H, A> OccupiedEntry<'a, K, V, H, A>
where
K: Eq + Hash + Clone + 'a,
V: Value + 'a,
H: BuildHasher + Default,
A: Allocator,
{
pub fn key(&self) -> &K {
&self.key
}
pub fn remove_entry(self) -> (K, V) {
let value = self.map.remove(&self.key).unwrap();
(self.key, value)
}
pub fn get(&self) -> &V {
self.value
}
pub fn get_mut(&mut self) -> &mut V {
self.value
}
pub fn into_mut(self) -> &'a mut V {
self.value
}
pub fn insert(&mut self, value: V) -> V {
let old = *self.value;
*self.value = value;
old
}
pub fn remove(self) -> V {
self.map.remove(&self.key).unwrap()
}
}
pub struct VacantEntry<'a, K, V, H, A: Allocator> {
pub(crate) map: &'a mut HashMap<K, V, H, A>,
pub(crate) key: K,
}
impl<'a, K, V, H, A> VacantEntry<'a, K, V, H, A>
where
K: Eq + Hash + Clone + 'a,
V: Value + 'a,
H: BuildHasher + Default,
A: Allocator,
{
pub fn key(&self) -> &K {
&self.key
}
pub fn into_key(self) -> K {
self.key
}
pub fn insert(&mut self, value: V) -> &'a mut V {
let _old = self.map.insert(self.key.clone(), value);
self.map.get_mut(&self.key).unwrap()
}
pub fn insert_entry(self, value: V) -> OccupiedEntry<'a, K, V, H, A> {
let _old = self.map.insert(self.key.clone(), value);
let value = self.map.get_mut(&self.key).unwrap();
OccupiedEntry {
map: self.map,
key: self.key,
value,
}
}
}