use std::borrow::Borrow;
use std::fmt::Debug;
use std::hash::Hash;
use std::marker::PhantomData;
use smallvec::SmallVec;
pub const DEFAULT_GRAPH_SUCCS_NUM: usize = 4;
pub trait Graph<const S: usize = DEFAULT_GRAPH_SUCCS_NUM> {
type NodeId: Copy + Hash + Eq + Ord + Debug;
type EdgeId: Copy;
fn entry(&self) -> Self::NodeId;
fn exit(&self) -> Self::NodeId;
fn predecessors(&self, n: Self::NodeId) -> SmallVec<[Self::EdgeId; S]>;
fn successors(&self, n: Self::NodeId) -> SmallVec<[Self::EdgeId; S]>;
fn source(&self, e: Self::EdgeId) -> Self::NodeId;
fn target(&self, e: Self::EdgeId) -> Self::NodeId;
fn size(&self) -> usize;
}
pub trait SuccessorNodes<const S: usize = DEFAULT_GRAPH_SUCCS_NUM> {
type NodeId: Copy + Hash + Eq;
fn get_succ_nodes(&self, n: Self::NodeId) -> SmallVec<[Self::NodeId; S]>;
}
impl<const S: usize, T: Graph<S>> SuccessorNodes<S> for T {
type NodeId = T::NodeId;
fn get_succ_nodes(&self, n: Self::NodeId) -> SmallVec<[Self::NodeId; S]> {
self.successors(n)
.into_iter()
.map(|edge_idx| self.target(edge_idx))
.collect()
}
}
pub struct ReversedGraph<G: Graph<S>, B: Borrow<G>, const S: usize = DEFAULT_GRAPH_SUCCS_NUM> {
graph: B,
phantom: PhantomData<*const G>,
}
pub type ReversedRefGraph<'a, G, const S: usize = DEFAULT_GRAPH_SUCCS_NUM> =
ReversedGraph<G, &'a G, S>;
pub type ReversedIntoGraph<G, const S: usize = DEFAULT_GRAPH_SUCCS_NUM> = ReversedGraph<G, G, S>;
pub trait ReverseGraph<const S: usize = DEFAULT_GRAPH_SUCCS_NUM> {
type G: Graph<S>;
fn rev(&self) -> ReversedRefGraph<Self::G, S>;
fn into_rev(self) -> ReversedIntoGraph<Self::G, S>;
}
impl<const S: usize, T: Graph<S>> ReverseGraph<S> for T {
type G = T;
fn rev(&self) -> ReversedRefGraph<T, S> {
ReversedGraph {
graph: self,
phantom: PhantomData,
}
}
fn into_rev(self) -> ReversedIntoGraph<T, S> {
ReversedGraph {
graph: self,
phantom: PhantomData,
}
}
}
impl<G: Graph<S>, B: Borrow<G>, const S: usize> Graph<S> for ReversedGraph<G, B, S> {
type NodeId = G::NodeId;
type EdgeId = G::EdgeId;
fn entry(&self) -> Self::NodeId {
self.graph.borrow().exit()
}
fn exit(&self) -> Self::NodeId {
self.graph.borrow().entry()
}
fn predecessors(&self, n: Self::NodeId) -> SmallVec<[Self::EdgeId; S]> {
self.graph.borrow().successors(n)
}
fn successors(&self, n: Self::NodeId) -> SmallVec<[Self::EdgeId; S]> {
self.graph.borrow().predecessors(n)
}
fn source(&self, e: Self::EdgeId) -> Self::NodeId {
self.graph.borrow().target(e)
}
fn target(&self, e: Self::EdgeId) -> Self::NodeId {
self.graph.borrow().source(e)
}
fn size(&self) -> usize {
self.graph.borrow().size()
}
}