use crate::graph::graph::Graph;
use std::hash::Hash;
#[derive(Debug)]
pub enum GraphConversionError {
EdgeAdditionFailed(usize, usize),
NodeAttributeError(usize, String),
EdgeAttributeError(usize, usize, String),
}
impl std::fmt::Display for GraphConversionError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
GraphConversionError::EdgeAdditionFailed(from, to) => {
write!(
f,
"Failed to add edge from node {} to node {} during conversion",
from, to
)
}
GraphConversionError::NodeAttributeError(id, key) => {
write!(
f,
"Failed to set attribute '{}' for node {} during conversion",
key, id
)
}
GraphConversionError::EdgeAttributeError(from, to, key) => {
write!(
f,
"Failed to set attribute '{}' for edge from {} to {} during conversion",
key, from, to
)
}
}
}
}
impl std::error::Error for GraphConversionError {}
pub trait GraphConversion<W, N, E> {
fn convert_to<N2, E2>(&self) -> Result<Graph<W, N2, E2>, GraphConversionError>
where
W: Copy + PartialEq + Default,
N2: Clone + Eq + Hash + std::fmt::Debug + Default,
E2: Clone + std::fmt::Debug + Default;
fn to_string_graph(&self) -> Result<Graph<W, String, String>, GraphConversionError>
where
W: Copy + PartialEq + Default;
}
impl<W, N, E> GraphConversion<W, N, E> for Graph<W, N, E>
where
W: Copy + PartialEq + Default,
N: Clone + Eq + Hash + std::fmt::Debug,
E: Clone + std::fmt::Debug + Default,
{
fn convert_to<N2, E2>(&self) -> Result<Graph<W, N2, E2>, GraphConversionError>
where
W: Copy + PartialEq + Default,
N2: Clone + Eq + Hash + std::fmt::Debug + Default,
E2: Clone + std::fmt::Debug + Default,
{
let mut new_graph = Graph::<W, N2, E2>::new(self.directed);
for (_id, node) in self.nodes.iter() {
let new_id = new_graph.add_node(N2::default());
for (key, value) in &node.attributes {
new_graph
.set_node_attribute(new_id, key.clone(), value.clone())
.map_err(|_| GraphConversionError::NodeAttributeError(new_id, key.clone()))?;
}
}
for (from, to, weight, _) in self.get_all_edges() {
if new_graph.add_edge(from, to, weight, E2::default()).is_err() {
return Err(GraphConversionError::EdgeAdditionFailed(from, to));
}
if let Some(attrs) = self.get_all_edge_attributes(from, to) {
for (key, value) in attrs {
new_graph
.set_edge_attribute(from, to, key.clone(), value.clone())
.map_err(|_| {
GraphConversionError::EdgeAttributeError(from, to, key.clone())
})?;
}
}
}
Ok(new_graph)
}
fn to_string_graph(&self) -> Result<Graph<W, String, String>, GraphConversionError>
where
W: Copy + PartialEq + Default,
{
let mut new_graph = Graph::<W, String, String>::new(self.directed);
for (id, node) in self.nodes.iter() {
let new_id = new_graph.add_node(id.to_string());
for (key, value) in &node.attributes {
new_graph
.set_node_attribute(new_id, key.clone(), value.clone())
.map_err(|_| GraphConversionError::NodeAttributeError(new_id, key.clone()))?;
}
}
for (from, to, weight, _) in self.get_all_edges() {
if new_graph
.add_edge(from, to, weight, "".to_string())
.is_err()
{
return Err(GraphConversionError::EdgeAdditionFailed(from, to));
}
if let Some(attrs) = self.get_all_edge_attributes(from, to) {
for (key, value) in attrs {
new_graph
.set_edge_attribute(from, to, key.clone(), value.clone())
.map_err(|_| {
GraphConversionError::EdgeAttributeError(from, to, key.clone())
})?;
}
}
}
Ok(new_graph)
}
}