use std::{collections::HashSet, marker::PhantomData};
use crate::graph::{Graph, edge::Edge};
pub trait Node<'graph> {
type Graph: Graph;
fn new(id: <Self::Graph as Graph>::NodeId, graph: &'graph Self::Graph) -> Self;
fn id(&self) -> <Self::Graph as Graph>::NodeId;
fn graph(&self) -> &'graph Self::Graph;
fn edge_ids(
&self,
) -> &'graph HashSet<<Self::Graph as Graph>::EdgeId, <Self::Graph as Graph>::Hasher>;
fn edge_count(&self) -> usize;
fn is_leaf(&self) -> bool {
self.edge_count() == 0
}
fn edges(&self) -> Iter<'graph, EdgeMode, Self::Graph> {
Iter {
graph: self.graph(),
node: self.id(),
iter: self.edge_ids().iter(),
_mode: PhantomData,
}
}
fn children(&self) -> Iter<'graph, ChildMode, Self::Graph> {
Iter {
graph: self.graph(),
node: self.id(),
iter: self.edge_ids().iter(),
_mode: PhantomData,
}
}
fn parents(&self) -> Iter<'graph, ParentMode, Self::Graph> {
Iter {
graph: self.graph(),
node: self.id(),
iter: self.edge_ids().iter(),
_mode: PhantomData,
}
}
}
pub trait NodeMut<'graph> {
type Graph: Graph;
fn new(id: <Self::Graph as Graph>::NodeId, graph: &'graph mut Self::Graph) -> Self;
fn id(&self) -> <Self::Graph as Graph>::NodeId;
fn graph(&mut self) -> &mut Self::Graph;
fn edge_ids(&self) -> &HashSet<<Self::Graph as Graph>::EdgeId, <Self::Graph as Graph>::Hasher>;
fn edge_count(&self) -> usize;
fn add_edge_id(&mut self, edge: <Self::Graph as Graph>::EdgeId);
fn remove_edge_id(&mut self, edge: <Self::Graph as Graph>::EdgeId);
fn as_ref<'a>(&'a mut self) -> <Self::Graph as Graph>::Node<'a>
where
'graph: 'a,
{
<Self::Graph as Graph>::Node::new(self.id(), &*self.graph())
}
}
pub struct EdgeItem<'graph, G: Graph> {
pub(crate) graph: &'graph G,
pub(crate) edge: G::EdgeId,
pub(crate) node: G::NodeId,
}
impl<'graph, G: Graph> EdgeItem<'graph, G> {
pub fn edge_id(&self) -> G::EdgeId {
self.edge
}
pub fn node_id(&self) -> G::NodeId {
self.node
}
pub fn node(&self) -> G::Node<'graph> {
<G as Graph>::Node::new(self.node, self.graph)
}
pub fn edge(&self) -> G::Edge<'graph> {
<G as Graph>::Edge::new(self.edge, self.graph)
}
}
pub struct ChildMode;
pub struct ParentMode;
pub struct EdgeMode;
pub struct Iter<'graph, Mode, G: Graph> {
graph: &'graph G,
node: G::NodeId,
iter: std::collections::hash_set::Iter<'graph, G::EdgeId>,
_mode: PhantomData<Mode>,
}
impl<'graph, G: Graph> Iterator for Iter<'graph, ChildMode, G> {
type Item = EdgeItem<'graph, G>;
fn next(&mut self) -> Option<Self::Item> {
for &id in self.iter.by_ref() {
let edge = <G as Graph>::Edge::new(id, self.graph);
if self.node == edge.from_id() {
return Some(EdgeItem {
graph: self.graph,
edge: id,
node: edge.to_id(),
});
}
}
None
}
}
impl<'graph, G: Graph> Iterator for Iter<'graph, ParentMode, G> {
type Item = EdgeItem<'graph, G>;
fn next(&mut self) -> Option<Self::Item> {
for id in self.iter.by_ref() {
let edge = <G as Graph>::Edge::new(*id, self.graph);
if self.node == edge.to_id() {
return Some(EdgeItem {
graph: self.graph,
edge: *id,
node: edge.from_id(),
});
}
}
None
}
}
impl<'graph, G: Graph> Iterator for Iter<'graph, EdgeMode, G> {
type Item = EdgeItem<'graph, G>;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(|&id| {
let edge = <G as Graph>::Edge::new(id, self.graph);
let other_node = if self.node == edge.from_id() {
edge.to_id()
} else {
edge.from_id()
};
EdgeItem {
graph: self.graph,
edge: id,
node: other_node,
}
})
}
}