use serde::{Deserialize, Serialize};
#[derive(
Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, Default,
)]
#[serde(rename_all = "lowercase")]
pub enum Severity {
#[default]
Info,
Warning,
Error,
}
impl Severity {
pub fn as_str(self) -> &'static str {
match self {
Severity::Info => "info",
Severity::Warning => "warning",
Severity::Error => "error",
}
}
pub fn parse(s: &str) -> Option<Severity> {
match s.trim().to_ascii_lowercase().as_str() {
"info" | "ok" | "green" => Some(Severity::Info),
"warning" | "warn" | "amber" => Some(Severity::Warning),
"error" | "err" | "red" => Some(Severity::Error),
_ => None,
}
}
pub fn is_error(self) -> bool {
self == Severity::Error
}
pub fn max(self, other: Severity) -> Severity {
core::cmp::max(self, other)
}
}
pub fn worst<I: IntoIterator<Item = Severity>>(iter: I) -> Severity {
iter.into_iter().fold(Severity::Info, Severity::max)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn default_is_the_green_floor() {
assert_eq!(Severity::default(), Severity::Info);
assert!(!Severity::default().is_error());
}
#[test]
fn ordering_puts_error_on_top() {
assert!(Severity::Info < Severity::Warning);
assert!(Severity::Warning < Severity::Error);
assert_eq!(Severity::Info.max(Severity::Error), Severity::Error);
assert_eq!(Severity::Warning.max(Severity::Info), Severity::Warning);
}
#[test]
fn worst_folds_to_the_red_and_empty_is_green() {
assert_eq!(worst([]), Severity::Info, "no atoms → green");
assert_eq!(
worst([Severity::Info, Severity::Info]),
Severity::Info,
"all green → green"
);
assert_eq!(
worst([Severity::Info, Severity::Warning, Severity::Info]),
Severity::Warning
);
assert_eq!(
worst([Severity::Info, Severity::Error, Severity::Warning]),
Severity::Error,
"one red pane atom makes the pane red"
);
}
#[test]
fn tag_roundtrips_and_is_lenient() {
for s in [Severity::Info, Severity::Warning, Severity::Error] {
assert_eq!(Severity::parse(s.as_str()), Some(s), "roundtrip {s:?}");
}
assert_eq!(Severity::parse("RED"), Some(Severity::Error));
assert_eq!(Severity::parse(" warn "), Some(Severity::Warning));
assert_eq!(Severity::parse("green"), Some(Severity::Info));
assert_eq!(Severity::parse("bogus"), None);
}
#[test]
fn serde_uses_the_lowercase_tag() {
let j = serde_json::to_string(&Severity::Error).unwrap();
assert_eq!(j, "\"error\"");
let back: Severity = serde_json::from_str("\"warning\"").unwrap();
assert_eq!(back, Severity::Warning);
}
}