1use std::io::Write;
2use std::io::{self};
3use std::sync::Arc;
4use std::sync::Mutex;
5
6#[derive(strum::Display, strum::EnumString, strum::VariantNames)]
8#[strum(serialize_all = "kebab-case")]
9#[derive(Default)]
10pub enum ReportingTarget {
11 #[strum(serialize = "stdout", serialize = "out")]
13 #[default]
14 Stdout,
15 #[strum(serialize = "stderr", serialize = "err")]
17 Stderr,
18 #[strum(disabled)]
20 Writer(Arc<Mutex<Box<dyn Write + Send>>>),
21}
22
23impl Clone for ReportingTarget {
24 fn clone(&self) -> Self {
25 match self {
26 ReportingTarget::Stdout => ReportingTarget::Stdout,
27 ReportingTarget::Stderr => ReportingTarget::Stderr,
28 ReportingTarget::Writer(writer) => ReportingTarget::Writer(writer.clone()),
29 }
30 }
31}
32
33impl std::fmt::Debug for ReportingTarget {
34 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
35 match self {
36 ReportingTarget::Stdout => write!(f, "ReportingTarget::Stdout"),
37 ReportingTarget::Stderr => write!(f, "ReportingTarget::Stderr"),
38 ReportingTarget::Writer(_) => write!(f, "ReportingTarget::Writer(..)"),
39 }
40 }
41}
42
43impl ReportingTarget {
44 #[must_use]
52 pub fn buffer() -> (Self, Arc<Mutex<Vec<u8>>>) {
53 let buffer = Arc::new(Mutex::new(Vec::new()));
54 let writer_buffer = buffer.clone();
55 let target = ReportingTarget::Writer(Arc::new(Mutex::new(Box::new(BufferWriter { buffer: writer_buffer }))));
56 (target, buffer)
57 }
58
59 pub(crate) fn resolve(&self) -> Box<dyn Write + '_> {
65 match self {
66 ReportingTarget::Stdout => Box::new(io::stdout()),
67 ReportingTarget::Stderr => Box::new(io::stderr()),
68 ReportingTarget::Writer(writer) => Box::new(LockedWriter { writer: writer.clone() }),
69 }
70 }
71}
72
73struct LockedWriter {
75 writer: Arc<Mutex<Box<dyn Write + Send>>>,
76}
77
78impl Write for LockedWriter {
79 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
80 self.writer.lock().unwrap().write(buf)
81 }
82
83 fn flush(&mut self) -> io::Result<()> {
84 self.writer.lock().unwrap().flush()
85 }
86}
87
88struct BufferWriter {
90 buffer: Arc<Mutex<Vec<u8>>>,
91}
92
93impl Write for BufferWriter {
94 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
95 self.buffer.lock().unwrap().write(buf)
96 }
97
98 fn flush(&mut self) -> io::Result<()> {
99 self.buffer.lock().unwrap().flush()
100 }
101}