Skip to content

Commit

Permalink
impl Display/AsRef<str> for Signal, restrict FromStr to only those
Browse files Browse the repository at this point in the history
This is a bit more of a conservative implementation of FromStr, and limits it
only the representations that should be generated programmatically.
  • Loading branch information
quodlibetor committed Apr 20, 2018
1 parent ee44712 commit d5db6f7
Showing 1 changed file with 94 additions and 39 deletions.
133 changes: 94 additions & 39 deletions src/sys/signal.rs
Expand Up @@ -5,6 +5,7 @@ use libc;
use {Error, Result};
use errno::Errno;
use std::mem;
use std::fmt;
use std::str::FromStr;
#[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
use std::os::unix::io::RawFd;
Expand Down Expand Up @@ -65,49 +66,100 @@ impl FromStr for Signal {
type Err = Error;
fn from_str(s: &str) -> Result<Signal> {
Ok(match s {
"SIGHUP" | "sighup" | "HUP" | "hup" => Signal::SIGHUP,
"SIGINT" | "sigint" | "INT" | "int" => Signal::SIGINT,
"SIGQUIT" | "sigquit" | "QUIT" | "quit" => Signal::SIGQUIT,
"SIGILL" | "sigill" | "ILL" | "ill" => Signal::SIGILL,
"SIGTRAP" | "sigtrap" | "TRAP" | "trap" => Signal::SIGTRAP,
"SIGABRT" | "sigabrt" | "ABRT" | "abrt" => Signal::SIGABRT,
"SIGBUS" | "sigbus" | "BUS" | "bus" => Signal::SIGBUS,
"SIGFPE" | "sigfpe" | "FPE" | "fpe" => Signal::SIGFPE,
"SIGKILL" | "sigkill" | "KILL" | "kill" => Signal::SIGKILL,
"SIGUSR1" | "sigusr1" | "USR1" | "usr1" => Signal::SIGUSR1,
"SIGSEGV" | "sigsegv" | "SEGV" | "segv" => Signal::SIGSEGV,
"SIGUSR2" | "sigusr2" | "USR2" | "usr2" => Signal::SIGUSR2,
"SIGPIPE" | "sigpipe" | "PIPE" | "pipe" => Signal::SIGPIPE,
"SIGALRM" | "sigalrm" | "ALRM" | "alrm" => Signal::SIGALRM,
"SIGTERM" | "sigterm" | "TERM" | "term" => Signal::SIGTERM,
"SIGHUP" => Signal::SIGHUP,
"SIGINT" => Signal::SIGINT,
"SIGQUIT" => Signal::SIGQUIT,
"SIGILL" => Signal::SIGILL,
"SIGTRAP" => Signal::SIGTRAP,
"SIGABRT" => Signal::SIGABRT,
"SIGBUS" => Signal::SIGBUS,
"SIGFPE" => Signal::SIGFPE,
"SIGKILL" => Signal::SIGKILL,
"SIGUSR1" => Signal::SIGUSR1,
"SIGSEGV" => Signal::SIGSEGV,
"SIGUSR2" => Signal::SIGUSR2,
"SIGPIPE" => Signal::SIGPIPE,
"SIGALRM" => Signal::SIGALRM,
"SIGTERM" => Signal::SIGTERM,
#[cfg(all(any(target_os = "android", target_os = "emscripten", target_os = "linux"),
not(any(target_arch = "mips", target_arch = "mips64"))))]
"SIGSTKFLT" | "sigstkflt" | "STKFLT" | "stkflt" => Signal::SIGSTKFLT,
"SIGCHLD" | "sigchld" | "CHLD" | "chld" => Signal::SIGCHLD,
"SIGCONT" | "sigcont" | "CONT" | "cont" => Signal::SIGCONT,
"SIGSTOP" | "sigstop" | "STOP" | "stop" => Signal::SIGSTOP,
"SIGTSTP" | "sigtstp" | "TSTP" | "tstp" => Signal::SIGTSTP,
"SIGTTIN" | "sigttin" | "TTIN" | "ttin" => Signal::SIGTTIN,
"SIGTTOU" | "sigttou" | "TTOU" | "ttou" => Signal::SIGTTOU,
"SIGURG" | "sigurg" | "URG" | "urg" => Signal::SIGURG,
"SIGXCPU" | "sigxcpu" | "XCPU" | "xcpu" => Signal::SIGXCPU,
"SIGXFSZ" | "sigxfsz" | "XFSZ" | "xfsz" => Signal::SIGXFSZ,
"SIGVTALRM" | "sigvtalrm" | "VTALRM" | "vtalrm" => Signal::SIGVTALRM,
"SIGPROF" | "sigprof" | "PROF" | "prof" => Signal::SIGPROF,
"SIGWINCH" | "sigwinch" | "WINCH" | "winch" => Signal::SIGWINCH,
"SIGIO" | "sigio" | "IO" | "io" => Signal::SIGIO,
"SIGSTKFLT" => Signal::SIGSTKFLT,
"SIGCHLD" => Signal::SIGCHLD,
"SIGCONT" => Signal::SIGCONT,
"SIGSTOP" => Signal::SIGSTOP,
"SIGTSTP" => Signal::SIGTSTP,
"SIGTTIN" => Signal::SIGTTIN,
"SIGTTOU" => Signal::SIGTTOU,
"SIGURG" => Signal::SIGURG,
"SIGXCPU" => Signal::SIGXCPU,
"SIGXFSZ" => Signal::SIGXFSZ,
"SIGVTALRM" => Signal::SIGVTALRM,
"SIGPROF" => Signal::SIGPROF,
"SIGWINCH" => Signal::SIGWINCH,
"SIGIO" => Signal::SIGIO,
#[cfg(any(target_os = "android", target_os = "emscripten", target_os = "linux"))]
"SIGPW" | "sigpw" | "PWR" | "pwr" => Signal::SIGPWR,
"SIGSYS" | "sigsys" | "SYS" | "sys" => Signal::SIGSYS,
"SIGPWR" => Signal::SIGPWR,
"SIGSYS" => Signal::SIGSYS,
#[cfg(not(any(target_os = "android", target_os = "emscripten", target_os = "linux")))]
"SIGEMT" | "sigemt" | "EMT" | "emt" => Signal::SIGEMT,
"SIGEMT" => Signal::SIGEMT,
#[cfg(not(any(target_os = "android", target_os = "emscripten", target_os = "linux")))]
"SIGINFO" | "siginfo" | "INFO" | "info" => Signal::SIGINFO,
"SIGINFO" => Signal::SIGINFO,
_ => return Err(Error::invalid_argument()),
})
}
}

impl AsRef<str> for Signal {
fn as_ref(&self) -> &str {
match *self {
Signal::SIGHUP => "SIGHUP",
Signal::SIGINT => "SIGINT",
Signal::SIGQUIT => "SIGQUIT",
Signal::SIGILL => "SIGILL",
Signal::SIGTRAP => "SIGTRAP",
Signal::SIGABRT => "SIGABRT",
Signal::SIGBUS => "SIGBUS",
Signal::SIGFPE => "SIGFPE",
Signal::SIGKILL => "SIGKILL",
Signal::SIGUSR1 => "SIGUSR1",
Signal::SIGSEGV => "SIGSEGV",
Signal::SIGUSR2 => "SIGUSR2",
Signal::SIGPIPE => "SIGPIPE",
Signal::SIGALRM => "SIGALRM",
Signal::SIGTERM => "SIGTERM",
#[cfg(all(any(target_os = "android", target_os = "emscripten", target_os = "linux"),
not(any(target_arch = "mips", target_arch = "mips64"))))]
Signal::SIGSTKFLT => "SIGSTKFLT",
Signal::SIGCHLD => "SIGCHLD",
Signal::SIGCONT => "SIGCONT",
Signal::SIGSTOP => "SIGSTOP",
Signal::SIGTSTP => "SIGTSTP",
Signal::SIGTTIN => "SIGTTIN",
Signal::SIGTTOU => "SIGTTOU",
Signal::SIGURG => "SIGURG",
Signal::SIGXCPU => "SIGXCPU",
Signal::SIGXFSZ => "SIGXFSZ",
Signal::SIGVTALRM => "SIGVTALRM",
Signal::SIGPROF => "SIGPROF",
Signal::SIGWINCH => "SIGWINCH",
Signal::SIGIO => "SIGIO",
#[cfg(any(target_os = "android", target_os = "emscripten", target_os = "linux"))]
Signal::SIGPWR => "SIGPWR",
Signal::SIGSYS => "SIGSYS",
#[cfg(not(any(target_os = "android", target_os = "emscripten", target_os = "linux")))]
Signal::SIGEMT => "SIGEMT",
#[cfg(not(any(target_os = "android", target_os = "emscripten", target_os = "linux")))]
Signal::SIGINFO => "SIGINFO",
}
}
}

impl fmt::Display for Signal {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str(self.as_ref())
}
}

pub use self::Signal::*;

#[cfg(all(any(target_os = "linux", target_os = "android", target_os = "emscripten"), not(any(target_arch = "mips", target_arch = "mips64"))))]
Expand Down Expand Up @@ -707,16 +759,19 @@ mod tests {
}

#[test]
fn test_from_str() {
// The debug repr round-trips
format!("{:?}", Signal::SIGHUP).parse::<Signal>().unwrap();
// The `kill` representation also works
"kill".parse::<Signal>().unwrap();
fn test_from_str_round_trips() {
for signal in Signal::iterator() {
assert_eq!(signal.as_ref().parse::<Signal>().unwrap(), signal);
assert_eq!(signal.to_string().parse::<Signal>().unwrap(), signal);
}
}

#[test]
fn test_from_str_invalid_value() {
assert_eq!("NOSIGNAL".parse::<Signal>(), Err(Error::Sys(Errno::EINVAL)));
let errval = Err(Error::Sys(Errno::EINVAL));
assert_eq!("NOSIGNAL".parse::<Signal>(), errval);
assert_eq!("kill".parse::<Signal>(), errval);
assert_eq!("9".parse::<Signal>(), errval);
}

#[test]
Expand Down

0 comments on commit d5db6f7

Please sign in to comment.