use std::borrow::Cow;
use chrono::Local;
use crate::{CBRACE_SEM, OBRACE, Priority, RFC3164_MAX_PAYLOAD_LEN, SyslogMsgPriFac, WSPACE, truncate, truncate_n};
use super::{SyslogFormatted, SyslogFormatter};
#[derive(Debug, Clone)]
#[repr(transparent)]
pub struct FormatRfc3146(Cow<'static, str>);
unsafe impl Send for FormatRfc3146 {}
impl From<String> for FormatRfc3146
{
fn from(value: String) -> FormatRfc3146
{
return Self(Cow::Owned(value));
}
}
impl From<&'static str> for FormatRfc3146
{
fn from(value: &'static str) -> FormatRfc3146
{
return FormatRfc3146(Cow::Borrowed(value));
}
}
impl SyslogFormatter for FormatRfc3146
{
fn vsyslog1_format(&self, _max_msg_size: usize, prifac: SyslogMsgPriFac, progname: &str, pid: Option<&str>) -> SyslogFormatted
{
let timedate = Local::now().format("%h %e %T").to_string();
let msg_payload = truncate_n(&self.0, RFC3164_MAX_PAYLOAD_LEN);
let msg_payload_final =
if msg_payload.ends_with("\n") == true
{
truncate(&msg_payload)
}
else
{
&msg_payload
};
let msg_pri =
[
"<", prifac.get_val().to_string().as_str(), ">"
]
.concat();
let msg_pid =
if let Some(p) = pid
{
[OBRACE, p, CBRACE_SEM].concat()
}
else
{
[""].concat()
};
let msg_pkt =
[
timedate.as_str(),
WSPACE, progname,
msg_pid.as_str(),
WSPACE, msg_payload_final
]
.concat();
return
SyslogFormatted
{
msg_header: Some(msg_pri),
msg_payload: msg_pkt,
full_msg: None
};
}
}
#[cfg(test)]
mod test_rfc3146
{
use crate::LogFacility;
use super::*;
#[test]
fn test_1()
{
let msg = FormatRfc3146::from("test string!");
let prifac = SyslogMsgPriFac::set_facility(Priority::LOG_ERR, LogFacility::LOG_DAEMON);
let mut res = msg.vsyslog1_format(1024, prifac, "testprog", Some("102"));
assert_eq!(res.msg_header.as_ref().map(|f| f.as_str()), Some("<27>"));
let fullmsg = res.get_full_msg();
println!("{}", fullmsg);
assert_eq!(fullmsg.find("testprog"), Some(20));
assert_eq!(fullmsg.find("[102]"), Some(28));
assert_eq!(fullmsg.find("]:"), Some(32));
assert_eq!(fullmsg.find("test string!"), Some(35));
}
}