use std::io::{self, Write};
use crossbeam_channel::{Receiver, Sender};
use tracing_subscriber::fmt::MakeWriter;
#[derive(Clone)]
pub struct DebugConsoleWriter {
sender: Option<Sender<String>>,
}
impl DebugConsoleWriter {
pub fn new() -> (Self, Receiver<String>) {
let (tx, rx) = crossbeam_channel::unbounded();
let writer = Self { sender: Some(tx) };
(writer, rx)
}
}
impl Write for DebugConsoleWriter {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
let message = String::from_utf8_lossy(buf);
if let Some(ref sender) = self.sender
&& sender.send(message.to_string()).is_err()
{
eprintln!("Warning: Log channel is closed, message dropped: {}", message);
}
Ok(buf.len())
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
impl<'a> MakeWriter<'a> for DebugConsoleWriter {
type Writer = Self;
fn make_writer(&'a self) -> Self::Writer {
self.clone()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_debug_console_writer_send_and_receive() {
let (mut writer, rx) = DebugConsoleWriter::new();
let msg = "Hello, mq!";
let bytes_written = writer.write(msg.as_bytes()).unwrap();
assert_eq!(bytes_written, msg.len());
let received = rx.try_recv().unwrap();
assert_eq!(received, msg);
}
#[test]
fn test_debug_console_writer_flush() {
let (mut writer, _rx) = DebugConsoleWriter::new();
assert!(writer.flush().is_ok());
}
#[test]
fn test_debug_console_writer_channel_closed() {
let (mut writer, rx) = DebugConsoleWriter::new();
drop(rx); let msg = "Should not panic";
let bytes_written = writer.write(msg.as_bytes()).unwrap();
assert_eq!(bytes_written, msg.len());
}
#[test]
fn test_make_writer_returns_clone() {
let (writer, _rx) = DebugConsoleWriter::new();
let clone = writer.make_writer();
assert!(clone.sender.is_some());
}
}