use crate::{int::SealedInt, IntKey, IntMap};
pub enum Entry<'a, K: IntKey, V: 'a> {
Occupied(OccupiedEntry<'a, K, V>),
Vacant(VacantEntry<'a, K, V>),
}
impl<'a, K: IntKey, V> Entry<'a, K, V> {
#[inline]
pub(crate) fn new(key: K, int_map: &'a mut IntMap<K, V>) -> Self {
let (cache_ix, vals_ix) = Self::indices(key, int_map);
match vals_ix {
Some(vals_ix) => Entry::Occupied(OccupiedEntry {
vals_ix,
vals: &mut int_map.cache[cache_ix],
count: &mut int_map.count,
}),
None => Entry::Vacant(VacantEntry {
key,
cache_ix,
int_map,
}),
}
}
fn indices(key: K, int_map: &IntMap<K, V>) -> (usize, Option<usize>) {
if int_map.cache.is_empty() {
return (0, None);
}
let k = key.into_int();
let cache_ix = k.calc_index(int_map.mod_mask, K::PRIME);
let vals = &int_map.cache[cache_ix];
let vals_ix = vals.iter().position(|(key, _)| key.into_int() == k);
(cache_ix, vals_ix)
}
pub fn or_insert(self, default: V) -> &'a mut V {
match self {
Entry::Occupied(entry) => entry.into_mut(),
Entry::Vacant(entry) => entry.insert(default),
}
}
pub fn or_insert_with<F>(self, default: F) -> &'a mut V
where
F: FnOnce() -> V,
{
match self {
Entry::Occupied(entry) => entry.into_mut(),
Entry::Vacant(entry) => entry.insert(default()),
}
}
pub fn or_insert_with_key<F>(self, default: F) -> &'a mut V
where
F: FnOnce(K) -> V,
{
match self {
Entry::Occupied(entry) => entry.into_mut(),
Entry::Vacant(entry) => {
let d = default(entry.key);
entry.insert(d)
}
}
}
}
impl<'a, K: IntKey, V> Entry<'a, K, V>
where
V: Default,
{
pub fn or_default(self) -> &'a mut V {
match self {
Entry::Occupied(entry) => entry.into_mut(),
Entry::Vacant(entry) => entry.insert(Default::default()),
}
}
}
pub struct OccupiedEntry<'a, K: IntKey, V: 'a> {
vals_ix: usize,
vals: &'a mut Vec<(K, V)>,
count: &'a mut usize,
}
impl<'a, K: IntKey, V> OccupiedEntry<'a, K, V> {
pub fn get(&self) -> &V {
&self.vals.get(self.vals_ix).unwrap().1
}
pub fn get_mut(&mut self) -> &mut V {
&mut self.vals.get_mut(self.vals_ix).unwrap().1
}
pub fn into_mut(self) -> &'a mut V {
&mut self.vals.get_mut(self.vals_ix).unwrap().1
}
pub fn insert(&mut self, value: V) -> V {
std::mem::replace(&mut self.vals[self.vals_ix].1, value)
}
pub fn remove(self) -> V {
*self.count -= 1;
let kv = self.vals.swap_remove(self.vals_ix);
kv.1
}
}
pub struct VacantEntry<'a, K: IntKey, V: 'a> {
key: K,
cache_ix: usize,
int_map: &'a mut IntMap<K, V>,
}
impl<'a, K: IntKey, V: 'a> VacantEntry<'a, K, V> {
pub fn insert(mut self, value: V) -> &'a mut V {
if self.int_map.increase_cache_if_needed() {
let k = self.key.into_int();
self.cache_ix = k.calc_index(self.int_map.mod_mask, K::PRIME);
}
self.int_map.count += 1;
let vals = &mut self.int_map.cache[self.cache_ix];
vals.push((self.key, value));
&mut vals.last_mut().unwrap().1
}
}