miden_diagnostics/
emitter.rs1use parking_lot::Mutex;
2
3use crate::term::termcolor::*;
4
5pub trait Emitter: Send + Sync {
14 fn buffer(&self) -> Buffer;
16 fn print(&self, buffer: Buffer) -> std::io::Result<()>;
18}
19
20pub struct DefaultEmitter {
23 writer: BufferWriter,
24}
25impl DefaultEmitter {
26 pub fn new(color: ColorChoice) -> Self {
28 let writer = BufferWriter::stderr(color);
29 Self { writer }
30 }
31}
32impl Emitter for DefaultEmitter {
33 #[inline(always)]
34 fn buffer(&self) -> Buffer {
35 self.writer.buffer()
36 }
37
38 #[inline(always)]
39 fn print(&self, buffer: Buffer) -> std::io::Result<()> {
40 self.writer.print(&buffer)
41 }
42}
43
44#[derive(Default)]
49pub struct CaptureEmitter {
50 buffer: Mutex<Vec<u8>>,
51}
52impl CaptureEmitter {
53 #[inline]
55 pub fn new() -> Self {
56 Self::default()
57 }
58
59 pub fn captured(&self) -> String {
60 let buf = self.buffer.lock();
61 String::from_utf8_lossy(buf.as_slice()).into_owned()
62 }
63}
64impl Emitter for CaptureEmitter {
65 #[inline]
66 fn buffer(&self) -> Buffer {
67 Buffer::no_color()
68 }
69
70 #[inline]
71 fn print(&self, buffer: Buffer) -> std::io::Result<()> {
72 let mut bytes = buffer.into_inner();
73 let mut buf = self.buffer.lock();
74 buf.append(&mut bytes);
75 Ok(())
76 }
77}
78
79#[derive(Clone, Copy, Default)]
84pub struct NullEmitter {
85 ansi: bool,
86}
87impl NullEmitter {
88 pub fn new(color: ColorChoice) -> Self {
89 let ansi = match color {
90 ColorChoice::Never => false,
91 ColorChoice::Always | ColorChoice::AlwaysAnsi => true,
92 ColorChoice::Auto => atty::is(atty::Stream::Stdout),
93 };
94 Self { ansi }
95 }
96}
97impl Emitter for NullEmitter {
98 #[inline(always)]
99 fn buffer(&self) -> Buffer {
100 if self.ansi {
101 Buffer::ansi()
102 } else {
103 Buffer::no_color()
104 }
105 }
106
107 #[inline(always)]
108 fn print(&self, _buffer: Buffer) -> std::io::Result<()> {
109 Ok(())
110 }
111}