use std::io;
use std::sync::Arc;
use crate::console::component::ConsoleSendable;
use crate::console::ConsoleMessage;
use crate::console::receiver::Console;
use std::io::{Write};
#[derive(Clone)]
pub struct ConsoleSender<T: Console + Clone + 'static> {
target: T,
format: Option<Arc<dyn Fn(&dyn ConsoleSendable) -> ConsoleMessage + Send + Sync>>,
message_logging: bool,
}
impl<T: Console + Clone + 'static> ConsoleSender<T> {
pub fn new(rx: T) -> Self {
ConsoleSender {
target: rx,
format: None,
message_logging: true,
}
}
pub fn log(&mut self, message_logging_enabled: bool) {
self.message_logging = message_logging_enabled;
}
pub fn log_format<F>(&mut self, formatter: F)
where
F: Fn(&dyn ConsoleSendable) -> ConsoleMessage + Send + Sync + 'static
{
self.format = Some(Arc::new(formatter));
}
pub fn try_send<M: ConsoleSendable>(&self, msg: M) -> io::Result<()> {
if let Some(formatter) = &self.format {
self.target.send(&formatter(&msg))
} else {
self.target.send(&msg)
}
}
pub fn send<M: ConsoleSendable>(&self, msg: M) {
if let Err(e) = self.try_send(msg) {
eprintln!("Console send error: {}", e);
}
}
pub fn send_ref<M: ConsoleSendable>(&self, msg: &M) -> io::Result<()> {
if let Some(formatter) = &self.format {
self.target.send(&formatter(msg))
} else {
self.target.send(msg)
}
}
}
#[derive(Clone)]
pub struct Stdout {
inner: Arc<std::io::Stdout>
}
impl Stdout {
pub fn writeln(&self, msg: &str) -> io::Result<()> {
let mut handle = self.inner.lock();
writeln!(handle, "{}", msg)
}
}
pub fn stdout() -> Stdout {
Stdout {
inner: Arc::new(io::stdout())
}
}
impl Console for Stdout {
fn send(&self, msg: &dyn ConsoleSendable) -> io::Result<()> {
self.writeln(&msg.to_string())
}
}