1use serde::de;
15use serde::de::{DeserializeSeed, EnumAccess, VariantAccess, Visitor};
16use serde::{Deserialize, Deserializer, Serialize, Serializer};
17use std::cmp::Ordering;
18use std::error::Error;
19use std::fmt;
20use std::str::FromStr;
21
22static LOG_LEVEL_NAMES: [&str; 7] = ["OFF", "FATAL", "ERROR", "WARN", "INFO", "DEBUG", "TRACE"];
23
24#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
26pub enum Level {
27 Fatal = 1,
32 Error,
36 Warn,
40 Info,
44 Debug,
48 Trace,
52}
53
54impl fmt::Display for Level {
55 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
56 fmt.pad(LOG_LEVEL_NAMES[*self as usize])
57 }
58}
59
60impl FromStr for Level {
61 type Err = FromStrError;
62
63 fn from_str(s: &str) -> Result<Level, FromStrError> {
64 LOG_LEVEL_NAMES
65 .iter()
66 .position(|level| s.eq_ignore_ascii_case(level))
67 .and_then(Level::from_usize)
68 .ok_or(FromStrError(()))
69 }
70}
71
72impl PartialEq<LevelFilter> for Level {
73 #[inline]
74 fn eq(&self, other: &LevelFilter) -> bool {
75 *self as usize == *other as usize
76 }
77}
78
79impl PartialOrd<LevelFilter> for Level {
80 #[inline]
81 fn partial_cmp(&self, other: &LevelFilter) -> Option<Ordering> {
82 (*self as usize).partial_cmp(&(*other as usize))
83 }
84
85 #[inline]
86 fn lt(&self, other: &LevelFilter) -> bool {
87 (*self as usize) < (*other as usize)
88 }
89
90 #[inline]
91 fn le(&self, other: &LevelFilter) -> bool {
92 (*self as usize) <= (*other as usize)
93 }
94
95 #[inline]
96 fn gt(&self, other: &LevelFilter) -> bool {
97 (*self as usize) > (*other as usize)
98 }
99
100 #[inline]
101 fn ge(&self, other: &LevelFilter) -> bool {
102 (*self as usize) >= (*other as usize)
103 }
104}
105
106impl Level {
107 fn from_usize(n: usize) -> Option<Level> {
108 match n {
109 1 => Some(Level::Fatal),
110 2 => Some(Level::Error),
111 3 => Some(Level::Warn),
112 4 => Some(Level::Info),
113 5 => Some(Level::Debug),
114 6 => Some(Level::Trace),
115 _ => None,
116 }
117 }
118
119 pub fn as_str(self) -> &'static str {
121 LOG_LEVEL_NAMES[self as usize]
122 }
123}
124
125#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
129#[repr(usize)] pub enum LevelFilter {
131 Off,
133 Fatal,
135 Error,
137 Warn,
139 Info,
141 Debug,
143 Trace,
145}
146
147impl fmt::Display for LevelFilter {
148 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
149 fmt.pad(LOG_LEVEL_NAMES[*self as usize])
150 }
151}
152
153impl FromStr for LevelFilter {
154 type Err = FromStrError;
155
156 fn from_str(s: &str) -> Result<LevelFilter, FromStrError> {
157 LOG_LEVEL_NAMES
158 .iter()
159 .position(|level| s.eq_ignore_ascii_case(level))
160 .and_then(LevelFilter::from_usize)
161 .ok_or(FromStrError(()))
162 }
163}
164
165impl PartialEq<Level> for LevelFilter {
166 #[inline]
167 fn eq(&self, other: &Level) -> bool {
168 *self as usize == *other as usize
169 }
170}
171
172impl PartialOrd<Level> for LevelFilter {
173 #[inline]
174 fn partial_cmp(&self, other: &Level) -> Option<Ordering> {
175 (*self as usize).partial_cmp(&(*other as usize))
176 }
177
178 #[inline]
179 fn lt(&self, other: &Level) -> bool {
180 (*self as usize) < (*other as usize)
181 }
182
183 #[inline]
184 fn le(&self, other: &Level) -> bool {
185 (*self as usize) <= (*other as usize)
186 }
187
188 #[inline]
189 fn gt(&self, other: &Level) -> bool {
190 (*self as usize) > (*other as usize)
191 }
192
193 #[inline]
194 fn ge(&self, other: &Level) -> bool {
195 (*self as usize) >= (*other as usize)
196 }
197}
198
199impl LevelFilter {
200 fn from_usize(n: usize) -> Option<LevelFilter> {
201 match n {
202 0 => Some(LevelFilter::Off),
203 1 => Some(LevelFilter::Fatal),
204 2 => Some(LevelFilter::Error),
205 3 => Some(LevelFilter::Warn),
206 4 => Some(LevelFilter::Info),
207 5 => Some(LevelFilter::Debug),
208 6 => Some(LevelFilter::Trace),
209 _ => None,
210 }
211 }
212}
213
214#[derive(Debug)]
216pub struct FromStrError(());
217
218impl fmt::Display for FromStrError {
219 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
220 fmt.write_str("invalid log level")
221 }
222}
223
224impl Error for FromStrError {}
225
226impl Serialize for Level {
228 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
229 where
230 S: Serializer,
231 {
232 match *self {
233 Level::Fatal => serializer.serialize_unit_variant("Level", 0, "FATAL"),
234 Level::Error => serializer.serialize_unit_variant("Level", 1, "ERROR"),
235 Level::Warn => serializer.serialize_unit_variant("Level", 2, "WARN"),
236 Level::Info => serializer.serialize_unit_variant("Level", 3, "INFO"),
237 Level::Debug => serializer.serialize_unit_variant("Level", 4, "DEBUG"),
238 Level::Trace => serializer.serialize_unit_variant("Level", 5, "TRACE"),
239 }
240 }
241}
242
243impl<'de> Deserialize<'de> for Level {
244 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
245 where
246 D: Deserializer<'de>,
247 {
248 struct LevelIdentifier;
249
250 impl Visitor<'_> for LevelIdentifier {
251 type Value = Level;
252
253 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
254 formatter.write_str("log level")
255 }
256
257 fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
258 where
259 E: de::Error,
260 {
261 FromStr::from_str(s)
263 .map_err(|_| de::Error::unknown_variant(s, &LOG_LEVEL_NAMES[1..]))
264 }
265 }
266
267 impl<'de> DeserializeSeed<'de> for LevelIdentifier {
268 type Value = Level;
269
270 fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
271 where
272 D: Deserializer<'de>,
273 {
274 deserializer.deserialize_identifier(LevelIdentifier)
275 }
276 }
277
278 struct LevelEnum;
279
280 impl<'de> Visitor<'de> for LevelEnum {
281 type Value = Level;
282
283 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
284 formatter.write_str("log level")
285 }
286
287 fn visit_enum<A>(self, value: A) -> Result<Self::Value, A::Error>
288 where
289 A: EnumAccess<'de>,
290 {
291 let (level, variant) = value.variant_seed(LevelIdentifier)?;
292 variant.unit_variant()?;
294 Ok(level)
295 }
296 }
297
298 deserializer.deserialize_enum("Level", &LOG_LEVEL_NAMES[1..], LevelEnum)
299 }
300}
301
302impl Serialize for LevelFilter {
303 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
304 where
305 S: Serializer,
306 {
307 match *self {
308 LevelFilter::Off => serializer.serialize_unit_variant("LevelFilter", 0, "OFF"),
309 LevelFilter::Fatal => serializer.serialize_unit_variant("LevelFilter", 1, "FATAL"),
310 LevelFilter::Error => serializer.serialize_unit_variant("LevelFilter", 2, "ERROR"),
311 LevelFilter::Warn => serializer.serialize_unit_variant("LevelFilter", 3, "WARN"),
312 LevelFilter::Info => serializer.serialize_unit_variant("LevelFilter", 4, "INFO"),
313 LevelFilter::Debug => serializer.serialize_unit_variant("LevelFilter", 5, "DEBUG"),
314 LevelFilter::Trace => serializer.serialize_unit_variant("LevelFilter", 6, "TRACE"),
315 }
316 }
317}
318
319impl<'de> Deserialize<'de> for LevelFilter {
320 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
321 where
322 D: Deserializer<'de>,
323 {
324 struct LevelFilterIdentifier;
325
326 impl Visitor<'_> for LevelFilterIdentifier {
327 type Value = LevelFilter;
328
329 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
330 formatter.write_str("log level filter")
331 }
332
333 fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
334 where
335 E: de::Error,
336 {
337 FromStr::from_str(s).map_err(|_| de::Error::unknown_variant(s, &LOG_LEVEL_NAMES))
339 }
340 }
341
342 impl<'de> DeserializeSeed<'de> for LevelFilterIdentifier {
343 type Value = LevelFilter;
344
345 fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
346 where
347 D: Deserializer<'de>,
348 {
349 deserializer.deserialize_identifier(LevelFilterIdentifier)
350 }
351 }
352
353 struct LevelFilterEnum;
354
355 impl<'de> Visitor<'de> for LevelFilterEnum {
356 type Value = LevelFilter;
357
358 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
359 formatter.write_str("log level filter")
360 }
361
362 fn visit_enum<A>(self, value: A) -> Result<Self::Value, A::Error>
363 where
364 A: EnumAccess<'de>,
365 {
366 let (level_filter, variant) = value.variant_seed(LevelFilterIdentifier)?;
367 variant.unit_variant()?;
369 Ok(level_filter)
370 }
371 }
372
373 deserializer.deserialize_enum("LevelFilter", &LOG_LEVEL_NAMES, LevelFilterEnum)
374 }
375}
376
377#[cfg(test)]
378mod tests {
379 use serde_test::{assert_de_tokens, assert_de_tokens_error, assert_tokens, Token};
380
381 use crate::{Level, LevelFilter};
382
383 fn level_token(variant: &'static str) -> Token {
384 Token::UnitVariant {
385 name: "Level",
386 variant,
387 }
388 }
389
390 fn level_filter_token(variant: &'static str) -> Token {
391 Token::UnitVariant {
392 name: "LevelFilter",
393 variant,
394 }
395 }
396
397 #[test]
398 fn test_level_ser_de() {
399 let cases = [
400 (Level::Fatal, [level_token("FATAL")]),
401 (Level::Error, [level_token("ERROR")]),
402 (Level::Warn, [level_token("WARN")]),
403 (Level::Info, [level_token("INFO")]),
404 (Level::Debug, [level_token("DEBUG")]),
405 (Level::Trace, [level_token("TRACE")]),
406 ];
407
408 for &(s, expected) in &cases {
409 assert_tokens(&s, &expected);
410 }
411 }
412
413 #[test]
414 fn test_level_case_insensitive() {
415 let cases = [
416 (Level::Fatal, [level_token("fatal")]),
417 (Level::Error, [level_token("error")]),
418 (Level::Warn, [level_token("warn")]),
419 (Level::Info, [level_token("info")]),
420 (Level::Debug, [level_token("debug")]),
421 (Level::Trace, [level_token("trace")]),
422 ];
423
424 for &(s, expected) in &cases {
425 assert_de_tokens(&s, &expected);
426 }
427 }
428
429 #[test]
430 fn test_level_de_error() {
431 let msg = "unknown variant `errorx`, expected one of \
432 `FATAL`, `ERROR`, `WARN`, `INFO`, `DEBUG`, `TRACE`";
433 assert_de_tokens_error::<Level>(&[level_token("errorx")], msg);
434 }
435
436 #[test]
437 fn test_level_filter_ser_de() {
438 let cases = [
439 (LevelFilter::Off, [level_filter_token("OFF")]),
440 (LevelFilter::Fatal, [level_filter_token("FATAL")]),
441 (LevelFilter::Error, [level_filter_token("ERROR")]),
442 (LevelFilter::Warn, [level_filter_token("WARN")]),
443 (LevelFilter::Info, [level_filter_token("INFO")]),
444 (LevelFilter::Debug, [level_filter_token("DEBUG")]),
445 (LevelFilter::Trace, [level_filter_token("TRACE")]),
446 ];
447
448 for &(s, expected) in &cases {
449 assert_tokens(&s, &expected);
450 }
451 }
452
453 #[test]
454 fn test_level_filter_case_insensitive() {
455 let cases = [
456 (LevelFilter::Off, [level_filter_token("off")]),
457 (LevelFilter::Fatal, [level_filter_token("fatal")]),
458 (LevelFilter::Error, [level_filter_token("error")]),
459 (LevelFilter::Warn, [level_filter_token("warn")]),
460 (LevelFilter::Info, [level_filter_token("info")]),
461 (LevelFilter::Debug, [level_filter_token("debug")]),
462 (LevelFilter::Trace, [level_filter_token("trace")]),
463 ];
464
465 for &(s, expected) in &cases {
466 assert_de_tokens(&s, &expected);
467 }
468 }
469
470 #[test]
471 fn test_level_filter_de_error() {
472 let msg = "unknown variant `errorx`, expected one of \
473 `OFF`, `FATAL`, `ERROR`, `WARN`, `INFO`, `DEBUG`, `TRACE`";
474 assert_de_tokens_error::<LevelFilter>(&[level_filter_token("errorx")], msg);
475 }
476}