use crate::error::{Logger2Error, Result};
use serde::{Deserialize, Serialize};
use std::fmt;
use std::str::FromStr;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum Level {
Emergency,
Alert,
Critical,
Error,
Warning,
Notice,
Info,
Debug,
Trace,
}
impl Level {
pub const ALL: [Level; 9] = [
Level::Emergency,
Level::Alert,
Level::Critical,
Level::Error,
Level::Warning,
Level::Notice,
Level::Info,
Level::Debug,
Level::Trace,
];
pub fn severity(self) -> u8 {
match self {
Level::Emergency => 0,
Level::Alert => 1,
Level::Critical => 2,
Level::Error => 3,
Level::Warning => 4,
Level::Notice => 5,
Level::Info => 6,
Level::Debug | Level::Trace => 7,
}
}
pub fn as_str(self) -> &'static str {
match self {
Level::Emergency => "emergency",
Level::Alert => "alert",
Level::Critical => "critical",
Level::Error => "error",
Level::Warning => "warning",
Level::Notice => "notice",
Level::Info => "info",
Level::Debug => "debug",
Level::Trace => "trace",
}
}
pub fn label(self) -> &'static str {
match self {
Level::Emergency => "EMERG",
Level::Alert => "ALERT",
Level::Critical => "CRIT",
Level::Error => "ERROR",
Level::Warning => "WARN",
Level::Notice => "NOTICE",
Level::Info => "INFO",
Level::Debug => "DEBUG",
Level::Trace => "TRACE",
}
}
pub fn from_severity(sev: u8) -> Level {
match sev {
0 => Level::Emergency,
1 => Level::Alert,
2 => Level::Critical,
3 => Level::Error,
4 => Level::Warning,
5 => Level::Notice,
6 => Level::Info,
_ => Level::Debug,
}
}
}
impl fmt::Display for Level {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.as_str())
}
}
impl FromStr for Level {
type Err = Logger2Error;
fn from_str(s: &str) -> Result<Self> {
match s.to_ascii_lowercase().as_str() {
"emerg" | "emergency" | "panic" => Ok(Level::Emergency),
"alert" => Ok(Level::Alert),
"crit" | "critical" => Ok(Level::Critical),
"err" | "error" => Ok(Level::Error),
"warn" | "warning" => Ok(Level::Warning),
"notice" => Ok(Level::Notice),
"info" | "information" => Ok(Level::Info),
"debug" => Ok(Level::Debug),
"trace" => Ok(Level::Trace),
other => Err(Logger2Error::UnknownLevel(other.to_string())),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum Facility {
Kern,
User,
Mail,
Daemon,
Auth,
Syslog,
Lpr,
News,
Uucp,
Cron,
AuthPriv,
Ftp,
Ntp,
Security,
Console,
SolarisCron,
Local0,
Local1,
Local2,
Local3,
Local4,
Local5,
Local6,
Local7,
}
impl Facility {
pub fn code(self) -> u8 {
match self {
Facility::Kern => 0,
Facility::User => 1,
Facility::Mail => 2,
Facility::Daemon => 3,
Facility::Auth => 4,
Facility::Syslog => 5,
Facility::Lpr => 6,
Facility::News => 7,
Facility::Uucp => 8,
Facility::Cron => 9,
Facility::AuthPriv => 10,
Facility::Ftp => 11,
Facility::Ntp => 12,
Facility::Security => 13,
Facility::Console => 14,
Facility::SolarisCron => 15,
Facility::Local0 => 16,
Facility::Local1 => 17,
Facility::Local2 => 18,
Facility::Local3 => 19,
Facility::Local4 => 20,
Facility::Local5 => 21,
Facility::Local6 => 22,
Facility::Local7 => 23,
}
}
pub fn as_str(self) -> &'static str {
match self {
Facility::Kern => "kern",
Facility::User => "user",
Facility::Mail => "mail",
Facility::Daemon => "daemon",
Facility::Auth => "auth",
Facility::Syslog => "syslog",
Facility::Lpr => "lpr",
Facility::News => "news",
Facility::Uucp => "uucp",
Facility::Cron => "cron",
Facility::AuthPriv => "authpriv",
Facility::Ftp => "ftp",
Facility::Ntp => "ntp",
Facility::Security => "security",
Facility::Console => "console",
Facility::SolarisCron => "solaris-cron",
Facility::Local0 => "local0",
Facility::Local1 => "local1",
Facility::Local2 => "local2",
Facility::Local3 => "local3",
Facility::Local4 => "local4",
Facility::Local5 => "local5",
Facility::Local6 => "local6",
Facility::Local7 => "local7",
}
}
}
impl fmt::Display for Facility {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.as_str())
}
}
impl FromStr for Facility {
type Err = Logger2Error;
fn from_str(s: &str) -> Result<Self> {
match s.to_ascii_lowercase().replace('_', "-").as_str() {
"kern" => Ok(Facility::Kern),
"user" => Ok(Facility::User),
"mail" => Ok(Facility::Mail),
"daemon" => Ok(Facility::Daemon),
"auth" => Ok(Facility::Auth),
"syslog" => Ok(Facility::Syslog),
"lpr" => Ok(Facility::Lpr),
"news" => Ok(Facility::News),
"uucp" => Ok(Facility::Uucp),
"cron" => Ok(Facility::Cron),
"authpriv" | "auth-priv" => Ok(Facility::AuthPriv),
"ftp" => Ok(Facility::Ftp),
"ntp" => Ok(Facility::Ntp),
"security" => Ok(Facility::Security),
"console" => Ok(Facility::Console),
"solaris-cron" => Ok(Facility::SolarisCron),
"local0" => Ok(Facility::Local0),
"local1" => Ok(Facility::Local1),
"local2" => Ok(Facility::Local2),
"local3" => Ok(Facility::Local3),
"local4" => Ok(Facility::Local4),
"local5" => Ok(Facility::Local5),
"local6" => Ok(Facility::Local6),
"local7" => Ok(Facility::Local7),
other => Err(Logger2Error::UnknownFacility(other.to_string())),
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct Priority {
pub facility: Facility,
pub level: Level,
}
impl Priority {
pub fn pri(self) -> u8 {
self.facility.code() * 8 + self.level.severity()
}
}
impl fmt::Display for Priority {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}.{}", self.facility, self.level)
}
}
impl FromStr for Priority {
type Err = Logger2Error;
fn from_str(s: &str) -> Result<Self> {
let (fac, lvl) = s
.split_once('.')
.ok_or_else(|| Logger2Error::InvalidPriority(s.to_string()))?;
let facility = Facility::from_str(fac)
.map_err(|_| Logger2Error::InvalidPriority(s.to_string()))?;
let level =
Level::from_str(lvl).map_err(|_| Logger2Error::InvalidPriority(s.to_string()))?;
Ok(Priority { facility, level })
}
}