Skip to main content

openvpn_mgmt_codec/
stream_mode.rs

1use std::fmt;
2use std::str::FromStr;
3
4/// Mode selector for commands that share the on/off/all/on-all/N grammar.
5/// This is used by `log`, `state`, and `echo`, all of which support
6/// identical sub-commands.
7#[derive(Debug, Clone, PartialEq, Eq)]
8pub enum StreamMode {
9    /// Enable real-time notifications.
10    On,
11
12    /// Disable real-time notifications.
13    Off,
14
15    /// Dump the entire history buffer.
16    All,
17
18    /// Atomically enable real-time notifications AND dump history.
19    /// This guarantees no messages are missed between the dump and
20    /// the start of real-time streaming.
21    OnAll,
22
23    /// Show the N most recent history entries.
24    Recent(u32),
25}
26
27impl fmt::Display for StreamMode {
28    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
29        match self {
30            Self::On => f.write_str("on"),
31            Self::Off => f.write_str("off"),
32            Self::All => f.write_str("all"),
33            Self::OnAll => f.write_str("on all"),
34            Self::Recent(n) => write!(f, "{n}"),
35        }
36    }
37}
38
39impl FromStr for StreamMode {
40    type Err = String;
41
42    /// Parse a stream mode string: `on`, `off`, `all`, `on all`, or a number.
43    fn from_str(s: &str) -> Result<Self, Self::Err> {
44        match s {
45            "on" => Ok(Self::On),
46            "off" => Ok(Self::Off),
47            "all" => Ok(Self::All),
48            "on all" => Ok(Self::OnAll),
49            n => n
50                .parse::<u32>()
51                .map(Self::Recent)
52                .map_err(|_| format!("invalid stream mode: {s} (use on/off/all/on all/N)")),
53        }
54    }
55}
56
57#[cfg(test)]
58mod tests {
59    use super::*;
60
61    #[test]
62    fn parse_roundtrip() {
63        for mode in [
64            StreamMode::On,
65            StreamMode::Off,
66            StreamMode::All,
67            StreamMode::OnAll,
68            StreamMode::Recent(42),
69        ] {
70            let s = mode.to_string();
71            assert_eq!(s.parse::<StreamMode>().unwrap(), mode);
72        }
73    }
74
75    #[test]
76    fn parse_invalid() {
77        assert!("bogus".parse::<StreamMode>().is_err());
78    }
79}