use std::any::Any;
use std::marker::PhantomData;
use anyhow::Result;
use provide::{Edges, Graph, Neighbors, Vertices};
use crate::graph::{error::Error, DefaultEdge, Edge, EdgeDir, FlowEdge};
use crate::provide;
use crate::storage::{FlowList, FlowMat, GraphStorage, List, Mat};
pub type MatGraph<W, Dir> = SimpleGraph<W, DefaultEdge<W>, Dir, Mat<W, Dir>>;
pub type ListGraph<W, Dir> = SimpleGraph<W, DefaultEdge<W>, Dir, List<W, Dir>>;
pub type FlowMatGraph<W, Dir> = SimpleGraph<W, FlowEdge<W>, Dir, FlowMat<W>>;
pub type FlowListGraph<W, Dir> = SimpleGraph<W, DefaultEdge<W>, Dir, FlowList<W, Dir>>;
pub struct SimpleGraph<W, E: Edge<W>, Dir: EdgeDir, S: GraphStorage<W, E, Dir>> {
storage: S,
phantom_w: PhantomData<W>,
phantom_e: PhantomData<E>,
phantom_dir: PhantomData<Dir>,
}
impl<W: Any, E: Edge<W>, Dir: EdgeDir, S: GraphStorage<W, E, Dir>> SimpleGraph<W, E, Dir, S> {
pub fn init(storage: S) -> Self {
SimpleGraph {
storage,
phantom_e: PhantomData,
phantom_w: PhantomData,
phantom_dir: PhantomData,
}
}
}
impl<W, E: Edge<W>, Dir: EdgeDir, S: GraphStorage<W, E, Dir>> Neighbors
for SimpleGraph<W, E, Dir, S>
{
fn neighbors(&self, src_id: usize) -> Result<Vec<usize>> {
self.storage.neighbors(src_id)
}
fn neighbors_unchecked(&self, src_id: usize) -> Vec<usize> {
self.storage.neighbors_unchecked(src_id)
}
}
impl<W, E: Edge<W>, Dir: EdgeDir, S: GraphStorage<W, E, Dir>> Vertices
for SimpleGraph<W, E, Dir, S>
{
fn vertices(&self) -> Vec<usize> {
self.storage.vertices()
}
fn vertex_count(&self) -> usize {
self.storage.vertex_count()
}
fn contains_vertex(&self, vertex_id: usize) -> bool {
self.storage.contains_vertex(vertex_id)
}
}
impl<W, E: Edge<W>, Dir: EdgeDir, S: GraphStorage<W, E, Dir>> Edges<W, E>
for SimpleGraph<W, E, Dir, S>
{
fn edges_from(&self, src_id: usize) -> Result<Vec<(usize, &E)>> {
self.storage.edges_from(src_id)
}
fn edges_from_unchecked(&self, src_id: usize) -> Vec<(usize, &E)> {
self.storage.edges_from_unchecked(src_id)
}
fn edges_between(&self, src_id: usize, dst_id: usize) -> Result<Vec<&E>> {
self.storage.edges_between(src_id, dst_id)
}
fn edges_between_unchecked(&self, src_id: usize, dst_id: usize) -> Vec<&E> {
self.storage.edges_between_unchecked(src_id, dst_id)
}
fn edge_between(&self, src_id: usize, dst_id: usize, edge_id: usize) -> Result<&E> {
self.storage.edge_between(src_id, dst_id, edge_id)
}
fn edge_between_unchecked(&self, src_id: usize, dst_id: usize, edge_id: usize) -> &E {
self.storage.edge_between_unchecked(src_id, dst_id, edge_id)
}
fn edge(&self, edge_id: usize) -> Result<&E> {
self.storage.edge(edge_id)
}
fn edge_unchecked(&self, edge_id: usize) -> &E {
self.storage.edge_unchecked(edge_id)
}
fn has_any_edge(&self, src_id: usize, dst_id: usize) -> Result<bool> {
self.storage.has_any_edge(src_id, dst_id)
}
fn has_any_edge_unchecked(&self, src_id: usize, dst_id: usize) -> bool {
self.storage.has_any_edge_unchecked(src_id, dst_id)
}
fn edges(&self) -> Vec<(usize, usize, &E)> {
self.storage.edges()
}
fn as_directed_edges(&self) -> Vec<(usize, usize, &E)> {
self.storage.as_directed_edges()
}
fn edges_count(&self) -> usize {
self.storage.edge_count()
}
fn contains_edge(&self, edge_id: usize) -> bool {
self.storage.contains_edge(edge_id)
}
}
impl<W, E: Edge<W>, Dir: EdgeDir, S: GraphStorage<W, E, Dir>> Graph<W, E, Dir>
for SimpleGraph<W, E, Dir, S>
{
fn add_vertex(&mut self) -> usize {
self.storage.add_vertex()
}
fn remove_vertex(&mut self, vertex_id: usize) -> Result<()> {
self.storage.remove_vertex(vertex_id)
}
fn remove_vertex_unchecked(&mut self, vertex_id: usize) {
self.storage.remove_vertex_unchecked(vertex_id)
}
fn add_edge(&mut self, src_id: usize, dst_id: usize, edge: E) -> Result<usize> {
if self.has_any_edge(src_id, dst_id)? {
Err(Error::new_me(src_id, dst_id))?
} else if src_id == dst_id {
Err(Error::new_l(src_id))?
} else {
self.storage.add_edge(src_id, dst_id, edge)
}
}
fn add_edge_unchecked(&mut self, src_id: usize, dst_id: usize, edge: E) -> usize {
self.storage.add_edge_unchecked(src_id, dst_id, edge)
}
fn update_edge(&mut self, src_id: usize, dst_id: usize, edge_id: usize, edge: E) -> Result<()> {
self.storage.update_edge(src_id, dst_id, edge_id, edge)
}
fn update_edge_unchecked(&mut self, src_id: usize, dst_id: usize, edge_id: usize, edge: E) {
self.storage
.update_edge_unchecked(src_id, dst_id, edge_id, edge)
}
fn remove_edge(&mut self, src_id: usize, dst_id: usize, edge_id: usize) -> Result<E> {
self.storage.remove_edge(src_id, dst_id, edge_id)
}
fn remove_edge_unchecked(&mut self, src_id: usize, dst_id: usize, edge_id: usize) -> E {
self.storage.remove_edge_unchecked(src_id, dst_id, edge_id)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::provide::*;
#[test]
fn add_loop() {
let mut graph = MatGraph::init(Mat::<usize>::init());
assert!(graph.add_edge(0, 0, 1.into()).is_err());
}
#[test]
fn add_multiple_edge() {
let mut graph = MatGraph::init(Mat::<usize>::init());
let a = graph.add_vertex();
let b = graph.add_vertex();
graph.add_edge_unchecked(a, b, 1.into());
assert!(graph.add_edge(a, b, 1.into()).is_err());
}
}