use std::collections::HashMap;
use std::fmt;
use lazy_static::lazy_static;
#[derive(Debug, Clone)]
pub enum SignalTypeError {
InvalidSignalType(String),
}
impl fmt::Display for SignalTypeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
SignalTypeError::InvalidSignalType(value) => {
write!(f, "Invalid signal type: '{}'", value)
}
}
}
}
impl std::error::Error for SignalTypeError {}
lazy_static! {
static ref SIGNAL_CONVERTER: HashMap<&'static str, SignalType> = {
let mut m = HashMap::new();
m.insert("r", SignalType::Red);
m.insert("y", SignalType::Yellow);
m.insert("g", SignalType::Green);
m.insert("G", SignalType::GreenPriority);
m.insert("s", SignalType::GreenRight);
m.insert("u", SignalType::RedYellow);
m.insert("o", SignalType::Blinking);
m.insert("O", SignalType::NoSignal);
m
};
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum SignalType {
Undefined,
Red,
Yellow,
Green,
GreenPriority,
GreenRight,
RedYellow,
Blinking,
NoSignal,
}
impl SignalType {
pub fn from_str(signal_str: &str) -> Result<Self, SignalTypeError> {
SIGNAL_CONVERTER
.get(signal_str)
.copied()
.ok_or(SignalTypeError::InvalidSignalType(signal_str.to_string()))
}
}
impl fmt::Display for SignalType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let signal_type_str = match self {
SignalType::Undefined => "undefined",
SignalType::Red => "r",
SignalType::Yellow => "y",
SignalType::Green => "g",
SignalType::GreenPriority => "G",
SignalType::GreenRight => "s",
SignalType::RedYellow => "u",
SignalType::Blinking => "o",
SignalType::NoSignal => "O",
};
write!(f, "{}", signal_type_str)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_signal_valid() {
assert_eq!(SignalType::from_str("r").unwrap(), SignalType::Red);
assert_eq!(SignalType::from_str("y").unwrap(), SignalType::Yellow);
assert_eq!(SignalType::from_str("g").unwrap(), SignalType::Green);
assert_eq!(SignalType::from_str("G").unwrap(), SignalType::GreenPriority);
assert_eq!(SignalType::from_str("s").unwrap(), SignalType::GreenRight);
assert_eq!(SignalType::from_str("u").unwrap(), SignalType::RedYellow);
assert_eq!(SignalType::from_str("o").unwrap(), SignalType::Blinking);
assert_eq!(SignalType::from_str("O").unwrap(), SignalType::NoSignal);
}
#[test]
fn test_parse_signal_invalid() {
let result = SignalType::from_str("z");
assert!(result.is_err());
assert_eq!(
result.unwrap_err().to_string(),
"Invalid signal type: 'z'"
);
}
}