Skip to main content

openvpn_mgmt_codec/
status_format.rs

1use std::str::FromStr;
2
3/// Error returned when a string is not a recognized status format.
4#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
5#[error("unrecognized status format: {0:?}")]
6pub struct ParseStatusFormatError(pub String);
7
8/// Status output format version. Higher versions are more machine-parseable.
9///
10/// - V1: default human-readable format
11/// - V2: adds header/footer markers for easier parsing
12/// - V3: tab-delimited, ideal for programmatic consumption
13#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, strum::Display)]
14pub enum StatusFormat {
15    /// Default human-readable format.
16    #[default]
17    #[strum(to_string = "1")]
18    V1,
19
20    /// Adds header/footer markers for easier parsing.
21    #[strum(to_string = "2")]
22    V2,
23
24    /// Tab-delimited, ideal for programmatic consumption.
25    #[strum(to_string = "3")]
26    V3,
27}
28
29impl FromStr for StatusFormat {
30    type Err = ParseStatusFormatError;
31
32    /// Parse a status format version: `1`, `2`, or `3`.
33    fn from_str(s: &str) -> Result<Self, Self::Err> {
34        match s {
35            "1" => Ok(Self::V1),
36            "2" => Ok(Self::V2),
37            "3" => Ok(Self::V3),
38            other => Err(ParseStatusFormatError(other.to_string())),
39        }
40    }
41}
42
43#[cfg(test)]
44mod tests {
45    use super::*;
46
47    #[test]
48    fn display_roundtrip() {
49        for fmt in [StatusFormat::V1, StatusFormat::V2, StatusFormat::V3] {
50            let s = fmt.to_string();
51            assert_eq!(s.parse::<StatusFormat>().unwrap(), fmt);
52        }
53    }
54
55    #[test]
56    fn display_values() {
57        assert_eq!(StatusFormat::V1.to_string(), "1");
58        assert_eq!(StatusFormat::V2.to_string(), "2");
59        assert_eq!(StatusFormat::V3.to_string(), "3");
60    }
61
62    #[test]
63    fn parse_invalid() {
64        assert!("4".parse::<StatusFormat>().is_err());
65        assert!("".parse::<StatusFormat>().is_err());
66    }
67}