openvpn_mgmt_codec/
log_level.rs1use std::str::FromStr;
2
3#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
5#[error("unrecognized log level: {0:?}")]
6pub struct ParseLogLevelError(pub String);
7
8#[derive(Debug, Clone, PartialEq, Eq, strum::Display)]
10pub enum LogLevel {
11 #[strum(to_string = "I")]
13 Info,
14
15 #[strum(to_string = "D")]
17 Debug,
18
19 #[strum(to_string = "W")]
21 Warning,
22
23 #[strum(to_string = "N")]
25 NonFatal,
26
27 #[strum(to_string = "F")]
29 Fatal,
30
31 #[strum(default)]
33 Unknown(String),
34}
35
36impl LogLevel {
37 pub fn label(&self) -> &str {
39 match self {
40 Self::Info => "INFO",
41 Self::Debug => "DEBUG",
42 Self::Warning => "WARN",
43 Self::NonFatal => "NFATAL",
44 Self::Fatal => "FATAL",
45 Self::Unknown(s) => s,
46 }
47 }
48}
49
50impl FromStr for LogLevel {
51 type Err = ParseLogLevelError;
52
53 fn from_str(input: &str) -> Result<Self, Self::Err> {
55 match input {
56 "I" => Ok(Self::Info),
57 "D" => Ok(Self::Debug),
58 "W" => Ok(Self::Warning),
59 "N" => Ok(Self::NonFatal),
60 "F" => Ok(Self::Fatal),
61 other => Err(ParseLogLevelError(other.to_string())),
62 }
63 }
64}
65
66#[cfg(test)]
67mod tests {
68 use super::*;
69 use test_case::test_case;
70
71 #[test_case("I" => LogLevel::Info)]
72 #[test_case("D" => LogLevel::Debug)]
73 #[test_case("W" => LogLevel::Warning)]
74 #[test_case("N" => LogLevel::NonFatal)]
75 #[test_case("F" => LogLevel::Fatal)]
76 fn parse_roundtrip(flag: &str) -> LogLevel {
77 flag.parse().unwrap()
78 }
79
80 #[test]
81 fn parse_invalid() {
82 let err = "X".parse::<LogLevel>().unwrap_err();
83 assert_eq!(err.to_string(), r#"unrecognized log level: "X""#);
84 }
85
86 #[test]
87 fn label_known_variants() {
88 assert_eq!(LogLevel::Info.label(), "INFO");
89 assert_eq!(LogLevel::Debug.label(), "DEBUG");
90 assert_eq!(LogLevel::Warning.label(), "WARN");
91 assert_eq!(LogLevel::NonFatal.label(), "NFATAL");
92 assert_eq!(LogLevel::Fatal.label(), "FATAL");
93 }
94
95 #[test]
96 fn label_unknown_returns_inner() {
97 let level = LogLevel::Unknown("Z".to_string());
98 assert_eq!(level.label(), "Z");
99 }
100
101 #[test]
102 fn display_unknown_uses_strum_default() {
103 let level = LogLevel::Unknown("Q".to_string());
104 assert_eq!(level.to_string(), "Q");
105 }
106}