1use std::fmt;
2use std::io;
3use termcolor::{Color, ColorSpec};
4
5pub trait Print {
16 fn write_str(&mut self, s: &str) -> io::Result<()>;
20
21 fn newline(&mut self) -> io::Result<()> {
26 self.write_str("\n")
27 }
28
29 fn start_line(&mut self, binary_offset: Option<usize>) {
36 let _ = binary_offset;
37 }
38
39 fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> io::Result<()> {
41 struct Adapter<'a, T: ?Sized + 'a> {
42 inner: &'a mut T,
43 error: io::Result<()>,
44 }
45
46 impl<T: Print + ?Sized> fmt::Write for Adapter<'_, T> {
47 fn write_str(&mut self, s: &str) -> fmt::Result {
48 match self.inner.write_str(s) {
49 Ok(()) => Ok(()),
50 Err(e) => {
51 self.error = Err(e);
52 Err(fmt::Error)
53 }
54 }
55 }
56 }
57
58 let mut output = Adapter {
59 inner: self,
60 error: Ok(()),
61 };
62 match fmt::write(&mut output, args) {
63 Ok(()) => Ok(()),
64 Err(..) => output.error,
65 }
66 }
67
68 fn print_custom_section(
75 &mut self,
76 name: &str,
77 binary_offset: usize,
78 data: &[u8],
79 ) -> io::Result<bool> {
80 let _ = (name, binary_offset, data);
81 Ok(false)
82 }
83
84 fn start_literal(&mut self) -> io::Result<()> {
86 Ok(())
87 }
88
89 fn start_name(&mut self) -> io::Result<()> {
91 Ok(())
92 }
93
94 fn start_keyword(&mut self) -> io::Result<()> {
96 Ok(())
97 }
98
99 fn start_type(&mut self) -> io::Result<()> {
101 Ok(())
102 }
103
104 fn start_comment(&mut self) -> io::Result<()> {
106 Ok(())
107 }
108
109 fn reset_color(&mut self) -> io::Result<()> {
111 Ok(())
112 }
113
114 fn supports_async_color(&self) -> bool {
116 false
117 }
118}
119
120pub struct PrintIoWrite<T>(pub T);
122
123impl<T> Print for PrintIoWrite<T>
124where
125 T: io::Write,
126{
127 fn write_str(&mut self, s: &str) -> io::Result<()> {
128 self.0.write_all(s.as_bytes())
129 }
130}
131
132pub struct PrintFmtWrite<T>(pub T);
134
135impl<T> Print for PrintFmtWrite<T>
136where
137 T: fmt::Write,
138{
139 fn write_str(&mut self, s: &str) -> io::Result<()> {
140 match self.0.write_str(s) {
141 Ok(()) => Ok(()),
142 Err(fmt::Error) => Err(io::Error::new(
143 io::ErrorKind::Other,
144 "failed to write string",
145 )),
146 }
147 }
148}
149
150pub struct PrintTermcolor<T>(pub T);
152
153impl<T> Print for PrintTermcolor<T>
154where
155 T: termcolor::WriteColor,
156{
157 fn write_str(&mut self, s: &str) -> io::Result<()> {
158 self.0.write_all(s.as_bytes())
159 }
160
161 fn start_name(&mut self) -> io::Result<()> {
162 self.0
163 .set_color(ColorSpec::new().set_fg(Some(Color::Magenta)))
164 }
165
166 fn start_literal(&mut self) -> io::Result<()> {
167 self.0.set_color(ColorSpec::new().set_fg(Some(Color::Red)))
168 }
169
170 fn start_keyword(&mut self) -> io::Result<()> {
171 self.0.set_color(
172 ColorSpec::new()
173 .set_fg(Some(Color::Yellow))
174 .set_bold(true)
175 .set_intense(true),
176 )
177 }
178
179 fn start_type(&mut self) -> io::Result<()> {
180 self.0.set_color(
181 ColorSpec::new()
182 .set_fg(Some(Color::Green))
183 .set_bold(true)
184 .set_intense(true),
185 )
186 }
187
188 fn start_comment(&mut self) -> io::Result<()> {
189 self.0.set_color(ColorSpec::new().set_fg(Some(Color::Cyan)))
190 }
191
192 fn reset_color(&mut self) -> io::Result<()> {
193 self.0.reset()
194 }
195
196 fn supports_async_color(&self) -> bool {
197 self.0.supports_color() && !self.0.is_synchronous()
198 }
199}