use crate::{compaction::Compactor, Cell, HexTreeMap};
pub enum Entry<'a, V, C> {
Occupied(OccupiedEntry<'a, V>),
Vacant(VacantEntry<'a, V, C>),
}
pub struct OccupiedEntry<'a, V> {
pub(crate) target_cell: Cell,
pub(crate) cell_value: (Cell, &'a mut V),
}
pub struct VacantEntry<'a, V, C> {
pub(crate) target_cell: Cell,
pub(crate) map: &'a mut HexTreeMap<V, C>,
}
impl<'a, V, C> Entry<'a, V, C>
where
C: Compactor<V>,
{
pub fn and_modify<F>(self, f: F) -> Self
where
F: FnOnce(Cell, &mut V),
{
match self {
Entry::Occupied(OccupiedEntry {
target_cell,
cell_value: (cell, value),
}) => {
f(cell, value);
Entry::Occupied(OccupiedEntry {
target_cell,
cell_value: (cell, value),
})
}
Entry::Vacant(_) => self,
}
}
pub fn or_insert(self, default: V) -> (Cell, &'a mut V) {
match self {
Entry::Occupied(OccupiedEntry {
target_cell: _,
cell_value,
}) => cell_value,
Entry::Vacant(VacantEntry { target_cell, map }) => {
map.insert(target_cell, default);
map.get_mut(target_cell).unwrap()
}
}
}
pub fn or_insert_with<F>(self, default: F) -> (Cell, &'a mut V)
where
F: FnOnce() -> V,
{
match self {
Entry::Occupied(OccupiedEntry {
target_cell: _,
cell_value,
}) => cell_value,
Entry::Vacant(VacantEntry { target_cell, map }) => {
map.insert(target_cell, default());
map.get_mut(target_cell).unwrap()
}
}
}
}
impl<'a, V, C> Entry<'a, V, C>
where
V: Default,
C: Compactor<V>,
{
pub fn or_default(self) -> (Cell, &'a mut V) {
match self {
Entry::Occupied(OccupiedEntry {
target_cell: _,
cell_value,
}) => cell_value,
Entry::Vacant(VacantEntry { target_cell, map }) => {
map.insert(target_cell, Default::default());
map.get_mut(target_cell).expect("we just inserted")
}
}
}
}