#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum SignalKind {
Interrupt,
Terminate,
Hangup,
Quit,
User1,
User2,
Child,
WindowChange,
Pipe,
Alarm,
}
impl SignalKind {
#[must_use]
#[inline]
pub const fn interrupt() -> Self {
Self::Interrupt
}
#[must_use]
#[inline]
pub const fn terminate() -> Self {
Self::Terminate
}
#[must_use]
#[inline]
pub const fn hangup() -> Self {
Self::Hangup
}
#[must_use]
#[inline]
pub const fn quit() -> Self {
Self::Quit
}
#[must_use]
#[inline]
pub const fn user_defined1() -> Self {
Self::User1
}
#[must_use]
#[inline]
pub const fn user_defined2() -> Self {
Self::User2
}
#[must_use]
#[inline]
pub const fn child() -> Self {
Self::Child
}
#[must_use]
#[inline]
pub const fn window_change() -> Self {
Self::WindowChange
}
#[must_use]
#[inline]
pub const fn pipe() -> Self {
Self::Pipe
}
#[must_use]
#[inline]
pub const fn alarm() -> Self {
Self::Alarm
}
#[cfg(unix)]
#[must_use]
#[inline]
pub const fn as_raw_value(&self) -> i32 {
match self {
Self::Interrupt => libc::SIGINT,
Self::Terminate => libc::SIGTERM,
Self::Hangup => libc::SIGHUP,
Self::Quit => libc::SIGQUIT,
Self::User1 => libc::SIGUSR1,
Self::User2 => libc::SIGUSR2,
Self::Child => libc::SIGCHLD,
Self::WindowChange => libc::SIGWINCH,
Self::Pipe => libc::SIGPIPE,
Self::Alarm => libc::SIGALRM,
}
}
#[cfg(windows)]
#[must_use]
#[inline]
pub const fn as_raw_value(&self) -> Option<i32> {
const SIGBREAK: i32 = 21;
match self {
Self::Interrupt => Some(libc::SIGINT),
Self::Terminate => Some(libc::SIGTERM),
Self::Quit => Some(SIGBREAK),
_ => None,
}
}
#[cfg(not(any(unix, windows)))]
#[must_use]
#[inline]
pub const fn as_raw_value(&self) -> Option<i32> {
None
}
#[must_use]
#[inline]
pub const fn name(&self) -> &'static str {
match self {
Self::Interrupt => "SIGINT",
Self::Terminate => "SIGTERM",
Self::Hangup => "SIGHUP",
Self::Quit => "SIGQUIT",
Self::User1 => "SIGUSR1",
Self::User2 => "SIGUSR2",
Self::Child => "SIGCHLD",
Self::WindowChange => "SIGWINCH",
Self::Pipe => "SIGPIPE",
Self::Alarm => "SIGALRM",
}
}
}
impl std::fmt::Display for SignalKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.name())
}
}
#[cfg(test)]
mod tests {
use super::*;
fn init_test(name: &str) {
crate::test_utils::init_test_logging();
crate::test_phase!(name);
}
#[test]
fn signal_kind_constructors() {
init_test("signal_kind_constructors");
crate::assert_with_log!(
SignalKind::interrupt() == SignalKind::Interrupt,
"interrupt",
SignalKind::Interrupt,
SignalKind::interrupt()
);
crate::assert_with_log!(
SignalKind::terminate() == SignalKind::Terminate,
"terminate",
SignalKind::Terminate,
SignalKind::terminate()
);
crate::assert_with_log!(
SignalKind::hangup() == SignalKind::Hangup,
"hangup",
SignalKind::Hangup,
SignalKind::hangup()
);
crate::assert_with_log!(
SignalKind::quit() == SignalKind::Quit,
"quit",
SignalKind::Quit,
SignalKind::quit()
);
crate::assert_with_log!(
SignalKind::user_defined1() == SignalKind::User1,
"user1",
SignalKind::User1,
SignalKind::user_defined1()
);
crate::assert_with_log!(
SignalKind::user_defined2() == SignalKind::User2,
"user2",
SignalKind::User2,
SignalKind::user_defined2()
);
crate::assert_with_log!(
SignalKind::child() == SignalKind::Child,
"child",
SignalKind::Child,
SignalKind::child()
);
crate::assert_with_log!(
SignalKind::window_change() == SignalKind::WindowChange,
"window_change",
SignalKind::WindowChange,
SignalKind::window_change()
);
crate::test_complete!("signal_kind_constructors");
}
#[test]
fn signal_kind_names() {
init_test("signal_kind_names");
let interrupt = SignalKind::Interrupt.name();
crate::assert_with_log!(interrupt == "SIGINT", "interrupt", "SIGINT", interrupt);
let terminate = SignalKind::Terminate.name();
crate::assert_with_log!(terminate == "SIGTERM", "terminate", "SIGTERM", terminate);
let hangup = SignalKind::Hangup.name();
crate::assert_with_log!(hangup == "SIGHUP", "hangup", "SIGHUP", hangup);
crate::test_complete!("signal_kind_names");
}
#[test]
fn signal_kind_display() {
init_test("signal_kind_display");
let interrupt = format!("{}", SignalKind::Interrupt);
crate::assert_with_log!(interrupt == "SIGINT", "interrupt", "SIGINT", interrupt);
let terminate = format!("{}", SignalKind::Terminate);
crate::assert_with_log!(terminate == "SIGTERM", "terminate", "SIGTERM", terminate);
crate::test_complete!("signal_kind_display");
}
#[cfg(unix)]
#[test]
fn signal_kind_raw_values() {
init_test("signal_kind_raw_values");
let interrupt = SignalKind::Interrupt.as_raw_value();
crate::assert_with_log!(
interrupt == libc::SIGINT,
"interrupt",
libc::SIGINT,
interrupt
);
let terminate = SignalKind::Terminate.as_raw_value();
crate::assert_with_log!(
terminate == libc::SIGTERM,
"terminate",
libc::SIGTERM,
terminate
);
let hangup = SignalKind::Hangup.as_raw_value();
crate::assert_with_log!(hangup == libc::SIGHUP, "hangup", libc::SIGHUP, hangup);
let user1 = SignalKind::User1.as_raw_value();
crate::assert_with_log!(user1 == libc::SIGUSR1, "user1", libc::SIGUSR1, user1);
let user2 = SignalKind::User2.as_raw_value();
crate::assert_with_log!(user2 == libc::SIGUSR2, "user2", libc::SIGUSR2, user2);
let child = SignalKind::Child.as_raw_value();
crate::assert_with_log!(child == libc::SIGCHLD, "child", libc::SIGCHLD, child);
let winch = SignalKind::WindowChange.as_raw_value();
crate::assert_with_log!(winch == libc::SIGWINCH, "winch", libc::SIGWINCH, winch);
let pipe = SignalKind::Pipe.as_raw_value();
crate::assert_with_log!(pipe == libc::SIGPIPE, "pipe", libc::SIGPIPE, pipe);
let alarm = SignalKind::Alarm.as_raw_value();
crate::assert_with_log!(alarm == libc::SIGALRM, "alarm", libc::SIGALRM, alarm);
crate::test_complete!("signal_kind_raw_values");
}
#[cfg(windows)]
#[test]
fn signal_kind_raw_values_windows_subset() {
init_test("signal_kind_raw_values_windows_subset");
let interrupt = SignalKind::Interrupt.as_raw_value();
crate::assert_with_log!(
interrupt == Some(libc::SIGINT),
"interrupt",
Some(libc::SIGINT),
interrupt
);
let terminate = SignalKind::Terminate.as_raw_value();
crate::assert_with_log!(
terminate == Some(libc::SIGTERM),
"terminate",
Some(libc::SIGTERM),
terminate
);
let quit = SignalKind::Quit.as_raw_value();
crate::assert_with_log!(
quit == Some(signal_hook::consts::SIGBREAK),
"quit",
Some(signal_hook::consts::SIGBREAK),
quit
);
let user1 = SignalKind::User1.as_raw_value();
crate::assert_with_log!(user1.is_none(), "user1 unsupported", true, user1.is_none());
crate::test_complete!("signal_kind_raw_values_windows_subset");
}
#[test]
fn signal_kind_debug_clone_copy_hash() {
use std::collections::HashSet;
let s = SignalKind::Interrupt;
let dbg = format!("{s:?}");
assert!(dbg.contains("Interrupt"), "{dbg}");
let copied = s;
let cloned = s;
assert_eq!(copied, cloned);
let mut set = HashSet::new();
set.insert(s);
assert!(set.contains(&SignalKind::Interrupt));
assert!(!set.contains(&SignalKind::Terminate));
}
}