use super::VecMap;
use core::hash::Hash;
use std::fmt::{self, Debug};
use std::mem;
pub enum Entry<'a, K, V, const N: usize, S> {
Occupied(OccupiedEntry<'a, K, V, S, N>),
Vacant(VacantEntry<'a, K, V, N, S>),
}
impl<'a, K, V, S, const N: usize> Entry<'a, K, V, N, S> {
#[inline]
pub fn or_insert(self, default: V) -> &'a mut V
where
K: Hash,
{
match self {
Entry::Occupied(entry) => entry.into_mut(),
Entry::Vacant(entry) => entry.insert(default),
}
}
#[inline]
pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V
where
K: Hash,
{
match self {
Entry::Occupied(entry) => entry.into_mut(),
Entry::Vacant(entry) => entry.insert(default()),
}
}
#[inline]
pub fn key(&self) -> &K {
match *self {
Entry::Occupied(ref entry) => entry.key(),
Entry::Vacant(ref entry) => entry.key(),
}
}
#[inline]
pub fn and_modify<F>(self, f: F) -> Self
where
F: FnOnce(&mut V),
{
match self {
Entry::Occupied(mut entry) => {
f(entry.get_mut());
Entry::Occupied(entry)
}
Entry::Vacant(entry) => Entry::Vacant(entry),
}
}
}
impl<K: fmt::Debug, V: fmt::Debug, const N: usize, S> fmt::Debug for Entry<'_, K, V, N, S> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
Entry::Vacant(ref v) => f.debug_tuple("Entry").field(v).finish(),
Entry::Occupied(ref o) => f.debug_tuple("Entry").field(o).finish(),
}
}
}
pub struct OccupiedEntry<'a, K, V, S, const N: usize> {
idx: usize,
key: Option<K>,
map: &'a mut VecMap<K, V, N, S>,
}
unsafe impl<K, V, S, const N: usize> Send for OccupiedEntry<'_, K, V, S, N>
where
K: Send,
V: Send,
S: Send,
{
}
unsafe impl<K, V, S, const N: usize> Sync for OccupiedEntry<'_, K, V, S, N>
where
K: Sync,
V: Sync,
S: Sync,
{
}
impl<K: Debug, V: Debug, S, const N: usize> Debug for OccupiedEntry<'_, K, V, S, N> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("OccupiedEntry")
.field("key", self.key())
.field("value", self.get())
.finish()
}
}
impl<'a, K, V, S, const N: usize> OccupiedEntry<'a, K, V, S, N> {
pub(crate) fn new(idx: usize, key: K, map: &'a mut VecMap<K, V, N, S>) -> Self {
Self {
idx,
key: Some(key),
map,
}
}
#[inline]
pub fn key(&self) -> &K {
unsafe { &self.map.v.get_unchecked(self.idx).0 }
}
#[inline]
pub fn remove_entry(self) -> (K, V) {
unsafe { self.map.remove_idx(self.idx) }
}
#[inline]
pub fn get(&self) -> &V {
unsafe { &self.map.v.get_unchecked(self.idx).1 }
}
#[inline]
pub fn get_mut(&mut self) -> &mut V {
unsafe { &mut self.map.v.get_unchecked_mut(self.idx).1 }
}
#[inline]
pub fn into_mut(self) -> &'a mut V {
unsafe { &mut self.map.v.get_unchecked_mut(self.idx).1 }
}
#[inline]
pub fn insert(&mut self, mut value: V) -> V {
let old_value = self.get_mut();
mem::swap(&mut value, old_value);
value
}
#[inline]
pub fn remove(self) -> V {
self.remove_entry().1
}
#[inline]
#[allow(clippy::unwrap_used)]
pub fn replace_entry_with<F>(self, f: F) -> Entry<'a, K, V, N, S>
where
F: FnOnce(&K, V) -> Option<V>,
{
let (key, value) = unsafe { self.map.remove_idx(self.idx) };
if let Some(v) = f(&key, value) {
let idx = self.map.insert_idx(key, v);
Entry::Occupied(OccupiedEntry {
idx,
key: self.key,
map: self.map,
})
} else {
Entry::Vacant(VacantEntry { key, map: self.map })
}
}
}
pub struct VacantEntry<'a, K, V, const N: usize, S> {
key: K,
map: &'a mut VecMap<K, V, N, S>,
}
impl<K: Debug, V, const N: usize, S> Debug for VacantEntry<'_, K, V, N, S> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("VacantEntry").field(self.key()).finish()
}
}
impl<'a, K, V, const N: usize, S> VacantEntry<'a, K, V, N, S> {
pub(crate) fn new(key: K, map: &'a mut VecMap<K, V, N, S>) -> Self {
Self { key, map }
}
#[inline]
pub fn key(&self) -> &K {
&self.key
}
#[inline]
pub fn into_key(self) -> K {
self.key
}
#[inline]
pub fn insert(self, value: V) -> &'a mut V
where
K: Hash,
{
let i = self.map.insert_idx(self.key, value);
unsafe { &mut self.map.v.get_unchecked_mut(i).1 }
}
}