digraph-rs 0.1.0

a handful of algorithms for digraphs
Documentation
pub mod dot;

use crate::{DiGraph, EmptyPayload};
use graphviz_rust::attributes::{EdgeAttributes, NodeAttributes};
use graphviz_rust::cmd::{CommandArg, Format};
use graphviz_rust::dot_generator::*;
use graphviz_rust::dot_structures::*;
use graphviz_rust::printer::{DotPrinter, PrinterContext};
use graphviz_rust::{exec, exec_dot};
use std::hash::Hash;

use self::dot::{DotProcessor, ToStringProcessor};
pub struct DotGraphVisualizer<'a, NId, NL, EL>
where
    NId: Eq + Hash,
{
    graph: &'a DiGraph<NId, NL, EL>,
}

impl<'a, NId, NL, EL> DotGraphVisualizer<'a, NId, NL, EL>
where
    NId: Eq + Hash + ToString,
    NL: ToString,
    EL: ToString,
{
    pub fn str_to_dot_file(&self, path: &str) -> std::io::Result<String> {
        self.to_dot_file(path, ToStringProcessor {})
    }
}

impl<'a, NId, NL, EL> DotGraphVisualizer<'a, NId, NL, EL>
where
    NId: Eq + Hash,
{
    pub fn new(graph: &'a DiGraph<NId, NL, EL>) -> Self {
        Self { graph }
    }
    pub fn to_dot<P>(&self, processor: P) -> Graph
    where
        P: DotProcessor<'a, NId, NL, EL>,
    {
        let mut dot = graph!(strict di id!("di_graph"));
        for (id, pl) in self.graph.nodes.iter() {
            dot.add_stmt(processor.node(id, pl));
        }
        for (from, to_map) in self.graph.edges.iter() {
            for (to, pl) in to_map.iter() {
                dot.add_stmt(processor.edge(from, to, pl))
            }
        }
        dot
    }

    pub fn to_dot_file<P>(&'a self, path: &str, processor: P) -> std::io::Result<String>
    where
        P: DotProcessor<'a, NId, NL, EL>,
    {
        vis_to_file(self.to_dot(processor), path.to_string())
    }
}

pub fn vis(dot_graph: Graph) -> String {
    dot_graph.print(&mut PrinterContext::default())
}

pub fn vis_to_file(dot_graph: Graph, path: String) -> std::io::Result<String> {
    let ext = path
        .split(".")
        .last()
        .map(|x| x.to_lowercase())
        .unwrap_or("svg".to_string());
    let format = match ext.as_str() {
        "svg" => Format::Svg,
        "dot" => Format::Dot,
        _ => panic!("dot or svg"),
    };
    exec(
        dot_graph,
        &mut PrinterContext::default(),
        vec![CommandArg::Output(path), CommandArg::Format(format)],
    )
}