use std::io;
use std::io::{stdout, Write};
use std::sync::Arc;
use crate::console::component::ConsoleSendable;
use crate::console::ConsoleMessage;
pub trait ConsoleReceiver {
fn send(&self, component: &dyn ConsoleSendable) -> io::Result<()>;
}
pub struct ConsoleSender {
console: Box<dyn ConsoleReceiver>,
format: Option<Arc<dyn Fn(&dyn ConsoleSendable) -> ConsoleMessage + Send + Sync>>,
}
impl ConsoleSender {
pub fn new<R: ConsoleReceiver + 'static>(receiver: R) -> ConsoleSender {
ConsoleSender {
console: Box::new(receiver),
format: None,
}
}
pub fn set_format<F>(&mut self, formatter: F)
where
F: Fn(&dyn ConsoleSendable) -> ConsoleMessage + Send + Sync + 'static
{
self.format = Some(Arc::new(formatter));
}
pub fn send<M: ConsoleSendable>(&self, msg: M) -> io::Result<()> {
if let Some(formatter) = &self.format {
self.console.send(&formatter(&msg))
} else {
self.console.send(&msg)
}
}
pub fn send_ref<M: ConsoleSendable>(&self, msg: &M) -> io::Result<()> {
if let Some(formatter) = &self.format {
self.console.send(&formatter(msg))
} else {
self.console.send(msg)
}
}
}
impl ConsoleReceiver for io::Stdout {
fn send(&self, msg: &dyn ConsoleSendable) -> io::Result<()> {
let mut stdout = stdout();
writeln!(stdout, "{}", msg)?;
Ok(())
}
}
impl ConsoleReceiver for ConsoleSender {
fn send(&self, msg: &dyn ConsoleSendable) -> io::Result<()> {
self.console.send(msg)
}
}