Skip to main content

cxx2flow_lib/display/
dot.rs

1use 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                } // GraphNodeType::Dummy => {} // all dummy node will be eliminated
63            }
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}