use crate::service::ServiceError;
use crate::service::fallback::Fallback;
use crate::service::write::{MessageFormatter, StandardMessageFormatter};
use crate::{LoggerStatus, Message, Service};
use std::any::Any;
use std::io::BufWriter;
use std::sync::Mutex;
struct IoData<W, F>
where
W: std::io::Write + Send + Sync,
F: MessageFormatter,
{
writer: W,
formatter: F,
}
pub struct IoWrite<W, F>
where
W: std::io::Write + Send + Sync,
F: MessageFormatter,
{
writer: Mutex<IoData<W, F>>,
}
impl<W, F> IoWrite<W, F>
where
W: std::io::Write + Send + Sync,
F: MessageFormatter,
{
pub fn new(writer: W) -> Box<Self> {
Box::new(Self {
writer: Mutex::new(IoData {
writer,
formatter: Default::default(),
}),
})
}
pub fn with_formatter(writer: W, formatter: F) -> Box<Self> {
Box::new(Self {
writer: Mutex::new(IoData { writer, formatter }),
})
}
}
impl<W, F> Service for IoWrite<W, F>
where
W: std::io::Write + Send + Sync + 'static,
F: MessageFormatter + 'static,
{
fn status(&self) -> LoggerStatus {
LoggerStatus::Running
}
fn work(&self, msg: &Message) -> Result<(), ServiceError> {
let mut guard = self.writer.lock()?;
let IoData {
formatter, writer, ..
} = &mut *guard;
formatter.format_io(msg, writer)?;
Ok(())
}
fn as_any(&self) -> &dyn Any {
self
}
}
impl<W, F> Fallback for IoWrite<W, F>
where
W: std::io::Write + Send + Sync + 'static,
F: MessageFormatter + 'static,
{
fn fallback(&self, error: &ServiceError, msg: &Message) {
if let Ok(mut guard) = self.writer.lock() {
let mut out = std::io::stdout();
let _ = guard.formatter.format_io(msg, &mut out);
let _ = eprintln!("IoWriteService Fallback [Error: {}]", error);
}
}
}
#[allow(type_alias_bounds)]
pub type BoxedIo<F: MessageFormatter> = IoWrite<Box<dyn std::io::Write + Send + Sync>, F>;
#[allow(type_alias_bounds)]
pub type File<F: MessageFormatter> = IoWrite<std::fs::File, F>;
#[allow(type_alias_bounds)]
pub type BufferedFile<F: MessageFormatter> = IoWrite<BufWriter<std::fs::File>, F>;
pub type StandardBoxedIo = BoxedIo<StandardMessageFormatter>;
pub type StandardFile = File<StandardMessageFormatter>;
pub type StandardBufferedFile = BufferedFile<StandardMessageFormatter>;