rivet_logger/logger/
level.rs1use std::str::FromStr;
2
3use super::LoggerError;
4
5#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
6#[repr(u16)]
7pub enum Level {
8 Debug = 100,
9 Info = 200,
10 Notice = 250,
11 Warning = 300,
12 Error = 400,
13 Critical = 500,
14 Alert = 550,
15 Emergency = 600,
16}
17
18impl Level {
19 pub const fn as_str(self) -> &'static str {
20 match self {
21 Self::Debug => "DEBUG",
22 Self::Info => "INFO",
23 Self::Notice => "NOTICE",
24 Self::Warning => "WARNING",
25 Self::Error => "ERROR",
26 Self::Critical => "CRITICAL",
27 Self::Alert => "ALERT",
28 Self::Emergency => "EMERGENCY",
29 }
30 }
31
32 pub const fn value(self) -> u16 {
33 self as u16
34 }
35
36 pub const fn from_rfc_5424(level: u8) -> Option<Self> {
37 match level {
38 7 => Some(Self::Debug),
39 6 => Some(Self::Info),
40 5 => Some(Self::Notice),
41 4 => Some(Self::Warning),
42 3 => Some(Self::Error),
43 2 => Some(Self::Critical),
44 1 => Some(Self::Alert),
45 0 => Some(Self::Emergency),
46 _ => None,
47 }
48 }
49}
50
51impl TryFrom<u16> for Level {
52 type Error = LoggerError;
53
54 fn try_from(value: u16) -> Result<Self, LoggerError> {
55 match value {
56 100 => Ok(Self::Debug),
57 200 => Ok(Self::Info),
58 250 => Ok(Self::Notice),
59 300 => Ok(Self::Warning),
60 400 => Ok(Self::Error),
61 500 => Ok(Self::Critical),
62 550 => Ok(Self::Alert),
63 600 => Ok(Self::Emergency),
64 _ => Err(LoggerError::InvalidLevelValue(value.to_string())),
65 }
66 }
67}
68
69impl FromStr for Level {
70 type Err = LoggerError;
71
72 fn from_str(s: &str) -> Result<Self, Self::Err> {
73 let normalized = s.trim().to_ascii_lowercase();
74 match normalized.as_str() {
75 "debug" => Ok(Self::Debug),
76 "info" => Ok(Self::Info),
77 "notice" => Ok(Self::Notice),
78 "warning" | "warn" => Ok(Self::Warning),
79 "error" => Ok(Self::Error),
80 "critical" => Ok(Self::Critical),
81 "alert" => Ok(Self::Alert),
82 "emergency" => Ok(Self::Emergency),
83 _ => {
84 if let Ok(value) = normalized.parse::<u16>() {
85 return value.into_level();
86 }
87 Err(LoggerError::InvalidLevelValue(s.to_string()))
88 }
89 }
90 }
91}
92
93pub trait IntoLevel {
94 fn into_level(self) -> Result<Level, LoggerError>;
95}
96
97impl IntoLevel for Level {
98 fn into_level(self) -> Result<Level, LoggerError> {
99 Ok(self)
100 }
101}
102
103impl IntoLevel for u8 {
104 fn into_level(self) -> Result<Level, LoggerError> {
105 if let Some(level) = Level::from_rfc_5424(self) {
106 return Ok(level);
107 }
108
109 Level::try_from(self as u16)
110 }
111}
112
113impl IntoLevel for u16 {
114 fn into_level(self) -> Result<Level, LoggerError> {
115 if let Some(level) = Level::from_rfc_5424(self as u8).filter(|_| self <= 7) {
116 return Ok(level);
117 }
118
119 Level::try_from(self)
120 }
121}
122
123impl IntoLevel for i32 {
124 fn into_level(self) -> Result<Level, LoggerError> {
125 if self < 0 {
126 return Err(LoggerError::InvalidLevelValue(self.to_string()));
127 }
128
129 (self as u16).into_level()
130 }
131}
132
133impl IntoLevel for &str {
134 fn into_level(self) -> Result<Level, LoggerError> {
135 self.parse()
136 }
137}
138
139impl IntoLevel for String {
140 fn into_level(self) -> Result<Level, LoggerError> {
141 self.as_str().into_level()
142 }
143}