use core::fmt::Debug;
use core::hash::Hash;
use crate::{free_pointer::FreePointer, generation::Generation};
pub(crate) enum Entry<V> {
Occupied(OccupiedEntry<V>),
Empty(EmptyEntry),
}
impl<V> Entry<V> {
pub(crate) fn into_value(self) -> Option<V> {
match self {
Entry::Occupied(occupied) => Some(occupied.value),
Entry::Empty(_) => None,
}
}
pub(crate) fn get_value_mut(&mut self, generation: Generation) -> Option<&mut V> {
match self {
Entry::Occupied(occupied) if occupied.generation == generation => {
Some(&mut occupied.value)
}
_ => None,
}
}
pub(crate) fn as_empty(&self) -> Option<&EmptyEntry> {
match self {
Entry::Empty(empty) => Some(empty),
Entry::Occupied(_) => None,
}
}
pub(crate) fn as_empty_mut(&mut self) -> Option<&mut EmptyEntry> {
match self {
Entry::Empty(empty) => Some(empty),
Entry::Occupied(_) => None,
}
}
}
pub(crate) struct OccupiedEntry<V> {
pub(crate) generation: Generation,
pub(crate) value: V,
}
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
pub(crate) struct EmptyEntry {
pub(crate) generation: Generation,
pub(crate) next_free: Option<FreePointer>,
}
impl<V: Clone> Clone for OccupiedEntry<V> {
fn clone(&self) -> Self {
Self {
generation: self.generation,
value: self.value.clone(),
}
}
}
impl<V: Copy> Copy for OccupiedEntry<V> {}
impl<V: PartialEq> PartialEq for OccupiedEntry<V> {
fn eq(&self, other: &Self) -> bool {
self.generation == other.generation && self.value.eq(&other.value)
}
}
impl<V: Eq> Eq for OccupiedEntry<V> {}
impl<V: Clone> Clone for Entry<V> {
fn clone(&self) -> Self {
match self {
Entry::Occupied(entry) => Self::Occupied(entry.clone()),
Entry::Empty(entry) => Self::Empty(*entry),
}
}
}
impl<V: Hash> Hash for OccupiedEntry<V> {
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
self.generation.hash(state);
self.value.hash(state);
}
}
impl<V: Copy> Copy for Entry<V> {}
impl<V: Debug> Debug for Entry<V> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
if let Entry::Occupied(entry) = self {
entry.value.fmt(f)
} else {
write!(f, "Empty")
}
}
}
impl<V: PartialEq> PartialEq for Entry<V> {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(Entry::Occupied(e0), Entry::Occupied(e1)) => e0.eq(e1),
(Entry::Empty(e0), Entry::Empty(e1)) => e0.eq(e1),
_ => false,
}
}
}
impl<V: Eq> Eq for Entry<V> {}
impl<V: Hash> Hash for Entry<V> {
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
match self {
Entry::Occupied(entry) => entry.hash(state),
Entry::Empty(entry) => entry.hash(state),
}
}
}