1#![warn(missing_docs)]
7
8use fidl_fuchsia_diagnostics_types_common as fdiagnostics;
9use std::str::FromStr;
10use std::{cmp, fmt};
11
12#[cfg(feature = "serde")]
13#[doc(hidden)]
14pub mod serde_ext;
15
16#[cfg_attr(feature = "serde", derive(schemars::JsonSchema))]
18#[cfg_attr(feature = "serde", serde(rename_all = "UPPERCASE"))]
19#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
20#[repr(u8)]
21pub enum Severity {
22 Trace = 0x10,
24 Debug = 0x20,
26 Info = 0x30,
28 Warn = 0x40,
30 Error = 0x50,
32 Fatal = 0x60,
34}
35
36#[cfg(feature = "serde")]
37impl serde::Serialize for Severity {
38 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
39 where
40 S: serde::Serializer,
41 {
42 serde_ext::severity::serialize(self, serializer)
43 }
44}
45
46#[cfg(feature = "serde")]
47impl<'de> serde::Deserialize<'de> for Severity {
48 fn deserialize<D>(deserializer: D) -> Result<Severity, D::Error>
49 where
50 D: serde::Deserializer<'de>,
51 {
52 serde_ext::severity::deserialize(deserializer)
53 }
54}
55
56impl Severity {
57 pub fn parse_exact(raw_severity: u8) -> (Option<u8>, Severity) {
59 if raw_severity == Severity::Trace as u8 {
60 (None, Severity::Trace)
61 } else if raw_severity == Severity::Debug as u8 {
62 (None, Severity::Debug)
63 } else if raw_severity == Severity::Info as u8 {
64 (None, Severity::Info)
65 } else if raw_severity == Severity::Warn as u8 {
66 (None, Severity::Warn)
67 } else if raw_severity == Severity::Error as u8 {
68 (None, Severity::Error)
69 } else if raw_severity == Severity::Fatal as u8 {
70 (None, Severity::Fatal)
71 } else {
72 (Some(raw_severity), Severity::from(raw_severity))
73 }
74 }
75
76 pub fn as_str(&self) -> &'static str {
78 match self {
79 Severity::Trace => "TRACE",
80 Severity::Debug => "DEBUG",
81 Severity::Info => "INFO",
82 Severity::Warn => "WARN",
83 Severity::Error => "ERROR",
84 Severity::Fatal => "FATAL",
85 }
86 }
87}
88
89macro_rules! impl_from_signed {
90 ($($type:ty),*) => {
91 $(
92 impl From<$type> for Severity {
93 fn from(value: $type) -> Severity {
94 match value {
95 ..0x00 => Severity::Trace,
96 0x00..=0x10 => Severity::Trace,
97 0x11..=0x20 => Severity::Debug,
98 0x21..=0x30 => Severity::Info,
99 0x31..=0x40 => Severity::Warn,
100 0x41..=0x50 => Severity::Error,
101 0x51.. => Severity::Fatal,
102 }
103 }
104 }
105 )*
106 }
107}
108
109macro_rules! impl_from_unsigned {
110 ($($type:ty),*) => {
111 $(
112 impl From<$type> for Severity {
113 fn from(value: $type) -> Severity {
114 match value {
115 0x00..=0x10 => Severity::Trace,
116 0x11..=0x20 => Severity::Debug,
117 0x21..=0x30 => Severity::Info,
118 0x31..=0x40 => Severity::Warn,
119 0x41..=0x50 => Severity::Error,
120 0x51.. => Severity::Fatal,
121 }
122 }
123 }
124 )*
125 }
126}
127
128impl_from_signed!(i8, i16, i32, i64, i128);
129impl_from_unsigned!(u8, u16, u32, u64, u128);
130
131impl From<log::Level> for Severity {
132 fn from(level: log::Level) -> Severity {
133 match level {
134 log::Level::Trace => Severity::Trace,
135 log::Level::Debug => Severity::Debug,
136 log::Level::Info => Severity::Info,
137 log::Level::Warn => Severity::Warn,
138 log::Level::Error => Severity::Error,
139 }
140 }
141}
142
143impl TryFrom<log::LevelFilter> for Severity {
144 type Error = ();
145 fn try_from(s: log::LevelFilter) -> Result<Severity, ()> {
146 match s {
147 log::LevelFilter::Off => Err(()),
148 log::LevelFilter::Trace => Ok(Severity::Trace),
149 log::LevelFilter::Debug => Ok(Severity::Debug),
150 log::LevelFilter::Info => Ok(Severity::Info),
151 log::LevelFilter::Warn => Ok(Severity::Warn),
152 log::LevelFilter::Error => Ok(Severity::Error),
153 }
154 }
155}
156
157impl From<Severity> for log::LevelFilter {
158 fn from(s: Severity) -> log::LevelFilter {
159 match s {
160 Severity::Trace => log::LevelFilter::Trace,
161 Severity::Debug => log::LevelFilter::Debug,
162 Severity::Info => log::LevelFilter::Info,
163 Severity::Warn => log::LevelFilter::Warn,
164 Severity::Fatal | Severity::Error => log::LevelFilter::Error,
165 }
166 }
167}
168
169impl From<Severity> for fdiagnostics::Severity {
170 fn from(s: Severity) -> fdiagnostics::Severity {
171 match s {
172 Severity::Trace => fdiagnostics::Severity::Trace,
173 Severity::Debug => fdiagnostics::Severity::Debug,
174 Severity::Info => fdiagnostics::Severity::Info,
175 Severity::Warn => fdiagnostics::Severity::Warn,
176 Severity::Error => fdiagnostics::Severity::Error,
177 Severity::Fatal => fdiagnostics::Severity::Fatal,
178 }
179 }
180}
181
182impl From<fdiagnostics::Severity> for Severity {
183 fn from(s: fdiagnostics::Severity) -> Severity {
184 match s {
185 fdiagnostics::Severity::Trace => Severity::Trace,
186 fdiagnostics::Severity::Debug => Severity::Debug,
187 fdiagnostics::Severity::Info => Severity::Info,
188 fdiagnostics::Severity::Warn => Severity::Warn,
189 fdiagnostics::Severity::Error => Severity::Error,
190 fdiagnostics::Severity::Fatal => Severity::Fatal,
191 fdiagnostics::Severity::__SourceBreaking { .. } => Severity::Info,
192 }
193 }
194}
195
196impl AsRef<str> for Severity {
197 fn as_ref(&self) -> &str {
198 self.as_str()
199 }
200}
201
202impl fmt::Display for Severity {
203 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
204 write!(f, "{}", self.as_str())
205 }
206}
207
208#[derive(thiserror::Error, Debug)]
210pub enum Error {
211 #[error("invalid severity: {0}")]
213 Invalid(String),
214}
215
216impl FromStr for Severity {
217 type Err = Error;
218 fn from_str(s: &str) -> Result<Self, Self::Err> {
219 let s = s.to_lowercase();
220 match s.as_str() {
221 "trace" => Ok(Severity::Trace),
222 "debug" => Ok(Severity::Debug),
223 "info" => Ok(Severity::Info),
224 "warn" | "warning" => Ok(Severity::Warn),
225 "error" => Ok(Severity::Error),
226 "fatal" => Ok(Severity::Fatal),
227 other => Err(Error::Invalid(other.to_string())),
228 }
229 }
230}
231
232impl PartialEq<fdiagnostics::Severity> for Severity {
233 fn eq(&self, other: &fdiagnostics::Severity) -> bool {
234 matches!(
235 (self, other),
236 (Severity::Trace, fdiagnostics::Severity::Trace)
237 | (Severity::Debug, fdiagnostics::Severity::Debug)
238 | (Severity::Info, fdiagnostics::Severity::Info)
239 | (Severity::Warn, fdiagnostics::Severity::Warn)
240 | (Severity::Error, fdiagnostics::Severity::Error)
241 | (Severity::Fatal, fdiagnostics::Severity::Fatal)
242 )
243 }
244}
245
246impl PartialOrd<fdiagnostics::Severity> for Severity {
247 fn partial_cmp(&self, other: &fdiagnostics::Severity) -> Option<cmp::Ordering> {
248 let other = match other {
249 fdiagnostics::Severity::Trace => Severity::Trace,
250 fdiagnostics::Severity::Debug => Severity::Debug,
251 fdiagnostics::Severity::Info => Severity::Info,
252 fdiagnostics::Severity::Warn => Severity::Warn,
253 fdiagnostics::Severity::Error => Severity::Error,
254 fdiagnostics::Severity::Fatal => Severity::Fatal,
255 fdiagnostics::Severity::__SourceBreaking { .. } => return None,
256 };
257 self.partial_cmp(&other)
258 }
259}
260
261#[cfg(test)]
262mod tests {
263 use super::*;
264
265 #[test]
266 fn from_fdiagnostics_severity() {
267 assert_eq!(Severity::from(fdiagnostics::Severity::Trace), Severity::Trace);
268 assert_eq!(Severity::from(fdiagnostics::Severity::Debug), Severity::Debug);
269 assert_eq!(Severity::from(fdiagnostics::Severity::Info), Severity::Info);
270 assert_eq!(Severity::from(fdiagnostics::Severity::Warn), Severity::Warn);
271 assert_eq!(Severity::from(fdiagnostics::Severity::Error), Severity::Error);
272 assert_eq!(Severity::from(fdiagnostics::Severity::Fatal), Severity::Fatal);
273 assert_eq!(
274 Severity::from(fdiagnostics::Severity::__SourceBreaking { unknown_ordinal: 123 }),
275 Severity::Info
276 );
277 }
278
279 #[test]
280 fn partial_cmp_fdiagnostics_severity() {
281 assert_eq!(
282 Severity::Info.partial_cmp(&fdiagnostics::Severity::Warn),
283 Some(cmp::Ordering::Less)
284 );
285 assert_eq!(
286 Severity::Warn.partial_cmp(&fdiagnostics::Severity::Info),
287 Some(cmp::Ordering::Greater)
288 );
289 assert_eq!(
290 Severity::Info.partial_cmp(&fdiagnostics::Severity::Info),
291 Some(cmp::Ordering::Equal)
292 );
293 assert_eq!(
294 Severity::Info
295 .partial_cmp(&fdiagnostics::Severity::__SourceBreaking { unknown_ordinal: 123 }),
296 None
297 );
298 }
299}