use super::Index;
use std::hash::{BuildHasher, Hash};
use std::mem;
use std::ops::{Deref, DerefMut};
use {Error, NonEmptyIndexMap};
pub struct Occupied<'a, K: 'a, V: 'a, S: 'a> {
pub(super) key: K,
pub(super) index: Index,
pub(super) map: &'a mut NonEmptyIndexMap<K, V, S>,
}
pub struct Vacant<'a, K: 'a, V: 'a, S: 'a> {
pub(super) key: K,
pub(super) map: &'a mut NonEmptyIndexMap<K, V, S>,
}
pub enum Entry<'a, K: 'a, V: 'a, S: 'a> {
Occupied(Occupied<'a, K, V, S>),
Vacant(Vacant<'a, K, V, S>),
}
impl<'a, K: 'a, V: 'a, S: 'a> Deref for Occupied<'a, K, V, S>
where
K: Eq + Hash,
S: BuildHasher,
{
type Target = V;
fn deref(&self) -> &V {
self.map.get_entry(self.index)
}
}
impl<'a, K: 'a, V: 'a, S: 'a> DerefMut for Occupied<'a, K, V, S>
where
K: Eq + Hash,
S: BuildHasher,
{
fn deref_mut(&mut self) -> &mut V {
self.map.get_entry_mut(self.index)
}
}
impl<'a, K: 'a, V: 'a, S: 'a> Occupied<'a, K, V, S>
where
K: Eq + Hash,
S: BuildHasher,
{
pub fn remove_entry(self) -> Result<(K, V), Error> {
let key = self.key;
let map = self.map;
map.remove_entry(&key)
.map(|x| x.expect("The entry exists for sure"))
}
pub fn replace(&mut self, new_value: V) -> V {
let old = self.map.get_entry_mut(self.index);
mem::replace(old, new_value)
}
pub fn into_value(self) -> &'a mut V {
let idx = self.index;
self.map.get_entry_mut(idx)
}
}
impl<'a, K: 'a, V: 'a, S: 'a> Vacant<'a, K, V, S>
where
K: Eq + Hash,
S: BuildHasher,
{
pub fn insert(self, value: V) -> &'a mut V {
let map = self.map;
let key = self.key;
match map.get_rest_mut().entry(key) {
::indexmap::map::Entry::Occupied(_) => panic!("The entry exists for sure"),
::indexmap::map::Entry::Vacant(entry) => entry.insert(value),
}
}
}
impl<'a, K: 'a, V: 'a, S: 'a> Entry<'a, K, V, S>
where
K: Eq + Hash,
S: BuildHasher,
{
pub fn or_insert(self, value: V) -> &'a mut V {
match self {
Entry::Occupied(x) => x.into_value(),
Entry::Vacant(v) => v.insert(value),
}
}
pub fn or_insert_with<F>(self, f: F) -> &'a mut V
where
F: FnOnce() -> V,
{
match self {
Entry::Occupied(x) => x.into_value(),
Entry::Vacant(v) => v.insert(f()),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_occupied_one() {
let mut map = NonEmptyIndexMap::new(1, 2);
let entry = map.entry(1);
let occupied = match entry {
Entry::Occupied(x) => x,
Entry::Vacant(_) => panic!("Expected an occupied entry"),
};
assert_eq!(Err(Error::EmptyCollection), occupied.remove_entry());
}
#[test]
fn test_occupied() {
let mut map = NonEmptyIndexMap::from_item_and_iterator(1, 2, vec![(3, 4), (5, 6), (7, 8)]);
{
let entry = map.entry(1);
let occupied = match entry {
Entry::Occupied(x) => x,
Entry::Vacant(_) => panic!("Expected an occupied entry"),
};
assert_eq!(Ok((1, 2)), occupied.remove_entry());
}
assert_eq!(3, map.len());
{
let entry = map.entry(5);
match entry {
Entry::Occupied(x) => x,
Entry::Vacant(_) => panic!("Expected an occupied entry"),
};
}
assert_eq!(3, map.len());
}
#[test]
fn test_vacant() {
let mut map = NonEmptyIndexMap::new(1, 2);
{
let entry = map.entry(2);
let vacant = match entry {
Entry::Vacant(x) => x,
Entry::Occupied(_) => panic!("Expected a vacant entry"),
};
assert_eq!(&3, vacant.insert(3));
}
assert_eq!(Some(&3), map.get(&2));
}
#[test]
fn test_or_insert() {
let mut map = NonEmptyIndexMap::new(1, 2);
{
let entry = map.entry(1);
assert_eq!(&2, entry.or_insert(3));
}
assert_eq!(Some(&2), map.get(&1));
assert_eq!(1, map.len());
{
let entry = map.entry(2);
assert_eq!(&3, entry.or_insert(3));
}
assert_eq!(Some(&3), map.get(&2));
assert_eq!(2, map.len());
}
#[test]
fn test_or_insert_with() {
let mut map = NonEmptyIndexMap::new(1, 2);
{
let entry = map.entry(1);
assert_eq!(&2, entry.or_insert_with(|| 3));
}
assert_eq!(Some(&2), map.get(&1));
assert_eq!(1, map.len());
{
let entry = map.entry(2);
assert_eq!(&3, entry.or_insert_with(|| 3));
}
assert_eq!(Some(&3), map.get(&2));
assert_eq!(2, map.len());
}
}