1use crate::{utils::upper_triangle, GraphConversion};
2
3pub trait WriteGraph: GraphConversion {
5 fn write_graph(&self) -> String {
6 write_graph6(self.bit_vec().to_vec(), self.size(), self.is_directed())
7 }
8}
9
10fn write_header(repr: &mut String, is_directed: bool) {
11 if is_directed {
12 repr.push('&');
13 }
14}
15
16fn write_size(repr: &mut String, size: usize) {
17 let size_char = char::from_u32(size as u32 + 63).unwrap();
18 repr.push(size_char);
19}
20
21fn pad_bitvector(bit_vec: &mut Vec<usize>) {
22 if bit_vec.len() % 6 != 0 {
23 (0..6 - (bit_vec.len() % 6)).for_each(|_| bit_vec.push(0));
24 }
25}
26
27fn parse_bitvector(bit_vec: &[usize], repr: &mut String) {
28 for chunk in bit_vec.chunks(6) {
29 let mut sum = 0;
30 for (i, bit) in chunk.iter().rev().enumerate() {
31 sum += bit * 2usize.pow(i as u32);
32 }
33 let char = char::from_u32(sum as u32 + 63).unwrap();
34 repr.push(char);
35 }
36}
37
38pub fn write_graph6(bit_vec: Vec<usize>, n: usize, is_directed: bool) -> String {
39 let mut repr = String::new();
40 let mut bit_vec = if is_directed {
41 bit_vec
42 } else {
43 upper_triangle(&bit_vec, n)
44 };
45 write_header(&mut repr, is_directed);
46 write_size(&mut repr, n);
47 pad_bitvector(&mut bit_vec);
48 parse_bitvector(&bit_vec, &mut repr);
49 repr
50}
51
52#[cfg(test)]
53mod testing {
54
55 #[test]
56 fn test_write_undirected_n2() {
57 let bit_vec = vec![0, 1, 1, 0];
58 let repr = super::write_graph6(bit_vec, 2, false);
59 assert_eq!(repr, "A_");
60 }
61
62 #[test]
63 fn test_write_directed_n2_mirror() {
64 let bit_vec = vec![0, 1, 1, 0];
65 let repr = super::write_graph6(bit_vec, 2, true);
66 assert_eq!(repr, "&AW");
67 }
68
69 #[test]
70 fn test_write_directed_n2_unmirrored() {
71 let bit_vec = vec![0, 0, 1, 0];
72 let repr = super::write_graph6(bit_vec, 2, true);
73 assert_eq!(repr, "&AG");
74 }
75}