use std::collections::hash_map;
use std::mem;
pub enum Entry<'a, K1, K2, V> {
Occupied(OccupiedEntry<'a, K1, K2, V>),
Vacant(VacantEntry<'a, K1, K2, V>),
}
impl<K1, K2, V> Entry<'_, K1, K2, V> {
pub fn key1(&self) -> &K1 {
match self {
Entry::Occupied(e) => e.key1(),
Entry::Vacant(e) => e.key1(),
}
}
pub fn key2(&self) -> &K2 {
match self {
Entry::Occupied(e) => e.key2(),
Entry::Vacant(e) => e.key2(),
}
}
pub fn keys(&self) -> (&K1, &K2) {
match self {
Entry::Occupied(e) => e.keys(),
Entry::Vacant(e) => e.keys(),
}
}
}
impl<'a, K1, K2, V> Entry<'a, K1, K2, V>
where
K1: Clone,
K2: Clone,
{
pub fn or_insert(self, default: V) -> &'a mut V {
match self {
Entry::Occupied(e) => e.into_mut(),
Entry::Vacant(e) => e.insert(default),
}
}
pub fn or_insert_with<F>(self, default: F) -> &'a mut V
where
F: FnOnce() -> V,
{
match self {
Entry::Occupied(e) => e.into_mut(),
Entry::Vacant(e) => e.insert(default()),
}
}
pub fn or_insert_with_keys<F>(self, default: F) -> &'a mut V
where
F: FnOnce(&K1, &K2) -> V,
{
match self {
Entry::Occupied(e) => e.into_mut(),
Entry::Vacant(e) => {
let (key1, key2) = e.keys();
let v = default(key1, key2);
e.insert(v)
}
}
}
pub fn and_modify<F>(mut self, f: F) -> Self
where
F: FnOnce(&mut V),
{
if let Entry::Occupied(e) = &mut self {
f(e.get_mut());
}
self
}
pub fn insert_entry(self, value: V) -> OccupiedEntry<'a, K1, K2, V> {
match self {
Entry::Occupied(mut e) => {
e.insert(value);
e
}
Entry::Vacant(e) => e.insert_entry(value),
}
}
pub fn or_default(self) -> &'a mut V
where
V: Default,
{
self.or_insert_with(V::default)
}
}
pub struct VacantEntry<'a, K1, K2, V> {
primary: hash_map::VacantEntry<'a, K1, (K2, V)>,
secondary: hash_map::VacantEntry<'a, K2, K1>,
}
impl<'a, K1, K2, V> VacantEntry<'a, K1, K2, V> {
pub(super) fn new(
primary: hash_map::VacantEntry<'a, K1, (K2, V)>,
secondary: hash_map::VacantEntry<'a, K2, K1>,
) -> Self {
Self { primary, secondary }
}
}
impl<K1, K2, V> VacantEntry<'_, K1, K2, V> {
pub fn key1(&self) -> &K1 {
self.primary.key()
}
pub fn key2(&self) -> &K2 {
self.secondary.key()
}
pub fn keys(&self) -> (&K1, &K2) {
(self.key1(), self.key2())
}
pub fn into_keys(self) -> (K1, K2) {
(self.primary.into_key(), self.secondary.into_key())
}
}
impl<'a, K1, K2, V> VacantEntry<'a, K1, K2, V>
where
K1: Clone,
K2: Clone,
{
pub fn insert(self, value: V) -> &'a mut V {
let key1 = self.primary.key().clone();
let key2 = self.secondary.key().clone();
self.secondary.insert(key1);
let (_, v) = self.primary.insert((key2, value));
v
}
pub fn insert_entry(self, value: V) -> OccupiedEntry<'a, K1, K2, V> {
let key1 = self.primary.key().clone();
let key2 = self.secondary.key().clone();
let occupied_secondary = self.secondary.insert_entry(key1.clone());
let occupied_primary = self.primary.insert_entry((key2.clone(), value));
OccupiedEntry {
primary: occupied_primary,
secondary: occupied_secondary,
}
}
}
pub struct OccupiedEntry<'a, K1, K2, V> {
primary: hash_map::OccupiedEntry<'a, K1, (K2, V)>,
secondary: hash_map::OccupiedEntry<'a, K2, K1>,
}
impl<'a, K1, K2, V> OccupiedEntry<'a, K1, K2, V> {
pub(super) fn new(
primary: hash_map::OccupiedEntry<'a, K1, (K2, V)>,
secondary: hash_map::OccupiedEntry<'a, K2, K1>,
) -> Self {
Self { primary, secondary }
}
}
impl<'a, K1, K2, V> OccupiedEntry<'a, K1, K2, V> {
pub fn key1(&self) -> &K1 {
self.primary.key()
}
pub fn key2(&self) -> &K2 {
self.secondary.key()
}
pub fn keys(&self) -> (&K1, &K2) {
(self.key1(), self.key2())
}
pub fn get(&self) -> &V {
&self.primary.get().1
}
pub fn get_mut(&mut self) -> &mut V {
&mut self.primary.get_mut().1
}
pub fn into_mut(self) -> &'a mut V {
&mut self.primary.into_mut().1
}
pub fn insert(&mut self, value: V) -> V {
mem::replace(self.get_mut(), value)
}
pub fn remove(self) -> V {
self.remove_entry().2
}
pub fn remove_entry(self) -> (K1, K2, V) {
self.secondary.remove_entry();
let (key1, (key2, value)) = self.primary.remove_entry();
(key1, key2, value)
}
}