1use super::{GraphConversion, IOError};
2use crate::{
3 utils::{fill_bitvector, get_size},
4 WriteGraph,
5};
6
7#[derive(Debug)]
9pub struct DiGraph {
10 pub bit_vec: Vec<usize>,
11 pub n: usize,
12}
13impl DiGraph {
14 pub fn from_d6(repr: &str) -> Result<Self, IOError> {
30 let bytes = repr.as_bytes();
31 Self::valid_digraph(bytes)?;
32 let n = get_size(bytes, 1)?;
33 let Some(bit_vec) = Self::build_bitvector(bytes, n) else {
34 return Err(IOError::NonCanonicalEncoding);
35 };
36 Ok(Self { bit_vec, n })
37 }
38
39 pub fn from_adj(adj: &[usize]) -> Result<Self, IOError> {
55 let n2 = adj.len();
56 let n = (n2 as f64).sqrt() as usize;
57 if n * n != n2 {
58 return Err(IOError::InvalidAdjacencyMatrix);
59 }
60 let bit_vec = adj.to_vec();
61 Ok(Self { bit_vec, n })
62 }
63
64 fn valid_digraph(repr: &[u8]) -> Result<bool, IOError> {
66 if repr[0] == b'&' {
67 Ok(true)
68 } else {
69 Err(IOError::InvalidDigraphHeader)
70 }
71 }
72
73 fn build_bitvector(bytes: &[u8], n: usize) -> Option<Vec<usize>> {
76 let bv_len = n * n;
77 let bit_vec = fill_bitvector(bytes, bv_len, 2);
78 bit_vec
79 }
80}
81
82impl GraphConversion for DiGraph {
83 fn bit_vec(&self) -> &[usize] {
84 &self.bit_vec
85 }
86
87 fn size(&self) -> usize {
88 self.n
89 }
90
91 fn is_directed(&self) -> bool {
92 true
93 }
94}
95
96impl WriteGraph for DiGraph {}
97
98#[cfg(test)]
99mod testing {
100 use crate::WriteGraph;
101
102 use super::GraphConversion;
103
104 #[test]
105 fn test_header() {
106 let repr = b"&AG";
107 assert!(super::DiGraph::valid_digraph(repr).is_ok());
108 }
109
110 #[test]
111 fn test_invalid_header() {
112 let repr = b"AG";
113 assert!(super::DiGraph::valid_digraph(repr).is_err());
114 }
115
116 #[test]
117 fn test_from_adj() {
118 let adj = &[0, 0, 1, 0];
119 let graph = super::DiGraph::from_adj(adj).unwrap();
120 assert_eq!(graph.size(), 2);
121 assert_eq!(graph.bit_vec(), vec![0, 0, 1, 0]);
122 assert_eq!(graph.write_graph(), "&AG");
123 }
124
125 #[test]
126 fn test_from_nonsquare_adj() {
127 let adj = &[0, 0, 1, 0, 1];
128 let graph = super::DiGraph::from_adj(adj);
129 assert!(graph.is_err());
130 }
131
132 #[test]
133 fn test_bitvector_n2() {
137 let repr = "&AG";
138 let graph = super::DiGraph::from_d6(repr).unwrap();
139 assert_eq!(graph.size(), 2);
140 assert_eq!(graph.bit_vec(), vec![0, 0, 1, 0]);
141 }
142
143 #[test]
144 fn test_bitvector_n3() {
149 let repr = r"&B\o";
150 let graph = super::DiGraph::from_d6(repr).unwrap();
151 assert_eq!(graph.size(), 3);
152 assert_eq!(graph.bit_vec(), vec![0, 1, 1, 1, 0, 1, 1, 1, 0]);
153 }
154
155 #[test]
156 fn test_bitvector_n4() {
162 let repr = r"&C]|w";
163 let graph = super::DiGraph::from_d6(repr).unwrap();
164 assert_eq!(graph.size(), 4);
165 assert_eq!(
166 graph.bit_vec(),
167 vec![0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0]
168 );
169 }
170
171 #[test]
172 fn test_init_invalid_n2() {
173 let repr = "AG";
174 let graph = super::DiGraph::from_d6(repr);
175 assert!(graph.is_err());
176 }
177
178 #[test]
179 fn test_to_adjacency() {
180 let repr = r"&C]|w";
181 let graph = super::DiGraph::from_d6(repr).unwrap();
182 let adj = graph.to_adjmat();
183 assert_eq!(adj, "0 1 1 1\n1 0 1 1\n1 1 0 1\n1 1 1 0\n");
184 }
185
186 #[test]
187 fn test_to_dot() {
188 let repr = r"&AG";
189 let graph = super::DiGraph::from_d6(repr).unwrap();
190 let dot = graph.to_dot(None);
191 assert_eq!(dot, "digraph {\n1 -> 0;\n}");
192 }
193
194 #[test]
195 fn test_to_dot_with_id() {
196 let repr = r"&AG";
197 let graph = super::DiGraph::from_d6(repr).unwrap();
198 let dot = graph.to_dot(Some(1));
199 assert_eq!(dot, "digraph graph_1 {\n1 -> 0;\n}");
200 }
201
202 #[test]
203 fn test_to_net() {
204 let repr = r"&AG";
205 let graph = super::DiGraph::from_d6(repr).unwrap();
206 let net = graph.to_net();
207 assert_eq!(net, "*Vertices 2\n1 \"0\"\n2 \"1\"\n*Arcs\n2 1\n");
208 }
209
210 #[test]
211 fn test_to_flat() {
212 let repr = r"&AG";
213 let graph = super::DiGraph::from_d6(repr).unwrap();
214 let flat = graph.to_flat();
215 assert_eq!(flat, "0010");
216 }
217
218 #[test]
219 fn test_write_n2() {
220 let repr = r"&AG";
221 let graph = super::DiGraph::from_d6(repr).unwrap();
222 let graph6 = graph.write_graph();
223 assert_eq!(graph6, repr);
224 }
225
226 #[test]
227 fn test_write_n3() {
228 let repr = r"&B\o";
229 let graph = super::DiGraph::from_d6(repr).unwrap();
230 let graph6 = graph.write_graph();
231 assert_eq!(graph6, repr);
232 }
233
234 #[test]
235 fn test_write_n4() {
236 let repr = r"&C]|w";
237 let graph = super::DiGraph::from_d6(repr).unwrap();
238 let graph6 = graph.write_graph();
239 assert_eq!(graph6, repr);
240 }
241}