use serde::{Deserialize, Serialize};
use std::str::FromStr;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[repr(i32)]
#[derive(Default)]
pub enum Level {
Debug = 10,
#[default]
Info = 20,
Success = 25,
Warning = 30,
Error = 40,
Custom(i32), }
impl Level {
pub fn as_str(&self) -> &'static str {
match self {
Level::Debug => "debug",
Level::Info => "info",
Level::Success => "success",
Level::Warning => "warning",
Level::Error => "error",
Level::Custom(_) => "custom",
}
}
pub fn from_value(value: i32) -> Self {
match value {
10 => Level::Debug,
20 => Level::Info,
25 => Level::Success,
30 => Level::Warning,
40 => Level::Error,
v => Level::Custom(v),
}
}
pub fn value(&self) -> i32 {
match self {
Level::Debug => 10,
Level::Info => 20,
Level::Success => 25,
Level::Warning => 30,
Level::Error => 40,
Level::Custom(v) => *v,
}
}
}
impl PartialOrd for Level {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for Level {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.value().cmp(&other.value())
}
}
impl FromStr for Level {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_lowercase().as_str() {
"debug" => Ok(Level::Debug),
"info" => Ok(Level::Info),
"success" => Ok(Level::Success),
"warning" => Ok(Level::Warning),
"error" => Ok(Level::Error),
_ => Err(format!("Unknown message level: {}", s)),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_level() {
let default_level = Level::default();
assert_eq!(default_level, Level::Info);
}
#[test]
fn test_low_level() {
assert!(Level::Debug < Level::Info);
assert_eq!(Level::Debug.value(), 10);
}
#[test]
fn test_high_level() {
assert!(Level::Warning > Level::Info);
assert!(Level::Error > Level::Warning);
assert_eq!(Level::Warning.value(), 30);
assert_eq!(Level::Error.value(), 40);
}
#[test]
fn test_messages_level_from_str() {
assert_eq!(Level::from_str("debug"), Ok(Level::Debug));
assert_eq!(Level::from_str("info"), Ok(Level::Info));
assert_eq!(Level::from_str("success"), Ok(Level::Success));
assert_eq!(Level::from_str("warning"), Ok(Level::Warning));
assert_eq!(Level::from_str("error"), Ok(Level::Error));
assert_eq!(Level::from_str("DEBUG"), Ok(Level::Debug));
assert_eq!(Level::from_str("INFO"), Ok(Level::Info));
assert_eq!(Level::from_str("WARNING"), Ok(Level::Warning));
assert!(Level::from_str("invalid").is_err());
assert!(Level::from_str("").is_err());
}
#[test]
fn test_level_values() {
assert_eq!(Level::Debug.value(), 10);
assert_eq!(Level::Info.value(), 20);
assert_eq!(Level::Success.value(), 25);
assert_eq!(Level::Warning.value(), 30);
assert_eq!(Level::Error.value(), 40);
}
#[test]
fn test_custom_level() {
let custom_level = Level::Custom(29);
assert_eq!(custom_level.value(), 29);
assert_eq!(custom_level.as_str(), "custom");
let from_value = Level::from_value(29);
assert_eq!(from_value, Level::Custom(29));
}
#[test]
fn test_level_ordering_with_custom() {
let debug = Level::Debug;
let custom_low = Level::Custom(15);
let info = Level::Info;
let custom_high = Level::Custom(35);
let error = Level::Error;
assert!(custom_low > debug);
assert!(custom_low < info);
assert!(custom_high > info);
assert!(custom_high < error);
}
}