use std::fmt::Debug;
use std::{hash::Hash, iter::FusedIterator};
use crate::id_distributer::IdDistributer;
use crate::{NodeEnum, NodeIndex};
use ordermap::OrderMap;
pub trait NodeDiscriminant:
Debug + Clone + Copy + PartialEq + Eq + Hash + Ord + PartialOrd + Sized + Sync + Send + 'static
{
fn first() -> Self;
fn next(&self) -> Option<Self>;
}
pub trait Discriminated<D: NodeDiscriminant> {
fn discriminant(&self) -> D;
}
pub trait NodeIter<'a, T: NodeEnum + 'a>:
Clone + ExactSizeIterator + FusedIterator + Iterator<Item = (NodeIndex, &'a T)> + Sized
{
}
pub trait NodeIterMut<'a, T: NodeEnum + 'a>:
ExactSizeIterator + FusedIterator + Iterator<Item = (NodeIndex, &'a mut T)> + Sized
{
}
pub trait NodeIntoIter<T: NodeEnum>:
ExactSizeIterator + FusedIterator + Iterator<Item = (NodeIndex, T)> + Sized
{
}
pub trait CateArena: 'static {
type V: NodeEnum<Discriminant = Self::D>;
type D: NodeDiscriminant;
type Iter<'a>: NodeIter<'a, Self::V>;
type IterMut<'a>: NodeIterMut<'a, Self::V>;
type IntoIter: NodeIntoIter<Self::V>;
fn new(id_distributer: IdDistributer) -> Self;
fn new_from_iter(id_distributer: IdDistributer, iter: impl IntoIterator<Item = (NodeIndex, Self::V)>) -> Self;
fn dispatch(&self, i: NodeIndex) -> Option<Self::D>;
fn get_container<'a>(&'a self, d: Self::D) -> &'a OrderMap<usize, Self::V>;
fn get_container_mut<'a>(&'a mut self, d: Self::D) -> &'a mut OrderMap<usize, Self::V>;
fn alloc(&mut self, d: Self::D) -> NodeIndex;
fn alloc_untyped(&mut self) -> NodeIndex;
fn fill_back_untyped(&mut self, i: NodeIndex, item: Self::V);
fn merge(&mut self, other: Self)
where
Self: Sized;
fn remove(&mut self, i: NodeIndex) -> Option<Self::V>;
fn len(&self) -> usize;
fn iter<'a>(&'a self) -> Self::Iter<'a>;
fn iter_mut<'a>(&'a mut self) -> Self::IterMut<'a>;
fn into_iter(self) -> Self::IntoIter;
fn insert(&mut self, item: Self::V) -> NodeIndex {
let d = Discriminated::discriminant(&item);
let idx = self.alloc(d);
if self.get_container_mut(d).insert(idx.0, item).is_some() {
panic!("Allocated index already existed, check if the context is correct!");
}
idx
}
fn fill_back(&mut self, i: NodeIndex, item: Self::V) {
let d = self.dispatch(i).expect(&format!("Fillback an non-existing index {:?}", i));
if Discriminated::discriminant(&item) != d {
panic!("Fillback with incompatible type: found{:?} expect{:?}", Discriminated::discriminant(&item), d);
}
if self.get_container_mut(d).insert(i.0, item).is_some() {
panic!("Fillback an occupied index {:?}", i);
}
}
fn contains(&self, i: NodeIndex) -> bool {
self.dispatch(i).map_or(false, |d| self.get_container(d).contains_key(&i.0))
}
fn get(&self, i: NodeIndex) -> Option<&Self::V> {
self.dispatch(i).and_then(|d| self.get_container(d).get(&i.0))
}
fn get_mut(&mut self, i: NodeIndex) -> Option<&mut Self::V> {
self.dispatch(i).and_then(|d| self.get_container_mut(d).get_mut(&i.0))
}
fn update_with<F>(&mut self, i: NodeIndex, f: F)
where
F: FnOnce(Self::V) -> Self::V,
{
let d = self.dispatch(i).expect(&format!("Update a non-existing node {:?}", i));
let x = self.get_container_mut(d).swap_remove(&i.0).expect(&format!("Update a non-existing node {:?}", i));
self.get_container_mut(d).insert(i.0, f(x));
}
}