use std::collections::HashSet;
use std::fmt::Debug;
use std::hash::{BuildHasher, Hash};
pub mod analysis;
pub mod edge;
pub mod node;
pub mod owning;
pub mod parse;
pub use edge::{Edge, EdgeMut};
pub use node::{Node, NodeMut};
pub use parse::TestGraph;
pub use rustc_hash::FxBuildHasher;
pub trait Graph {
type NodeId: Copy + Eq + Hash + Ord + Debug;
type EdgeId: Copy + Eq + Hash + Ord + Debug;
type Hasher: BuildHasher + Default;
type Node<'graph>: Node<'graph, Graph = Self>
where
Self: 'graph;
type Edge<'graph>: Edge<'graph, Graph = Self>
where
Self: 'graph;
fn get_node(&self, id: Self::NodeId) -> Option<Self::Node<'_>>;
fn get_edge(&self, id: Self::EdgeId) -> Option<Self::Edge<'_>>;
fn nodes(&self) -> impl Iterator<Item = Self::Node<'_>> + '_;
fn edges(&self) -> impl Iterator<Item = Self::Edge<'_>> + '_;
fn dfs(&self, root: Self::NodeId) -> DfsIter<'_, Directed, Self>
where
Self: Sized,
{
DfsIter {
graph: self,
visited: HashSet::default(),
stack: vec![(None, root)],
_marker: std::marker::PhantomData,
}
}
fn undirected_dfs(&self, root: Self::NodeId) -> DfsIter<'_, Undirected, Self>
where
Self: Sized,
{
DfsIter {
graph: self,
visited: HashSet::default(),
stack: vec![(None, root)],
_marker: std::marker::PhantomData,
}
}
}
pub trait GraphMut: Graph {
type NodeMut<'graph>: NodeMut<'graph, Graph = Self>
where
Self: 'graph;
type EdgeMut<'graph>: EdgeMut<'graph, Graph = Self>
where
Self: 'graph;
fn get_node_mut(&mut self, id: Self::NodeId) -> Option<Self::NodeMut<'_>>;
fn get_edge_mut(&mut self, id: Self::EdgeId) -> Option<Self::EdgeMut<'_>>;
fn merge_nodes(&mut self, keep: Self::NodeId, remove: Self::NodeId, direct_edge: Self::EdgeId)
where
Self: Sized,
{
self.get_node_mut(keep).unwrap().remove_edge_id(direct_edge);
self.get_node_mut(remove)
.unwrap()
.remove_edge_id(direct_edge);
let outgoing: Vec<Self::EdgeId> = self
.get_node(remove)
.unwrap()
.children()
.map(|item| item.edge_id())
.collect();
for eid in outgoing {
self.get_edge_mut(eid).unwrap().set_from(keep);
self.get_node_mut(keep).unwrap().add_edge_id(eid);
self.get_node_mut(remove).unwrap().remove_edge_id(eid);
}
}
}
pub trait Cfg {
type NodeId: Copy + Eq + Hash + Ord + Debug;
type Hasher: BuildHasher + Default;
fn successors(&self, n: Self::NodeId) -> impl Iterator<Item = Self::NodeId> + '_;
}
impl<G: Graph> Cfg for G {
type NodeId = G::NodeId;
type Hasher = G::Hasher;
fn successors(&self, n: Self::NodeId) -> impl Iterator<Item = Self::NodeId> + '_ {
let succs: Vec<Self::NodeId> = self
.get_node(n)
.map(|nref| nref.children().map(|e| e.node_id()).collect())
.unwrap_or_default();
succs.into_iter()
}
}
pub struct Directed;
pub struct Undirected;
pub struct DfsIter<'graph, Mode, G: Graph + Sized> {
graph: &'graph G,
visited: HashSet<G::NodeId, G::Hasher>,
stack: Vec<(Option<G::EdgeId>, G::NodeId)>,
_marker: std::marker::PhantomData<Mode>,
}
impl<'graph, G: Graph + Sized> Iterator for DfsIter<'graph, Directed, G> {
type Item = (Option<G::Edge<'graph>>, G::Node<'graph>);
fn next(&mut self) -> Option<Self::Item> {
while let Some((edge_id, node_id)) = self.stack.pop() {
if !self.visited.insert(node_id) {
continue;
}
let node_ref = self.graph.get_node(node_id).unwrap();
for edge in node_ref.children() {
let child_id = edge.node_id();
if !self.visited.contains(&child_id) {
self.stack.push((Some(edge.edge_id()), child_id));
}
}
return Some((edge_id.and_then(|id| self.graph.get_edge(id)), node_ref));
}
None
}
}
impl<'graph, G: Graph + Sized> Iterator for DfsIter<'graph, Undirected, G> {
type Item = (Option<G::Edge<'graph>>, G::Node<'graph>);
fn next(&mut self) -> Option<Self::Item> {
while let Some((edge_id, node_id)) = self.stack.pop() {
if !self.visited.insert(node_id) {
continue;
}
let node_ref = self.graph.get_node(node_id).unwrap();
for edge in node_ref.edges() {
let child_id = edge.node_id();
if !self.visited.contains(&child_id) {
self.stack.push((Some(edge.edge_id()), child_id));
}
}
return Some((edge_id.and_then(|id| self.graph.get_edge(id)), node_ref));
}
None
}
}