1use crate::Graph;
6use core::fmt::{self, Formatter, Result, Write};
7
8pub struct Dot<'a, Arg>(pub &'a Graph<Arg>);
11
12impl<Arg> Dot<'_, Arg> {
13 fn graph_fmt<AF>(&self, f: &mut Formatter<'_>, argfmtf: AF) -> Result
14 where
15 AF: Fn(&Arg, &mut Formatter<'_>) -> Result,
16 {
17 writeln!(f, "digraph {{")?;
18
19 for (h, i) in &self.0.events {
21 writeln!(
22 f,
23 " \"{h}\" [label=\"{h}\\n{}:{}\"];",
24 i.cmd,
25 Escaped(FnFmt(&i.arg, &argfmtf)),
26 h = h,
27 )?;
28 }
29
30 for (h, i) in &self.0.events {
32 for dep in &i.deps {
33 writeln!(f, " \"{}\" -> \"{}\";", h, dep)?;
34 }
35 }
36
37 for (nstate, deps) in &self.0.nstates {
39 writeln!(f, " subgraph \"cluster_{}\" {{", Escaped(&nstate))?;
40 for dep in deps {
41 writeln!(f, " \"{}\";", dep)?;
42 }
43 writeln!(f, " }}")?;
44 }
45
46 writeln!(f, "}}")
47 }
48}
49
50impl<Arg: fmt::Display> fmt::Display for Dot<'_, Arg> {
51 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
52 self.graph_fmt(f, fmt::Display::fmt)
53 }
54}
55
56impl<Arg: fmt::Debug> fmt::Debug for Dot<'_, Arg> {
57 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
58 self.graph_fmt(f, fmt::Debug::fmt)
59 }
60}
61
62struct Escaper<W>(W);
64
65impl<W> fmt::Write for Escaper<W>
66where
67 W: fmt::Write,
68{
69 fn write_str(&mut self, s: &str) -> Result {
70 for c in s.chars() {
71 self.write_char(c)?;
72 }
73 Ok(())
74 }
75
76 fn write_char(&mut self, c: char) -> Result {
77 match c {
78 '"' | '\\' => self.0.write_char('\\')?,
79 '\n' => return self.0.write_str("\\l"),
81 _ => {}
82 }
83 self.0.write_char(c)
84 }
85}
86
87struct Escaped<T>(T);
89
90impl<T> fmt::Display for Escaped<T>
91where
92 T: fmt::Display,
93{
94 fn fmt(&self, f: &mut Formatter) -> Result {
95 if f.alternate() {
96 writeln!(&mut Escaper(f), "{:#}", &self.0)
97 } else {
98 write!(&mut Escaper(f), "{}", &self.0)
99 }
100 }
101}
102
103struct FnFmt<'a, T, F>(&'a T, F);
105
106impl<'a, T, F> fmt::Display for FnFmt<'a, T, F>
107where
108 F: Fn(&'a T, &mut Formatter<'_>) -> Result,
109{
110 fn fmt(&self, f: &mut Formatter) -> Result {
111 self.1(self.0, f)
112 }
113}