use std::collections::HashMap;
use std::fmt::{self, Debug, Display, Formatter};
use std::hash::Hash;
use std::str::FromStr;
use super::{Graph, ParseGraphError, VertexId};
pub trait Label: Ord + Hash + Clone + Default + Debug + FromStr + Display {}
impl<T: Ord + Hash + Clone + Default + Debug + FromStr + Display> Label for T {}
impl<V: Label, E: Label> Display for Graph<V, E> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
let mut vertices = HashMap::<VertexId, usize>::with_capacity(self.vertices_count());
for (n, (&vertex_id, _)) in (1_usize..).zip(self.vertices.iter()) {
if let Ok(vertex_data) = self.get_vertex(vertex_id) {
vertices.insert(vertex_id, n);
writeln!(f, "{n} {vertex_data}")?;
}
}
writeln!(f, "#")?;
for ([from, to], edge) in self.edges().expect("failed to get edges") {
let from_id = self.get_vertex_id(from);
let to_id = self.get_vertex_id(to);
if let Some((from, to)) = vertices.get(&from_id).zip(vertices.get(&to_id)) {
writeln!(f, "{from} {to} {edge}")?;
}
}
Ok(())
}
}
#[derive(Ord, PartialOrd, Eq, PartialEq)]
enum ParserMode {
VertexDefinitions,
EdgeDefinitions,
}
fn parse_index(s: &str, line: usize) -> Result<usize, ParseGraphError> {
s.parse().map_err(|_| ParseGraphError::ParseInt(line))
}
fn parse_label<T: FromStr>(s: &str, line: usize) -> Result<T, ParseGraphError> {
s.parse::<T>()
.map_err(|_| ParseGraphError::ParseLabel(line))
}
impl<V: Label, E: Label> FromStr for Graph<V, E> {
type Err = ParseGraphError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut graph = Self::new();
let mut vertices = HashMap::<usize, VertexId>::new();
let mut mode = ParserMode::VertexDefinitions;
for (n, line) in (1_usize..).zip(s.lines()) {
if line.starts_with('#') {
mode = ParserMode::EdgeDefinitions;
continue;
}
let mut it = line.split_whitespace();
match mode {
ParserMode::VertexDefinitions => {
let s = it.next().ok_or(ParseGraphError::VertexDefinition(n))?;
let index = parse_index(s, n)?;
let label: V = parse_label(it.remainder().unwrap_or(""), n)?;
let vertex_id = graph
.add_vertex(label)
.map_err(|err| ParseGraphError::GraphError(err, n))?;
if vertices.insert(index, vertex_id).is_some() {
return Err(ParseGraphError::VertexAlreadyDefined(index, n));
}
}
ParserMode::EdgeDefinitions => {
let (from, to) = it
.next()
.zip(it.next())
.ok_or(ParseGraphError::EdgeDefinition(n))?;
let from = parse_index(from, n)?;
let to = parse_index(to, n)?;
let label: E = parse_label(it.remainder().unwrap_or(""), n)?;
let (&from, &to) = vertices
.get(&from)
.zip(vertices.get(&to))
.ok_or(ParseGraphError::VerticesNotDefined(from, to, n))?;
graph
.add_edge(from, to, label)
.map_err(|err| ParseGraphError::GraphError(err, n))?;
}
}
}
Ok(graph)
}
}