1mod attributes;
2pub use attributes::*;
3
4mod parser;
5use std::sync::Arc;
6
7pub use parser::{DOT, DOTParser, DotIO};
8
9use crate::{
10 models::{DiGraph, Graph, HasLabels, UnGraph},
11 types::{Error, Result},
12};
13
14impl From<&DiGraph> for DOT {
16 fn from(graph: &DiGraph) -> Self {
17 let labels: Vec<&String> = graph.labels().iter().collect();
18 let vertices = graph
19 .labels()
20 .iter()
21 .map(|l| (l.clone(), VertexAttributes::default()))
22 .collect();
23 let edges = graph
24 .edges()
25 .iter()
26 .map(|&(x, y)| {
27 (
28 labels[x].clone(),
29 labels[y].clone(),
30 EdgeAttributes::default(),
31 )
32 })
33 .collect();
34 Self {
35 graph_type: "digraph".to_string(),
36 strict: false,
37 id: None,
38 graph_attributes: GraphAttributes::default(),
39 default_node_attributes: VertexAttributes::default(),
40 default_edge_attributes: EdgeAttributes::default(),
41 vertices,
42 edges,
43 }
44 }
45}
46
47impl TryFrom<DOT> for DiGraph {
49 type Error = Error;
50
51 fn try_from(dot: DOT) -> Result<Self> {
52 if dot.graph_type != "digraph" {
53 return Err(Error::InvalidParameter(
54 "dot graph type",
55 "expected 'digraph' for a directed graph",
56 ));
57 }
58 let labels: Vec<String> = dot.vertices.keys().cloned().collect();
59 let mut graph = DiGraph::empty(labels)?;
60 for (stats, t, _) in dot.edges {
61 let x = graph.label_to_index(&stats)?;
62 let y = graph.label_to_index(&t)?;
63 graph.add_edge(x, y)?;
64 }
65 Ok(graph)
66 }
67}
68
69impl From<&UnGraph> for DOT {
71 fn from(graph: &UnGraph) -> Self {
72 let labels: Vec<&String> = graph.labels().iter().collect();
73 let vertices = graph
74 .labels()
75 .iter()
76 .map(|l| (l.clone(), VertexAttributes::default()))
77 .collect();
78 let edges = graph
79 .edges()
80 .iter()
81 .map(|&(x, y)| {
82 (
83 labels[x].clone(),
84 labels[y].clone(),
85 EdgeAttributes::default(),
86 )
87 })
88 .collect();
89 Self {
90 graph_type: "graph".to_string(),
91 strict: false,
92 id: None,
93 graph_attributes: GraphAttributes::default(),
94 default_node_attributes: VertexAttributes::default(),
95 default_edge_attributes: EdgeAttributes::default(),
96 vertices,
97 edges,
98 }
99 }
100}
101
102impl TryFrom<DOT> for UnGraph {
104 type Error = Error;
105
106 fn try_from(dot: DOT) -> Result<Self> {
107 if dot.graph_type != "graph" {
108 return Err(Error::InvalidParameter(
109 "dot graph type",
110 "expected 'graph' for an undirected graph",
111 ));
112 }
113 let labels: Vec<String> = dot.vertices.keys().cloned().collect();
114 let mut graph = UnGraph::empty(labels)?;
115 for (stats, t, _) in dot.edges {
116 let x = graph.label_to_index(&stats)?;
117 let y = graph.label_to_index(&t)?;
118 graph.add_edge(x, y)?;
119 }
120 Ok(graph)
121 }
122}
123
124impl DotIO for DiGraph {
125 fn from_dot_string(dot: &str) -> Result<Self> {
126 DiGraph::try_from(DOT::from_string(dot)?)
127 }
128
129 fn to_dot_string(&self) -> Result<String> {
130 DOT::from(self).to_string_repr()
131 }
132
133 fn from_dot_file(path: &str) -> Result<Self> {
134 let string =
135 std::fs::read_to_string(path).map_err(|evidence| Error::Io(Arc::new(evidence)))?;
136 Self::from_dot_string(&string)
137 }
138
139 fn to_dot_file(&self, path: &str) -> Result<()> {
140 let string = self.to_dot_string()?;
141 std::fs::write(path, string).map_err(|evidence| Error::Io(Arc::new(evidence)))?;
142 Ok(())
143 }
144}
145
146impl DotIO for UnGraph {
147 fn from_dot_string(dot: &str) -> Result<Self> {
148 UnGraph::try_from(DOT::from_string(dot)?)
149 }
150
151 fn to_dot_string(&self) -> Result<String> {
152 DOT::from(self).to_string_repr()
153 }
154
155 fn from_dot_file(path: &str) -> Result<Self> {
156 let string =
157 std::fs::read_to_string(path).map_err(|evidence| Error::Io(Arc::new(evidence)))?;
158 Self::from_dot_string(&string)
159 }
160
161 fn to_dot_file(&self, path: &str) -> Result<()> {
162 let string = self.to_dot_string()?;
163 std::fs::write(path, string).map_err(|evidence| Error::Io(Arc::new(evidence)))?;
164 Ok(())
165 }
166}