digraph_rs/
visualizer.rs

1pub mod dot;
2
3use crate::{DiGraph, EmptyPayload};
4use graphviz_rust::attributes::{EdgeAttributes, NodeAttributes};
5use graphviz_rust::cmd::{CommandArg, Format};
6use graphviz_rust::dot_generator::*;
7use graphviz_rust::dot_structures::*;
8use graphviz_rust::printer::{DotPrinter, PrinterContext};
9use graphviz_rust::{exec, exec_dot};
10use std::hash::Hash;
11
12use self::dot::{DotProcessor, ToStringProcessor};
13pub struct DotGraphVisualizer<'a, NId, NL, EL>
14where
15    NId: Eq + Hash,
16{
17    graph: &'a DiGraph<NId, NL, EL>,
18}
19
20impl<'a, NId, NL, EL> DotGraphVisualizer<'a, NId, NL, EL>
21where
22    NId: Eq + Hash + ToString,
23    NL: ToString,
24    EL: ToString,
25{
26    pub fn str_to_dot_file(&self, path: &str) -> std::io::Result<String> {
27        self.to_dot_file(path, ToStringProcessor {})
28    }
29}
30
31impl<'a, NId, NL, EL> DotGraphVisualizer<'a, NId, NL, EL>
32where
33    NId: Eq + Hash,
34{
35    pub fn new(graph: &'a DiGraph<NId, NL, EL>) -> Self {
36        Self { graph }
37    }
38    pub fn to_dot<P>(&self, processor: P) -> Graph
39    where
40        P: DotProcessor<'a, NId, NL, EL>,
41    {
42        let mut dot = graph!(strict di id!("di_graph"));
43        for (id, pl) in self.graph.nodes.iter() {
44            dot.add_stmt(processor.node(id, pl));
45        }
46        for (from, to_map) in self.graph.edges.iter() {
47            for (to, pl) in to_map.iter() {
48                dot.add_stmt(processor.edge(from, to, pl))
49            }
50        }
51        dot
52    }
53
54    pub fn to_dot_file<P>(&'a self, path: &str, processor: P) -> std::io::Result<String>
55    where
56        P: DotProcessor<'a, NId, NL, EL>,
57    {
58        vis_to_file(self.to_dot(processor), path.to_string())
59    }
60}
61
62pub fn vis(dot_graph: Graph) -> String {
63    dot_graph.print(&mut PrinterContext::default())
64}
65
66pub fn vis_to_file(dot_graph: Graph, path: String) -> std::io::Result<String> {
67    let ext = path
68        .split(".")
69        .last()
70        .map(|x| x.to_lowercase())
71        .unwrap_or("svg".to_string());
72    let format = match ext.as_str() {
73        "svg" => Format::Svg,
74        "dot" => Format::Dot,
75        _ => panic!("dot or svg"),
76    };
77    exec(
78        dot_graph,
79        &mut PrinterContext::default(),
80        vec![CommandArg::Output(path), CommandArg::Format(format)],
81    )
82}