use std::fmt;
use std::io;
use termcolor::{Color, ColorSpec};
pub trait Print {
fn write_str(&mut self, s: &str) -> io::Result<()>;
fn newline(&mut self) -> io::Result<()> {
self.write_str("\n")
}
fn start_line(&mut self, binary_offset: Option<usize>) {
let _ = binary_offset;
}
fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> io::Result<()> {
struct Adapter<'a, T: ?Sized + 'a> {
inner: &'a mut T,
error: io::Result<()>,
}
impl<T: Print + ?Sized> fmt::Write for Adapter<'_, T> {
fn write_str(&mut self, s: &str) -> fmt::Result {
match self.inner.write_str(s) {
Ok(()) => Ok(()),
Err(e) => {
self.error = Err(e);
Err(fmt::Error)
}
}
}
}
let mut output = Adapter {
inner: self,
error: Ok(()),
};
match fmt::write(&mut output, args) {
Ok(()) => Ok(()),
Err(..) => output.error,
}
}
fn print_custom_section(
&mut self,
name: &str,
binary_offset: usize,
data: &[u8],
) -> io::Result<bool> {
let _ = (name, binary_offset, data);
Ok(false)
}
fn start_literal(&mut self) -> io::Result<()> {
Ok(())
}
fn start_name(&mut self) -> io::Result<()> {
Ok(())
}
fn start_keyword(&mut self) -> io::Result<()> {
Ok(())
}
fn start_type(&mut self) -> io::Result<()> {
Ok(())
}
fn start_comment(&mut self) -> io::Result<()> {
Ok(())
}
fn reset_color(&mut self) -> io::Result<()> {
Ok(())
}
fn supports_async_color(&self) -> bool {
false
}
}
pub struct PrintIoWrite<T>(pub T);
impl<T> Print for PrintIoWrite<T>
where
T: io::Write,
{
fn write_str(&mut self, s: &str) -> io::Result<()> {
self.0.write_all(s.as_bytes())
}
}
pub struct PrintFmtWrite<T>(pub T);
impl<T> Print for PrintFmtWrite<T>
where
T: fmt::Write,
{
fn write_str(&mut self, s: &str) -> io::Result<()> {
match self.0.write_str(s) {
Ok(()) => Ok(()),
Err(fmt::Error) => Err(io::Error::new(
io::ErrorKind::Other,
"failed to write string",
)),
}
}
}
pub struct PrintTermcolor<T>(pub T);
impl<T> Print for PrintTermcolor<T>
where
T: termcolor::WriteColor,
{
fn write_str(&mut self, s: &str) -> io::Result<()> {
self.0.write_all(s.as_bytes())
}
fn start_name(&mut self) -> io::Result<()> {
self.0
.set_color(ColorSpec::new().set_fg(Some(Color::Magenta)))
}
fn start_literal(&mut self) -> io::Result<()> {
self.0.set_color(ColorSpec::new().set_fg(Some(Color::Red)))
}
fn start_keyword(&mut self) -> io::Result<()> {
self.0.set_color(
ColorSpec::new()
.set_fg(Some(Color::Yellow))
.set_bold(true)
.set_intense(true),
)
}
fn start_type(&mut self) -> io::Result<()> {
self.0.set_color(
ColorSpec::new()
.set_fg(Some(Color::Green))
.set_bold(true)
.set_intense(true),
)
}
fn start_comment(&mut self) -> io::Result<()> {
self.0.set_color(ColorSpec::new().set_fg(Some(Color::Cyan)))
}
fn reset_color(&mut self) -> io::Result<()> {
self.0.reset()
}
fn supports_async_color(&self) -> bool {
self.0.supports_color() && !self.0.is_synchronous()
}
}