use std::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum LogFormat {
Default,
Rfc5424,
Rfc3164,
Json,
}
impl Default for LogFormat {
fn default() -> Self {
Self::Default
}
}
impl LogFormat {
pub fn parse(s: &str) -> Result<Self, LogFormatParseError> {
let lower = s.trim().to_ascii_lowercase();
match lower.as_str() {
"" | "default" => Ok(Self::Default),
"rfc5424" => Ok(Self::Rfc5424),
"rfc3164" => Ok(Self::Rfc3164),
"json" | "ndjson" => Ok(Self::Json),
_ => Err(LogFormatParseError {
input: s.to_string(),
}),
}
}
pub fn as_str(self) -> &'static str {
match self {
Self::Default => "default",
Self::Rfc5424 => "rfc5424",
Self::Rfc3164 => "rfc3164",
Self::Json => "json",
}
}
}
impl fmt::Display for LogFormat {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct LogFormatParseError {
pub input: String,
}
impl fmt::Display for LogFormatParseError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"unknown log_format '{}': expected one of default, rfc5424, rfc3164, json, ndjson",
self.input
)
}
}
impl std::error::Error for LogFormatParseError {}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn parse_known_values() {
for (input, expected) in [
("default", LogFormat::Default),
("DEFAULT", LogFormat::Default),
("", LogFormat::Default),
(" rfc5424 ", LogFormat::Rfc5424),
("RFC3164", LogFormat::Rfc3164),
("json", LogFormat::Json),
("ndjson", LogFormat::Json),
] {
assert_eq!(LogFormat::parse(input).unwrap(), expected, "input: {input}");
}
}
#[test]
fn parse_unknown_rejected() {
let err = LogFormat::parse("yaml").unwrap_err();
assert_eq!(err.input, "yaml");
assert!(err.to_string().contains("yaml"));
}
#[test]
fn display_and_as_str_match() {
for variant in [
LogFormat::Default,
LogFormat::Rfc5424,
LogFormat::Rfc3164,
LogFormat::Json,
] {
assert_eq!(variant.to_string(), variant.as_str());
assert_eq!(LogFormat::parse(variant.as_str()).unwrap(), variant);
}
}
}