use std::{fmt::{self, Arguments}, io::{self, ErrorKind}, marker::PhantomData};
use crate::{Priority, SyslogDestination, error::SyRes, formatters::SyslogFormatter};
pub trait SyStreamSyslogApi<F: SyslogFormatter, D: SyslogDestination>
{
type SYSLOG<'t>;
fn syslog<'t>(syslog: Self::SYSLOG<'t>, pri: Priority, fmt: F) -> SyRes<()>;
}
pub struct SyStream<'t, PRI, D, F, S>
where PRI: SyStreamPri, D: SyslogDestination, F: SyslogFormatter, S: SyStreamSyslogApi<F, D>
{
pub(crate) s: Option<S::SYSLOG<'t>>,
pub(crate) _p: PhantomData<PRI>,
pub(crate) _p1: PhantomData<F>,
pub(crate) _p2: PhantomData<D>,
}
impl<'t, PRI: SyStreamPri, D: SyslogDestination, F: SyslogFormatter, S: SyStreamSyslogApi<F, D>> fmt::Write
for SyStream<'t, PRI, D, F, S>
{
fn write_str(&mut self, s: &str) -> fmt::Result
{
let s = s.to_string();
return
S::syslog( self.s.take().unwrap() , PRI::PRIO, s.into())
.map_err(|_e|
fmt::Error
);
}
fn write_fmt(self: &mut Self, args: Arguments<'_>) -> fmt::Result
{
if let Some(s) = args.as_str()
{
return
S::syslog( self.s.take().unwrap() , PRI::PRIO, s.into())
.map_err(|_| fmt::Error );
}
else
{
return
S::syslog( self.s.take().unwrap() , PRI::PRIO, args.to_string().into())
.map_err(|_| fmt::Error );
}
}
}
impl<'t, PRI: SyStreamPri, D: SyslogDestination, F: SyslogFormatter, S: SyStreamSyslogApi<F, D>> io::Write
for SyStream<'t, PRI, D, F, S>
{
fn write(&mut self, buf: &[u8]) -> io::Result<usize>
{
let s = str::from_utf8(buf).unwrap().to_string();
let n = s.len();
return
S::syslog( self.s.take().unwrap() , PRI::PRIO, s.into())
.map_err(|e|
io::Error::new(ErrorKind::Other, e.to_string())
)
.map(|_| n);
}
fn flush(&mut self) -> io::Result<()>
{
return Ok(());
}
}
pub trait SyStreamPri
{
const PRIO: Priority;
}
pub struct SyStreamPriErr;
impl SyStreamPri for SyStreamPriErr
{
const PRIO: Priority = Priority::LOG_ERR;
}
pub struct SyStreamPriDebug;
impl SyStreamPri for SyStreamPriDebug
{
const PRIO: Priority = Priority::LOG_DEBUG;
}
pub struct SyStreamPriAlert;
impl SyStreamPri for SyStreamPriAlert
{
const PRIO: Priority = Priority::LOG_ALERT;
}
pub struct SyStreamPriCrit;
impl SyStreamPri for SyStreamPriCrit
{
const PRIO: Priority = Priority::LOG_CRIT;
}
pub struct SyStreamPriEmerg;
impl SyStreamPri for SyStreamPriEmerg
{
const PRIO: Priority = Priority::LOG_EMERG;
}
pub struct SyStreamPriInfo;
impl SyStreamPri for SyStreamPriInfo
{
const PRIO: Priority = Priority::LOG_INFO;
}
pub struct SyStreamPriNotice;
impl SyStreamPri for SyStreamPriNotice
{
const PRIO: Priority = Priority::LOG_NOTICE;
}
pub struct SyStreamPriWarning;
impl SyStreamPri for SyStreamPriWarning
{
const PRIO: Priority = Priority::LOG_WARNING;
}