use serde::{Deserialize, Serialize};
use std::{convert::TryFrom, error::Error, fmt, str::FromStr};
#[derive(Debug, Clone)]
pub struct ParseLogLevelError {
pub invalid_value: String,
}
impl ParseLogLevelError {
pub fn new(invalid_value: &str) -> Self {
ParseLogLevelError {
invalid_value: invalid_value.to_string(),
}
}
}
impl fmt::Display for ParseLogLevelError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Invalid log level: {}", self.invalid_value)
}
}
impl Error for ParseLogLevelError {}
#[derive(
Clone,
Copy,
Debug,
Deserialize,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
Serialize,
)]
pub enum LogLevel {
ALL,
NONE,
DISABLED,
DEBUG,
TRACE,
VERBOSE,
INFO,
WARN,
ERROR,
FATAL,
CRITICAL,
}
impl LogLevel {
pub fn includes(self, other: LogLevel) -> bool {
match self {
LogLevel::ALL => true, LogLevel::NONE => false, _ => self.to_numeric() >= other.to_numeric(), }
}
pub fn to_numeric(self) -> u8 {
match self {
LogLevel::ALL => 0,
LogLevel::NONE => 1,
LogLevel::DISABLED => 2,
LogLevel::DEBUG => 3,
LogLevel::TRACE => 4,
LogLevel::VERBOSE => 5,
LogLevel::INFO => 6,
LogLevel::WARN => 7,
LogLevel::ERROR => 8,
LogLevel::FATAL => 9,
LogLevel::CRITICAL => 10,
}
}
pub fn from_numeric(value: u8) -> Option<Self> {
match value {
0 => Some(LogLevel::ALL),
1 => Some(LogLevel::NONE),
2 => Some(LogLevel::DISABLED),
3 => Some(LogLevel::DEBUG),
4 => Some(LogLevel::TRACE),
5 => Some(LogLevel::VERBOSE),
6 => Some(LogLevel::INFO),
7 => Some(LogLevel::WARN),
8 => Some(LogLevel::ERROR),
9 => Some(LogLevel::FATAL),
10 => Some(LogLevel::CRITICAL),
_ => None,
}
}
}
impl FromStr for LogLevel {
type Err = ParseLogLevelError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_uppercase().as_str() {
"ALL" => Ok(LogLevel::ALL),
"NONE" => Ok(LogLevel::NONE),
"DISABLED" => Ok(LogLevel::DISABLED),
"DEBUG" => Ok(LogLevel::DEBUG),
"TRACE" => Ok(LogLevel::TRACE),
"VERBOSE" => Ok(LogLevel::VERBOSE),
"INFO" => Ok(LogLevel::INFO),
"WARN" => Ok(LogLevel::WARN),
"ERROR" => Ok(LogLevel::ERROR),
"FATAL" => Ok(LogLevel::FATAL),
"CRITICAL" => Ok(LogLevel::CRITICAL),
_ => Err(ParseLogLevelError::new(s)),
}
}
}
impl TryFrom<String> for LogLevel {
type Error = ParseLogLevelError;
fn try_from(value: String) -> Result<Self, Self::Error> {
LogLevel::from_str(&value)
}
}
impl fmt::Display for LogLevel {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let level_str = match self {
LogLevel::ALL => "ALL",
LogLevel::NONE => "NONE",
LogLevel::DISABLED => "DISABLED",
LogLevel::DEBUG => "DEBUG",
LogLevel::TRACE => "TRACE",
LogLevel::VERBOSE => "VERBOSE",
LogLevel::INFO => "INFO",
LogLevel::WARN => "WARN",
LogLevel::ERROR => "ERROR",
LogLevel::FATAL => "FATAL",
LogLevel::CRITICAL => "CRITICAL",
};
write!(f, "{}", level_str)
}
}
impl Default for LogLevel {
fn default() -> Self {
LogLevel::INFO
}
}