1use crate::{
2 node::{Node},
3 edge::{Edge}, subgraph::Subgraph,
4};
5use std::io::prelude::*;
6use std::io;
7
8pub struct Graph {
10 name: String,
11 kind: Kind,
12 nodes: Vec<Node>,
13 edges: Vec<Edge>,
14 subgraph: Vec<Subgraph>
15}
16
17impl Graph {
18 pub fn new(name: &str, kind: Kind) -> Graph {
19 Graph { name: String::from(name), kind: kind, nodes: vec![], edges: vec![], subgraph: vec![] }
20 }
21
22 pub fn add_node(&mut self, node: Node) -> () {
23 self.nodes.push(node);
24 }
25
26 pub fn add_edge(&mut self, edge: Edge) -> () {
27 self.edges.push(edge);
28 }
29
30 pub fn add_subgraph(&mut self, subgraph: Subgraph) -> () {
31 self.subgraph.push(subgraph.edgeop(self.kind.edgeop()))
32 }
33
34 pub fn to_dot_string(&self) -> io::Result<String> {
35 let mut writer = Vec::new();
36 self.render_opts(&mut writer).unwrap();
37 let mut s = String::new();
38 Read::read_to_string(&mut &*writer, &mut s)?;
39 Ok(s)
40 }
41
42 fn render_opts<'a,
45 W: Write>
46 (&self,
47 w: &mut W)
48 -> io::Result<()> {
49 fn writeln<W: Write>(w: &mut W, arg: &[&str]) -> io::Result<()> {
50 for &s in arg {
51 w.write_all(s.as_bytes())?;
52 }
53 write!(w, "\n")
54 }
55
56 fn indent<W: Write>(w: &mut W) -> io::Result<()> {
57 w.write_all(b" ")
58 }
59
60 writeln(w, &[self.kind.keyword(), " ", self.name.as_str(), " {"])?;
61 for n in self.subgraph.iter() {
62 indent(w)?;
63 let mut text: Vec<&str> = vec![];
64 let subgraph_dot_string: String = n.to_dot_string();
65 text.push(&subgraph_dot_string.as_str());
66 writeln(w, &text)?;
67 }
68
69 for n in self.nodes.iter() {
70 indent(w)?;
71 let mut text: Vec<&str> = vec![];
72 let node_dot_string: String = n.to_dot_string();
73 text.push(&node_dot_string.as_str());
74 writeln(w, &text)?;
75 }
76
77 let edge_symbol = self.kind.edgeop();
78 for e in self.edges.iter() {
79 indent(w)?;
80 let mut text: Vec<&str> = vec![];
81 let edge_dot_string: String = e.to_dot_string(edge_symbol);
82 text.push(&edge_dot_string.as_str());
83 writeln(w, &text)?;
84 }
85
86 writeln(w, &["}"])
87 }
88}
89
90#[derive(Copy, Clone, PartialEq, Eq, Debug)]
93pub enum Kind {
94 Digraph,
95 Graph,
96}
97
98impl Kind {
99 pub fn keyword(&self) -> &'static str {
102 match *self {
103 Kind::Digraph => "digraph",
104 Kind::Graph => "graph"
105 }
106 }
107
108 pub fn edgeop(&self) -> &'static str {
110 match *self {
111 Kind::Digraph => "->",
112 Kind::Graph => "--",
113 }
114 }
115}