use serde::{Deserialize, Serialize};
use std::fmt;
use std::str::FromStr;
#[derive(
Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Serialize, Deserialize,
)]
#[serde(rename_all = "lowercase")]
pub enum Level {
Debug,
#[default]
Info,
Warning,
Error,
Fatal,
}
impl Level {
pub const fn as_str(self) -> &'static str {
match self {
Level::Debug => "debug",
Level::Info => "info",
Level::Warning => "warning",
Level::Error => "error",
Level::Fatal => "fatal",
}
}
}
impl fmt::Display for Level {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}
impl FromStr for Level {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.trim().to_ascii_lowercase().as_str() {
"debug" | "trace" => Ok(Level::Debug),
"info" => Ok(Level::Info),
"warn" | "warning" => Ok(Level::Warning),
"error" => Ok(Level::Error),
"fatal" | "critical" => Ok(Level::Fatal),
_ => Err(()),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn ordering_is_severity_ordering() {
assert!(Level::Debug < Level::Info);
assert!(Level::Info < Level::Warning);
assert!(Level::Warning < Level::Error);
assert!(Level::Error < Level::Fatal);
}
#[test]
fn serializes_lowercase() {
let json = serde_json::to_string(&Level::Warning).unwrap();
assert_eq!(json, "\"warning\"");
}
#[test]
fn parse_aliases() {
assert_eq!(Level::from_str("WARN").unwrap(), Level::Warning);
assert_eq!(Level::from_str("trace").unwrap(), Level::Debug);
assert_eq!(Level::from_str("critical").unwrap(), Level::Fatal);
assert!(Level::from_str("nope").is_err());
}
}