cxx2flow_lib/display/
dot.rs1use crate::error::{Error, Result};
2use crate::graph::{Graph, GraphNodeType};
3use petgraph::{
4 visit::IntoNodeReferences,
5 visit::{EdgeRef, IntoEdgeReferences},
6};
7
8use super::GraphDisplay;
9
10pub struct Dot {
11 curly: bool,
12}
13
14impl Dot {
15 pub fn new(curly: bool) -> Self {
16 Dot { curly }
17 }
18}
19
20impl GraphDisplay for Dot {
21 fn generate_from_graph(&self, graph: &Graph) -> Result<String> {
22 let mut res = "digraph {\n".to_string();
23 if !self.curly {
24 res.push_str("graph [splines=polyline];\n");
25 }
26 for (id, i) in graph.node_references() {
27 match i {
28 GraphNodeType::Begin => res.push_str(
29 format!(
30 "D{} [shape=box, style=rounded, label=\"begin\"];\n",
31 id.index()
32 )
33 .as_str(),
34 ),
35 GraphNodeType::End => res.push_str(
36 format!(
37 "{{rank = sink; D{} [shape=box, style=rounded, label=\"end\"];}}\n",
38 id.index()
39 )
40 .as_str(),
41 ),
42 GraphNodeType::Node(str) => res.push_str(
43 format!(
44 "D{} [shape=box, label=\"{}\"];\n",
45 id.index(),
46 str.replace('\"', "\\\"")
47 )
48 .as_str(),
49 ),
50 GraphNodeType::Choice(str) => res.push_str(
51 format!(
52 "D{} [shape=diamond, label=\"{}?\"];\n",
53 id.index(),
54 str.replace('\"', "\\\"")
55 )
56 .as_str(),
57 ),
58 GraphNodeType::Dummy => {
59 return Err(Error::UnexpectedDummyGraphNode {
60 graph: graph.clone(),
61 });
62 } }
64 }
65
66 for i in graph.edge_references() {
67 match i.weight() {
68 crate::graph::EdgeType::Normal => res.push_str(
69 format!("D{} -> D{};\n", i.source().index(), i.target().index()).as_str(),
70 ),
71 crate::graph::EdgeType::Branch(t) => res.push_str(
72 format!(
73 "D{}:{} -> D{}:n [xlabel={}];\n",
74 i.source().index(),
75 if *t { "s" } else { "e" },
76 i.target().index(),
77 if *t { "Y" } else { "N" }
78 )
79 .as_str(),
80 ),
81 };
82 }
83 res.push_str("}\n");
84 Ok(res)
85 }
86}