use crate::IntMap;
pub enum Entry<'a, V: 'a> {
Occupied(OccupiedEntry<'a, V>),
Vacant(VacantEntry<'a, V>),
}
impl<'a, V> Entry<'a, V> {
#[inline]
pub(crate) fn new(key: u64, int_map: &'a mut IntMap<V>) -> Self {
let (cache_ix, val_ix) = Self::indices(key, int_map);
match val_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, int_map }),
}
}
fn indices(key: u64, int_map: &IntMap<V>) -> (usize, Option<usize>) {
let cache_ix = int_map.calc_index(key);
let vals = &int_map.cache[cache_ix];
let vals_ix = { vals.iter() }
.enumerate()
.find_map(|(vals_ix, &(k, _))| (k == key).then(|| vals_ix));
(cache_ix, vals_ix)
}
}
pub struct OccupiedEntry<'a, V: 'a> {
vals_ix: usize,
vals: &'a mut Vec<(u64, V)>,
count: &'a mut usize,
}
impl<'a, V> OccupiedEntry<'a, 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, V: 'a> {
key: u64,
int_map: &'a mut IntMap<V>,
}
impl<'a, V: 'a> VacantEntry<'a, V> {
pub fn insert(self, value: V) -> &'a mut V {
self.int_map.insert(self.key, value);
return self.int_map.get_mut(self.key).unwrap();
}
}