use std::{borrow::Borrow, collections::{btree_map::Entry, BTreeMap, HashSet}, fmt::Debug, hash::Hash, sync::Arc};
mod mem;
use mem::Wrapper;
pub use mem::Ref;
#[derive(Debug, Default)]
pub struct MultiBiMap<L, R> {
pub left_to_right: BTreeMap<Ref<L>, HashSet<Ref<R>>>,
pub right_to_left: BTreeMap<Ref<R>, HashSet<Ref<L>>>
}
impl<L, R> MultiBiMap<L, R>
where
L: Eq + Hash + Debug + Ord, R: Eq + Hash + Debug + Ord,
{
pub fn new() -> Self {
Self {
left_to_right: BTreeMap::new(),
right_to_left: BTreeMap::new()
}
}
pub fn insert(&mut self, left: L, right: R) -> (&mut HashSet<Ref<L>>, &mut HashSet<Ref<R>>) {
let left = Ref(Arc::new(left));
let right = Ref(Arc::new(right));
let right_map = self.left_to_right.entry(left.clone()).or_insert(HashSet::new());
right_map.insert(right.clone());
let left_map = self.right_to_left.entry(right.clone()).or_insert(HashSet::new());
left_map.insert(left.clone());
(left_map, right_map)
}
pub fn insert_by_left(&mut self, left: L) -> &mut HashSet<Ref<R>> {
let left = Ref(Arc::new(left));
self.left_to_right.entry(left.clone()).or_insert(HashSet::new())
}
pub fn insert_by_right(&mut self, right: R) -> &mut HashSet<Ref<L>> {
let right = Ref(Arc::new(right));
self.right_to_left.entry(right.clone()).or_insert(HashSet::new())
}
pub fn remove_by_left(&mut self, left: L) {
let left_ref = Ref(Arc::new(left));
if let Some(right_set) = self.left_to_right.get(&left_ref) {
for right_ref in right_set.iter() {
if let Some(right_set) = self.right_to_left.get_mut(right_ref) {
if right_set.len() == 1 {
self.right_to_left.remove(right_ref);
} else {
right_set.remove(&left_ref);
}
}
}
}
self.left_to_right.remove(&left_ref);
}
pub fn remove_by_right(&mut self, right: R) {
let right_ref = Ref(Arc::new(right));
if let Some(left_set) = self.right_to_left.get(&right_ref) {
for left_ref in left_set.iter() {
if let Some(left_set) = self.left_to_right.get_mut(left_ref) {
if left_set.len() == 1 {
self.left_to_right.remove(left_ref);
} else {
left_set.remove(&right_ref);
}
}
}
}
self.right_to_left.remove(&right_ref);
}
pub fn get_by_left<Q>(&self, left: &Q) -> Option<&HashSet<Ref<R>>>
where
L: Borrow<Q>,
Q: Eq + Hash + ?Sized + Ord,
{
self.left_to_right.get(Wrapper::wrap(left))
}
pub fn get_mut_by_left<Q>(&mut self, left: &Q) -> Option<&mut HashSet<Ref<R>>>
where
L: Borrow<Q>,
Q: Eq + Hash + ?Sized + Ord,
{
self.left_to_right.get_mut(Wrapper::wrap(left))
}
pub fn entry_by_left(&mut self, left: L) -> Entry<'_, Ref<L>, HashSet<Ref<R>>> {
let left = Ref(Arc::new(left));
self.left_to_right.entry(left)
}
pub fn entry_by_right(&mut self, right: R) -> Entry<'_, Ref<R>, HashSet<Ref<L>>> {
let right = Ref(Arc::new(right));
self.right_to_left.entry(right)
}
pub fn get_by_right<Q>(&self, right: &Q) -> Option<&HashSet<Ref<L>>>
where
R: Borrow<Q>,
Q: Eq + Hash + ?Sized + Ord,
{
self.right_to_left.get(Wrapper::wrap(right))
}
pub fn get_mut_by_right<Q>(&mut self, right: &Q) -> Option<&mut HashSet<Ref<L>>>
where
R: Borrow<Q>,
Q: Eq + Hash + ?Sized + Ord,
{
self.right_to_left.get_mut(Wrapper::wrap(right))
}
}