use super::raw::RawTableEntry;
use super::{get_hash, IndexMapCore};
use crate::HashValue;
use core::{fmt, mem};
impl<K, V> IndexMapCore<K, V> {
pub(crate) fn entry(&mut self, hash: HashValue, key: K) -> Entry<'_, K, V>
where
K: Eq,
{
match self.raw_entry(hash, |k| *k == key) {
Ok(raw) => Entry::Occupied(OccupiedEntry { raw }),
Err(map) => Entry::Vacant(VacantEntry { map, hash, key }),
}
}
}
pub enum Entry<'a, K, V> {
Occupied(OccupiedEntry<'a, K, V>),
Vacant(VacantEntry<'a, K, V>),
}
impl<'a, K, V> Entry<'a, K, V> {
pub fn index(&self) -> usize {
match *self {
Entry::Occupied(ref entry) => entry.index(),
Entry::Vacant(ref entry) => entry.index(),
}
}
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>(self, call: F) -> &'a mut V
where
F: FnOnce() -> V,
{
match self {
Entry::Occupied(entry) => entry.into_mut(),
Entry::Vacant(entry) => entry.insert(call()),
}
}
pub fn or_insert_with_key<F>(self, call: F) -> &'a mut V
where
F: FnOnce(&K) -> V,
{
match self {
Entry::Occupied(entry) => entry.into_mut(),
Entry::Vacant(entry) => {
let value = call(&entry.key);
entry.insert(value)
}
}
}
pub fn key(&self) -> &K {
match *self {
Entry::Occupied(ref entry) => entry.key(),
Entry::Vacant(ref entry) => entry.key(),
}
}
pub fn and_modify<F>(mut self, f: F) -> Self
where
F: FnOnce(&mut V),
{
if let Entry::Occupied(entry) = &mut self {
f(entry.get_mut());
}
self
}
pub fn or_default(self) -> &'a mut V
where
V: Default,
{
match self {
Entry::Occupied(entry) => entry.into_mut(),
Entry::Vacant(entry) => entry.insert(V::default()),
}
}
}
impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for Entry<'_, K, V> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut tuple = f.debug_tuple("Entry");
match self {
Entry::Vacant(v) => tuple.field(v),
Entry::Occupied(o) => tuple.field(o),
};
tuple.finish()
}
}
pub struct OccupiedEntry<'a, K, V> {
raw: RawTableEntry<'a, K, V>,
}
impl<'a, K, V> OccupiedEntry<'a, K, V> {
#[inline]
pub fn index(&self) -> usize {
self.raw.index()
}
pub fn key(&self) -> &K {
&self.raw.bucket().key
}
pub fn get(&self) -> &V {
&self.raw.bucket().value
}
pub fn get_mut(&mut self) -> &mut V {
&mut self.raw.bucket_mut().value
}
pub fn into_mut(self) -> &'a mut V {
&mut self.raw.into_bucket().value
}
pub fn insert(&mut self, value: V) -> V {
mem::replace(self.get_mut(), value)
}
#[deprecated(note = "`remove` disrupts the map order -- \
use `swap_remove` or `shift_remove` for explicit behavior.")]
pub fn remove(self) -> V {
self.swap_remove()
}
pub fn swap_remove(self) -> V {
self.swap_remove_entry().1
}
pub fn shift_remove(self) -> V {
self.shift_remove_entry().1
}
#[deprecated(note = "`remove_entry` disrupts the map order -- \
use `swap_remove_entry` or `shift_remove_entry` for explicit behavior.")]
pub fn remove_entry(self) -> (K, V) {
self.swap_remove_entry()
}
pub fn swap_remove_entry(self) -> (K, V) {
let (map, index) = self.raw.remove_index();
map.swap_remove_finish(index)
}
pub fn shift_remove_entry(self) -> (K, V) {
let (map, index) = self.raw.remove_index();
map.shift_remove_finish(index)
}
}
impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for OccupiedEntry<'_, K, V> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("OccupiedEntry")
.field("key", self.key())
.field("value", self.get())
.finish()
}
}
pub struct VacantEntry<'a, K, V> {
map: &'a mut IndexMapCore<K, V>,
hash: HashValue,
key: K,
}
impl<'a, K, V> VacantEntry<'a, K, V> {
pub fn index(&self) -> usize {
self.map.indices.len()
}
pub fn key(&self) -> &K {
&self.key
}
pub fn into_key(self) -> K {
self.key
}
pub fn insert(self, value: V) -> &'a mut V {
let i = self.index();
let Self { map, hash, key } = self;
map.indices.insert(hash.get(), i, get_hash(&map.entries));
debug_assert_eq!(i, map.entries.len());
map.push_entry(hash, key, value);
&mut map.entries[i].value
}
}
impl<K: fmt::Debug, V> fmt::Debug for VacantEntry<'_, K, V> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_tuple("VacantEntry").field(self.key()).finish()
}
}
pub struct IndexedEntry<'a, K, V> {
map: &'a mut IndexMapCore<K, V>,
index: usize,
}
impl<'a, K, V> IndexedEntry<'a, K, V> {
pub(crate) fn new(map: &'a mut IndexMapCore<K, V>, index: usize) -> Self {
Self { map, index }
}
#[inline]
pub fn index(&self) -> usize {
self.index
}
pub fn key(&self) -> &K {
&self.map.entries[self.index].key
}
pub fn get(&self) -> &V {
&self.map.entries[self.index].value
}
pub fn get_mut(&mut self) -> &mut V {
&mut self.map.entries[self.index].value
}
pub fn insert(&mut self, value: V) -> V {
mem::replace(self.get_mut(), value)
}
pub fn into_mut(self) -> &'a mut V {
&mut self.map.entries[self.index].value
}
pub fn swap_remove_entry(self) -> (K, V) {
self.map.swap_remove_index(self.index).unwrap()
}
pub fn shift_remove_entry(self) -> (K, V) {
self.map.shift_remove_index(self.index).unwrap()
}
pub fn swap_remove(self) -> V {
self.swap_remove_entry().1
}
pub fn shift_remove(self) -> V {
self.shift_remove_entry().1
}
}
impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for IndexedEntry<'_, K, V> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("IndexedEntry")
.field("index", &self.index)
.field("key", self.key())
.field("value", self.get())
.finish()
}
}