use std::fmt;
use std::str::FromStr;
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
#[error("unrecognized stream mode: {0:?}")]
pub struct ParseStreamModeError(pub String);
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum StreamMode {
On,
Off,
All,
OnAll,
Recent(u32),
}
impl StreamMode {
pub fn returns_history(self) -> bool {
matches!(self, Self::All | Self::OnAll | Self::Recent(_))
}
}
impl fmt::Display for StreamMode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::On => f.write_str("on"),
Self::Off => f.write_str("off"),
Self::All => f.write_str("all"),
Self::OnAll => f.write_str("on all"),
Self::Recent(n) => write!(f, "{n}"),
}
}
}
impl FromStr for StreamMode {
type Err = ParseStreamModeError;
fn from_str(input: &str) -> Result<Self, Self::Err> {
match input {
"on" => Ok(Self::On),
"off" => Ok(Self::Off),
"all" => Ok(Self::All),
"on all" => Ok(Self::OnAll),
other => other
.parse::<u32>()
.map(Self::Recent)
.map_err(|_| ParseStreamModeError(input.to_string())),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use test_case::test_case;
#[test_case(StreamMode::On)]
#[test_case(StreamMode::Off)]
#[test_case(StreamMode::All)]
#[test_case(StreamMode::OnAll)]
#[test_case(StreamMode::Recent(42))]
fn parse_roundtrip(mode: StreamMode) {
let string = mode.to_string();
assert_eq!(string.parse::<StreamMode>().unwrap(), mode);
}
#[test]
fn parse_invalid() {
assert!("bogus".parse::<StreamMode>().is_err());
}
}