use std::fmt::{self, Debug};
use smallvec::Array;
use crate::{KeyValuePair, SmallOrdSet};
pub enum Entry<'a, A: Array, K> {
Occupied(OccupiedEntry<'a, A>),
Vacant(VacantEntry<'a, A, K>),
}
pub struct OccupiedEntry<'a, A: Array> {
set: &'a mut SmallOrdSet<A>,
idx: usize,
}
pub struct VacantEntry<'a, A: Array, K> {
set: &'a mut SmallOrdSet<A>,
idx: usize,
key: K,
}
impl<'a, A: Array, K> Entry<'a, A, K> {
pub(crate) fn occupied(set: &'a mut SmallOrdSet<A>, idx: usize) -> Self {
Entry::Occupied(OccupiedEntry { set, idx })
}
pub(crate) fn vacant(set: &'a mut SmallOrdSet<A>, idx: usize, key: K) -> Self {
Entry::Vacant(VacantEntry { set, idx, key })
}
}
impl<'a, A, K, V> Entry<'a, A, K>
where
A: Array<Item = KeyValuePair<K, V>>,
K: Ord + 'a,
V: 'a,
{
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: FnOnce() -> V>(self, default: F) -> &'a mut V {
match self {
Entry::Occupied(entry) => entry.into_mut(),
Entry::Vacant(entry) => entry.insert(default()),
}
}
pub fn key(&self) -> &K {
match self {
Entry::Occupied(entry) => entry.key(),
Entry::Vacant(entry) => entry.key(),
}
}
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<'a, A> OccupiedEntry<'a, A>
where
A: Array,
{
pub fn get_entry(&self) -> &A::Item {
&self.set.vec[self.idx]
}
pub fn remove_entry(self) -> A::Item {
self.set.vec.remove(self.idx)
}
}
impl<'a, A, K, V> OccupiedEntry<'a, A>
where
A: Array<Item = KeyValuePair<K, V>>,
K: Ord + 'a,
V: 'a,
{
pub fn key(&self) -> &K {
&self.get_entry().key
}
pub fn get(&self) -> &V {
&self.get_entry().value
}
pub fn get_mut(&mut self) -> &mut V {
&mut self.set.vec[self.idx].value
}
pub fn into_mut(self) -> &'a mut V {
&mut self.set.vec[self.idx].value
}
}
impl<'a, A: Array, K> VacantEntry<'a, A, K> {
pub fn key(&self) -> &K {
&self.key
}
pub fn into_key(self) -> K {
self.key
}
pub fn insert_with<F>(self, f: F) -> &'a mut A::Item
where
F: FnOnce(K) -> A::Item,
{
let element = f(self.key);
self.set.vec.insert(self.idx, element);
&mut self.set.vec[self.idx]
}
}
impl<'a, A, K, V> VacantEntry<'a, A, K>
where
A: Array<Item = KeyValuePair<K, V>>,
K: Ord + 'a,
V: 'a,
{
pub fn insert(self, value: V) -> &'a mut V {
&mut self.insert_with(|key| KeyValuePair { key, value }).value
}
}
impl<A, K> Debug for Entry<'_, A, K>
where
A: Array,
A::Item: Debug,
K: Debug,
{
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(),
}
}
}
impl<A> Debug for OccupiedEntry<'_, A>
where
A: Array,
A::Item: Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("OccupiedEntry")
.field("element", self.get_entry())
.finish()
}
}
impl<A, K> Debug for VacantEntry<'_, A, K>
where
A: Array,
K: Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("VacantEntry").finish()
}
}