mod adj_list;
mod adj_map;
mod adj_matrix;
mod error;
pub use adj_list::{AdjList, DiFlowList, DiList, FlowList, List};
pub use adj_map::{AdjMap, DiFlowMap, DiMap, FlowMap, Map};
pub use adj_matrix::{AdjMatrix, DiFlowMat, DiMat, FlowMat, Mat};
pub use error::{Error, ErrorKind};
use crate::graph::{Edge, EdgeDir};
use anyhow::Result;
pub trait GraphStorage<W, E: Edge<W>, Dir: EdgeDir> {
fn add_vertex(&mut self) -> usize;
fn remove_vertex(&mut self, vertex_id: usize) -> Result<()> {
if !self.contains_vertex(vertex_id) {
Err(Error::new_vnf(vertex_id))?
} else {
Ok(self.remove_vertex_unchecked(vertex_id))
}
}
fn remove_vertex_unchecked(&mut self, vertex_id: usize);
fn contains_vertex(&self, vertex_id: usize) -> bool;
fn add_edge(&mut self, src_id: usize, dst_id: usize, edge: E) -> Result<usize> {
if !self.contains_vertex(src_id) {
Err(Error::new_vnf(src_id))?
} else if !self.contains_vertex(dst_id) {
Err(Error::new_vnf(dst_id))?
} else {
Ok(self.add_edge_unchecked(src_id, dst_id, edge))
}
}
fn add_edge_unchecked(&mut self, src_id: usize, dst_id: usize, edge: E) -> usize;
fn update_edge(&mut self, src_id: usize, dst_id: usize, edge_id: usize, edge: E) -> Result<()> {
if !self.contains_vertex(src_id) {
Err(Error::new_vnf(src_id))?
} else if !self.contains_vertex(dst_id) {
Err(Error::new_vnf(dst_id))?
} else if !self.contains_edge(edge_id) {
Err(Error::new_enf(edge_id))?
} else {
Ok(self.update_edge_unchecked(src_id, dst_id, edge_id, edge))
}
}
fn update_edge_unchecked(&mut self, src_id: usize, dst_id: usize, edge_id: usize, mut edge: E) {
edge.set_id(edge_id);
self.remove_edge_unchecked(src_id, dst_id, edge_id);
self.add_edge_unchecked(src_id, dst_id, edge);
}
fn remove_edge(&mut self, src_id: usize, dst_id: usize, edge_id: usize) -> Result<E> {
if !self.contains_vertex(src_id) {
Err(Error::new_vnf(src_id))?
} else if !self.contains_vertex(dst_id) {
Err(Error::new_vnf(dst_id))?
} else if !self.contains_edge(edge_id) {
Err(Error::new_enf(edge_id))?
} else {
Ok(self.remove_edge_unchecked(src_id, dst_id, edge_id))
}
}
fn remove_edge_unchecked(&mut self, src_id: usize, dst_id: usize, edge_id: usize) -> E;
fn contains_edge(&self, edge_id: usize) -> bool;
fn vertex_count(&self) -> usize {
self.vertices().len()
}
fn vertices(&self) -> Vec<usize>;
fn edges_between(&self, src_id: usize, dst_id: usize) -> Result<Vec<&E>> {
if !self.contains_vertex(src_id) {
Err(Error::new_vnf(src_id))?
} else if !self.contains_vertex(dst_id) {
Err(Error::new_vnf(dst_id))?
} else {
Ok(self.edges_between_unchecked(src_id, dst_id))
}
}
fn edges_between_unchecked(&self, src_id: usize, dst_id: usize) -> Vec<&E> {
self.edges_from_unchecked(src_id)
.into_iter()
.filter_map(|(d_id, edge)| if d_id == dst_id { Some(edge) } else { None })
.collect()
}
fn edge_between(&self, src_id: usize, dst_id: usize, edge_id: usize) -> Result<&E> {
if !self.contains_vertex(src_id) {
Err(Error::new_vnf(src_id))?
} else if !self.contains_vertex(dst_id) {
Err(Error::new_vnf(dst_id))?
} else if !self.contains_edge(edge_id) {
Err(Error::new_enf(edge_id))?
} else {
let edge = self
.edges_between_unchecked(src_id, dst_id)
.into_iter()
.find(|edge| edge.get_id() == edge_id);
if edge.is_none() {
Err(Error::new_iei(src_id, dst_id, edge_id))?
} else {
Ok(edge.unwrap())
}
}
}
fn edge_between_unchecked(&self, src_id: usize, dst_id: usize, edge_id: usize) -> &E {
self.edges_between_unchecked(src_id, dst_id)
.into_iter()
.find(|edge| edge.get_id() == edge_id)
.unwrap()
}
fn edge(&self, edge_id: usize) -> Result<&E> {
if !self.contains_edge(edge_id) {
Err(Error::new_enf(edge_id))?
} else {
Ok(self.edge_unchecked(edge_id))
}
}
fn edge_unchecked(&self, edge_id: usize) -> &E {
self.edges()
.into_iter()
.find(|(_, _, edge)| edge.get_id() == edge_id)
.and_then(|(_, _, edge)| Some(edge))
.unwrap()
}
fn has_any_edge(&self, src_id: usize, dst_id: usize) -> Result<bool> {
if !self.contains_vertex(src_id) {
Err(Error::new_vnf(src_id))?
} else if !self.contains_vertex(dst_id) {
Err(Error::new_vnf(dst_id))?
} else {
Ok(self.has_any_edge_unchecked(src_id, dst_id))
}
}
fn has_any_edge_unchecked(&self, src_id: usize, dst_id: usize) -> bool {
!self.edges_between_unchecked(src_id, dst_id).is_empty()
}
fn edges(&self) -> Vec<(usize, usize, &E)> {
if Dir::is_directed() {
self.as_directed_edges()
} else {
self.as_directed_edges()
.into_iter()
.filter(|(src_id, dst_id, _)| src_id <= dst_id)
.collect()
}
}
fn edge_count(&self) -> usize {
self.edges().len()
}
fn as_directed_edges(&self) -> Vec<(usize, usize, &E)> {
self.vertices()
.into_iter()
.flat_map(|src_id| {
self.edges_from_unchecked(src_id)
.into_iter()
.map(|(dst_id, edge)| (src_id, dst_id, edge))
.collect::<Vec<(usize, usize, &E)>>()
})
.collect()
}
fn edges_from(&self, src_id: usize) -> Result<Vec<(usize, &E)>> {
if !self.contains_vertex(src_id) {
Err(Error::new_vnf(src_id))?
} else {
Ok(self.edges_from_unchecked(src_id))
}
}
fn edges_from_unchecked(&self, src_id: usize) -> Vec<(usize, &E)>;
fn neighbors(&self, src_id: usize) -> Result<Vec<usize>> {
if !self.contains_vertex(src_id) {
Err(Error::new_vnf(src_id))?
} else {
Ok(self.neighbors_unchecked(src_id))
}
}
fn neighbors_unchecked(&self, src_id: usize) -> Vec<usize> {
self.edges_from_unchecked(src_id)
.into_iter()
.map(|(dst_id, _)| dst_id)
.collect()
}
fn is_directed(&self) -> bool {
Dir::is_directed()
}
fn is_undirected(&self) -> bool {
Dir::is_undirected()
}
}