1use super::{Graph, VertexId};
2use crate::changestore::*;
3use crate::pristine::{Base32, GraphTxnT, Position};
4use crate::{HashMap, HashSet};
5use std::io::Write;
6
7impl Graph {
8 #[allow(dead_code)]
10 pub fn debug<W: Write, T: GraphTxnT, P: ChangeStore>(
11 &self,
12 changes: &P,
13 txn: &T,
14 channel: &T::Graph,
15 add_others: bool,
16 introduced_by: bool,
17 mut w: W,
18 ) -> Result<(), std::io::Error> {
19 writeln!(w, "digraph {{")?;
20 let mut buf = Vec::new();
21 let mut cache = HashMap::default();
22 if add_others {
23 for (line, i) in self.lines.iter().zip(0..) {
24 cache.insert(
25 Position {
26 change: line.vertex.change,
27 pos: line.vertex.start,
28 },
29 i,
30 );
31 }
32 }
33 let mut others = HashSet::default();
34 for (line, i) in self.lines.iter().zip(0..) {
35 buf.resize(line.vertex.end - line.vertex.start, 0);
36 changes
37 .get_contents(
38 |h| txn.get_external(&h).ok().map(|x| x.into()),
39 line.vertex,
40 &mut buf,
41 )
42 .unwrap();
43 let contents = &buf;
44 let contents = format!(
46 "{:?}",
47 if let Ok(contents) = std::str::from_utf8(contents) {
48 contents.chars().take(100).collect()
49 } else {
50 "<INVALID UTF8>".to_string()
51 }
52 );
53 let contents = contents.split_at(contents.len() - 1).0.split_at(1).1;
55 writeln!(
56 w,
57 "n_{}[label=\"{}({}): {}.[{};{}[: {}\"];",
58 i,
59 i,
60 line.scc,
61 line.vertex.change.to_base32(),
62 line.vertex.start.0,
63 line.vertex.end.0,
64 contents
65 )?;
66
67 if add_others && !line.vertex.is_root() {
68 for v in crate::pristine::iter_adj_all(txn, channel, line.vertex).unwrap() {
69 let v = v.unwrap();
70 if let Some(dest) = cache.get(&v.dest()) {
71 writeln!(
72 w,
73 "n_{} -> n_{}[color=red,label=\"{:?}{}{}\"];",
74 i,
75 dest,
76 v.flag().bits(),
77 if introduced_by { " " } else { "" },
78 if introduced_by {
79 v.introduced_by().to_base32()
80 } else {
81 String::new()
82 }
83 )?;
84 } else {
85 if !others.contains(&v.dest()) {
86 others.insert(v.dest());
87 writeln!(
88 w,
89 "n_{}_{}[label=\"{}.{}\",color=red];",
90 v.dest().change.to_base32(),
91 v.dest().pos.0,
92 v.dest().change.to_base32(),
93 v.dest().pos.0
94 )?;
95 }
96 writeln!(
97 w,
98 "n_{} -> n_{}_{}[color=red,label=\"{:?}{}{}\"];",
99 i,
100 v.dest().change.to_base32(),
101 v.dest().pos.0,
102 v.flag().bits(),
103 if introduced_by { " " } else { "" },
104 if introduced_by {
105 v.introduced_by().to_base32()
106 } else {
107 String::new()
108 }
109 )?;
110 }
111 }
112 }
113 for &(edge, VertexId(j)) in (self.children
114 [line.children..line.children + line.n_children])
115 .iter()
116 .chain(line.extra.iter())
117 {
118 if let Some(ref edge) = edge {
119 writeln!(
120 w,
121 "n_{}->n_{}[label=\"{:?}{}{}\"];",
122 i,
123 j,
124 edge.flag().bits(),
125 if introduced_by { " " } else { "" },
126 if introduced_by {
127 edge.introduced_by().to_base32()
128 } else {
129 String::new()
130 }
131 )?
132 } else {
133 writeln!(w, "n_{}->n_{}[label=\"none\"];", i, j)?
134 }
135 }
136 }
137 writeln!(w, "}}")?;
138 Ok(())
139 }
140
141 #[allow(dead_code)]
142 pub fn debug_raw<W: Write>(&self, mut w: W) -> Result<(), std::io::Error> {
143 writeln!(w, "digraph {{")?;
144 for (line, i) in self.lines.iter().zip(0..) {
145 writeln!(
147 w,
148 "n_{}[label=\"{}(scc {}): {}.[{};{}[\"];",
149 i,
150 i,
151 line.scc,
152 line.vertex.change.to_base32(),
153 line.vertex.start.0,
154 line.vertex.end.0,
155 )?;
156
157 for &(edge, VertexId(j)) in self.children
158 [line.children..line.children + line.n_children]
159 .iter()
160 .chain(line.extra.iter())
161 {
162 if let Some(ref edge) = edge {
163 writeln!(
164 w,
165 "n_{}->n_{}[label=\"{:?} {}\"];",
166 i,
167 j,
168 edge.flag().bits(),
169 edge.introduced_by().to_base32()
170 )?
171 } else {
172 writeln!(w, "n_{}->n_{}[label=\"none\"];", i, j)?
173 }
174 }
175 }
176 writeln!(w, "}}")?;
177 Ok(())
178 }
179}