#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum KillSignal {
Term,
Int,
Quit,
Usr2,
}
impl KillSignal {
pub const ACCEPTED: [&'static str; 4] = ["SIGTERM", "SIGINT", "SIGQUIT", "SIGUSR2"];
#[must_use]
pub fn parse(name: &str) -> Option<Self> {
match name.to_ascii_uppercase().as_str() {
"SIGTERM" | "TERM" => Some(Self::Term),
"SIGINT" | "INT" => Some(Self::Int),
"SIGQUIT" | "QUIT" => Some(Self::Quit),
"SIGUSR2" | "USR2" => Some(Self::Usr2),
_ => None,
}
}
#[must_use]
pub fn as_str(self) -> &'static str {
match self {
Self::Term => "SIGTERM",
Self::Int => "SIGINT",
Self::Quit => "SIGQUIT",
Self::Usr2 => "SIGUSR2",
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn every_accepted_name_round_trips_through_parse() {
for name in KillSignal::ACCEPTED {
let parsed = KillSignal::parse(name)
.unwrap_or_else(|| panic!("`{name}` is advertised but not parsed"));
assert_eq!(parsed.as_str(), name);
}
}
#[test]
fn the_prefix_and_the_case_are_both_optional() {
assert_eq!(KillSignal::parse("usr2"), Some(KillSignal::Usr2));
assert_eq!(KillSignal::parse("SigQuit"), Some(KillSignal::Quit));
}
#[test]
fn a_signal_the_ladder_cannot_send_does_not_parse() {
assert_eq!(KillSignal::parse("SIGUSR1"), None);
assert_eq!(KillSignal::parse("SIGKILL"), None);
assert_eq!(KillSignal::parse(""), None);
}
}