use crate::interface::{
Edge, GraphBase, GraphIndices, ImmutableGraphContainer, NavigableGraph, Neighbor,
};
use std::borrow::Borrow;
pub trait DecoratingSubgraph {
type ParentGraph: GraphBase;
type ParentGraphRef: Borrow<Self::ParentGraph>;
fn new_empty(graph: Self::ParentGraphRef) -> Self;
fn new_full(graph: Self::ParentGraphRef) -> Self;
fn clear(&mut self);
fn parent_graph(&self) -> &Self::ParentGraph;
fn contains_node(&self, node_index: <Self::ParentGraph as GraphBase>::NodeIndex) -> bool;
fn contains_edge(&self, edge_index: <Self::ParentGraph as GraphBase>::EdgeIndex) -> bool;
fn add_node(&mut self, node_index: <Self::ParentGraph as GraphBase>::NodeIndex);
fn add_edge(&mut self, edge_index: <Self::ParentGraph as GraphBase>::EdgeIndex);
fn remove_node(&mut self, node_index: <Self::ParentGraph as GraphBase>::NodeIndex);
fn remove_edge(&mut self, edge_index: <Self::ParentGraph as GraphBase>::EdgeIndex);
fn node_count(&self) -> usize;
fn edge_count(&self) -> usize;
}
impl<T: DecoratingSubgraph> GraphBase for T {
type NodeData = <<Self as DecoratingSubgraph>::ParentGraph as GraphBase>::NodeData;
type EdgeData = <<Self as DecoratingSubgraph>::ParentGraph as GraphBase>::EdgeData;
type OptionalNodeIndex =
<<Self as DecoratingSubgraph>::ParentGraph as GraphBase>::OptionalNodeIndex;
type OptionalEdgeIndex =
<<Self as DecoratingSubgraph>::ParentGraph as GraphBase>::OptionalEdgeIndex;
type NodeIndex = <<Self as DecoratingSubgraph>::ParentGraph as GraphBase>::NodeIndex;
type EdgeIndex = <<Self as DecoratingSubgraph>::ParentGraph as GraphBase>::EdgeIndex;
}
impl<T: DecoratingSubgraph> ImmutableGraphContainer for T
where
T::ParentGraph: ImmutableGraphContainer + for<'a> NavigableGraph<'a>,
{
fn node_indices(&self) -> GraphIndices<Self::NodeIndex, Self::OptionalNodeIndex> {
unimplemented!("Will not implement if not necessary");
}
fn edge_indices(&self) -> GraphIndices<Self::EdgeIndex, Self::OptionalEdgeIndex> {
unimplemented!("Will not implement if not necessary");
}
fn contains_node_index(&self, node_id: Self::NodeIndex) -> bool {
<Self as DecoratingSubgraph>::contains_node(self, node_id)
}
fn contains_edge_index(&self, edge_id: Self::EdgeIndex) -> bool {
<Self as DecoratingSubgraph>::contains_edge(self, edge_id)
}
fn node_count(&self) -> usize {
<Self as DecoratingSubgraph>::node_count(self)
}
fn edge_count(&self) -> usize {
<Self as DecoratingSubgraph>::edge_count(self)
}
fn node_data(&self, node_id: Self::NodeIndex) -> &Self::NodeData {
self.parent_graph().node_data(node_id)
}
fn edge_data(&self, edge_id: Self::EdgeIndex) -> &Self::EdgeData {
self.parent_graph().edge_data(edge_id)
}
fn node_data_mut(&mut self, _node_id: Self::NodeIndex) -> &mut Self::NodeData {
unimplemented!("Cannot access parent graph mutably")
}
fn edge_data_mut(&mut self, _edge_id: Self::EdgeIndex) -> &mut Self::EdgeData {
unimplemented!("Cannot access parent graph mutably")
}
fn contains_edge_between(&self, from: Self::NodeIndex, to: Self::NodeIndex) -> bool {
self.edge_count_between(from, to) > 0
}
fn edge_count_between(&self, from: Self::NodeIndex, to: Self::NodeIndex) -> usize {
self.parent_graph()
.edges_between(from, to)
.filter(|e| <Self as DecoratingSubgraph>::contains_edge(self, *e))
.count()
}
fn edge_endpoints(&self, edge_id: Self::EdgeIndex) -> Edge<Self::NodeIndex> {
self.parent_graph().edge_endpoints(edge_id)
}
}
impl<'a, T: 'a + DecoratingSubgraph> NavigableGraph<'a> for T
where
T::ParentGraph: ImmutableGraphContainer + for<'b> NavigableGraph<'b>,
{
type OutNeighbors = EdgeFilteredNeighborIterator<
'a,
T,
<<Self as DecoratingSubgraph>::ParentGraph as NavigableGraph<'a>>::OutNeighbors,
>;
type InNeighbors = EdgeFilteredNeighborIterator<
'a,
T,
<<Self as DecoratingSubgraph>::ParentGraph as NavigableGraph<'a>>::InNeighbors,
>;
type EdgesBetween = EdgeFilteredEdgeIterator<
'a,
T,
<<Self as DecoratingSubgraph>::ParentGraph as NavigableGraph<'a>>::EdgesBetween,
>;
fn out_neighbors(&'a self, node_id: Self::NodeIndex) -> Self::OutNeighbors {
EdgeFilteredNeighborIterator {
graph: self,
iter: self.parent_graph().out_neighbors(node_id),
}
}
fn in_neighbors(&'a self, node_id: Self::NodeIndex) -> Self::InNeighbors {
EdgeFilteredNeighborIterator {
graph: self,
iter: self.parent_graph().in_neighbors(node_id),
}
}
fn edges_between(
&'a self,
from_node_id: Self::NodeIndex,
to_node_id: Self::NodeIndex,
) -> Self::EdgesBetween {
EdgeFilteredEdgeIterator {
graph: self,
iter: self.parent_graph().edges_between(from_node_id, to_node_id),
}
}
}
pub struct EdgeFilteredNeighborIterator<'a, Graph, SourceIterator> {
graph: &'a Graph,
iter: SourceIterator,
}
impl<
'a,
Graph: DecoratingSubgraph,
SourceIterator: Iterator<Item = Neighbor<<Graph as GraphBase>::NodeIndex, <Graph as GraphBase>::EdgeIndex>>,
> Iterator for EdgeFilteredNeighborIterator<'a, Graph, SourceIterator>
{
type Item = Neighbor<<Graph as GraphBase>::NodeIndex, <Graph as GraphBase>::EdgeIndex>;
fn next(&mut self) -> Option<Self::Item> {
for neighbor in &mut self.iter {
if self.graph.contains_edge(neighbor.edge_id) {
return Some(neighbor);
}
}
None
}
}
pub struct EdgeFilteredEdgeIterator<'a, Graph, SourceIterator> {
graph: &'a Graph,
iter: SourceIterator,
}
impl<
'a,
Graph: DecoratingSubgraph,
SourceIterator: Iterator<Item = <Graph as GraphBase>::EdgeIndex>,
> Iterator for EdgeFilteredEdgeIterator<'a, Graph, SourceIterator>
{
type Item = <Graph as GraphBase>::EdgeIndex;
fn next(&mut self) -> Option<Self::Item> {
for edge in &mut self.iter {
if self.graph.contains_edge(edge) {
return Some(edge);
}
}
None
}
}