proc-result 0.3.0

A tiny cross-platform library containing exit status and code types
Documentation
use core::fmt::Display;

/// A Unix-like signal.
///
/// Represents a signal that can be sent to or received by processes on Unix-like systems.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[cfg_attr(
    feature = "serde",
    derive(serde::Serialize, serde::Deserialize),
    serde(transparent)
)]
pub struct Signal(u8);

impl Signal {
    /// Creates a new `UnixTerminationSignal` from the underlying `u8` signal number.
    #[must_use]
    pub const fn from_raw(signal: u8) -> Self {
        Self(signal)
    }

    /// Returns the underlying `u8` signal number.
    #[must_use]
    pub const fn to_raw(&self) -> u8 {
        self.0
    }

    /// Null signal.
    ///
    /// Corresponds to signal number `0`.
    ///
    /// Can be used to check if a process exists without sending an actual signal.
    pub const NULL: Self = Self(0);

    /// Hangup (`SIGHUP`).
    ///
    /// Corresponds to signal number `1`.
    ///
    /// Sent to a process when its controlling terminal is closed or when a parent process exits,
    /// often used by daemons to re-read configuration files.
    pub const HANGUP: Self = Self(1);

    /// Interrupt (`SIGINT`).
    ///
    /// Corresponds to signal number `2`.
    ///
    /// Sent by the terminal to the foreground process group to request its termination,
    /// often initiated by the user pressing `Ctrl+C`.
    pub const INTERRUPT: Self = Self(2);

    /// Quit (`SIGQUIT`).
    ///
    /// Corresponds to signal number `3`.
    ///
    /// Sent by the terminal to the foreground process group (often by pressing `Ctrl+\`).
    /// Typically causes a core dump and process termination.
    pub const QUIT: Self = Self(3);

    /// Illegal instruction (`SIGILL`).
    ///
    /// Corresponds to signal number `4`.
    ///
    /// Indicates an attempt to execute an invalid or malformed instruction.
    pub const ILLEGAL_INSTRUCTION: Self = Self(4);

    /// Trace trap (`SIGTRAP`).
    ///
    /// Corresponds to signal number `5`.
    ///
    /// Used by debuggers to implement breakpoints.
    pub const TRAP: Self = Self(5);

    /// Abort (`SIGABRT`).
    ///
    /// Corresponds to signal number `6`.
    ///
    /// Sent by the `abort()` function (or `_exit()` in some cases) to indicate an abnormal
    /// termination, typically due to a detected internal inconsistency. Often causes a core dump.
    pub const ABORT: Self = Self(6);

    /// Bus error (`SIGBUS`).
    ///
    /// Corresponds to signal number `7`.
    ///
    /// Indicates a memory access error, often due to misaligned access or non-existent physical address.
    pub const BUS_ERROR: Self = Self(7);

    /// Floating-point exception (`SIGFPE`).
    ///
    /// Corresponds to signal number `8`.
    ///
    /// Indicates an erroneous arithmetic operation (e.g., division by zero, overflow).
    pub const FLOATING_POINT_EXCEPTION: Self = Self(8);

    /// Kill (`SIGKILL`).
    ///
    /// Corresponds to signal number `9`.
    ///
    /// Unconditionally terminates a process. This signal cannot be caught, blocked, or ignored,
    /// making it the most forceful way to kill a process.
    pub const KILL: Self = Self(9);

    /// User-defined signal 1 (`SIGUSR1`).
    ///
    /// Corresponds to signal number `10` (often).
    ///
    /// A custom signal for application-specific use. Its exact number can vary by system.
    pub const USER1: Self = Self(10); // Note: Number might vary (often 10 or 30)

    /// Segmentation violation (`SIGSEGV`).
    ///
    /// Corresponds to signal number `11`.
    ///
    /// Indicates an invalid memory access (e.g., trying to write to read-only memory, or access
    /// outside allocated bounds). Typically causes a core dump.
    pub const SEGMENTATION_VIOLATION: Self = Self(11);

    /// User-defined signal 2 (`SIGUSR2`).
    ///
    /// Corresponds to signal number `12` (often).
    ///
    /// Another custom signal for application-specific use. Its exact number can vary by system.
    pub const USER2: Self = Self(12); // Note: Number might vary (often 12 or 31)

    /// Broken pipe (`SIGPIPE`).
    ///
    /// Corresponds to signal number `13`.
    ///
    /// Sent when a process attempts to write to a pipe, socket, or FIFO whose reading end has been
    /// closed.
    pub const BROKEN_PIPE: Self = Self(13);

    /// Alarm clock (`SIGALRM`).
    ///
    /// Corresponds to signal number `14`.
    ///
    /// Generated by the `alarm()` system call for timer expiration.
    pub const ALARM: Self = Self(14);

    /// Termination (`SIGTERM`).
    ///
    /// Corresponds to signal number `15`.
    ///
    /// A generic request to terminate a process. Unlike `SIGKILL`, this signal can be caught and
    /// handled by the process to perform cleanup before exiting gracefully.
    pub const TERMINATION: Self = Self(15);

    /// Stack fault (`SIGSTKFLT`).
    ///
    /// Corresponds to signal number `16`.
    ///
    /// (Linux specific) Indicates a stack fault on a coprocessor. Less common.
    pub const STACK_FAULT: Self = Self(16);

    /// Child stopped or terminated (`SIGCHLD`).
    ///
    /// Corresponds to signal number `17`.
    ///
    /// Sent to a parent process when one of its child processes stops or terminates.
    pub const CHILD: Self = Self(17);

    /// Continue (`SIGCONT`).
    ///
    /// Corresponds to signal number `18`.
    ///
    /// If the process is stopped, it is resumed. If it is already running, it continues.
    pub const CONTINUE: Self = Self(18);

    /// Stop (`SIGSTOP`).
    ///
    /// Corresponds to signal number `19`.
    ///
    /// Stops a process. Unlike `SIGTSTP`, this signal cannot be caught, blocked, or ignored, making
    /// it a forceful way to pause execution.
    pub const STOP: Self = Self(19);

    /// Tty stop (`SIGTSTP`).
    ///
    /// Corresponds to signal number `20`.
    ///
    /// Sent by the terminal to the foreground process group when the user presses `Ctrl+Z`.
    ///
    /// Can be caught and handled to allow the process to clean up or save state before stopping.
    pub const TTY_STOP: Self = Self(20);

    /// Background read from tty (`SIGTTIN`).
    ///
    /// Corresponds to signal number `21`.
    ///
    /// Sent to a process in the background when it attempts to read from its controlling terminal.
    pub const TTY_IN: Self = Self(21);

    /// Background write to tty (`SIGTTOU`).
    ///
    /// Corresponds to signal number `22`.
    ///
    /// Sent to a process in the background when it attempts to write to its controlling terminal.
    pub const TTY_OUT: Self = Self(22);

    /// Urgent condition on socket (`SIGURG`).
    ///
    /// Corresponds to signal number `23`.
    ///
    /// Indicates urgent data is available on a socket.
    pub const URGENT_IO: Self = Self(23);

    /// CPU time limit exceeded (`SIGXCPU`).
    ///
    /// Corresponds to signal number `24`.
    ///
    /// Sent when a process exceeds its CPU time limit.
    pub const CPU_LIMIT: Self = Self(24);

    /// File size limit exceeded (`SIGXFSZ`).
    ///
    /// Corresponds to signal number `25`.
    ///
    /// Sent when a process attempts to create a file larger than its imposed limit.
    pub const FILE_SIZE_LIMIT: Self = Self(25);

    /// Virtual alarm clock (`SIGVTALRM`).
    ///
    /// Corresponds to signal number `26`.
    ///
    /// Generated by a virtual alarm clock, often used for profiling.
    pub const VIRTUAL_ALARM: Self = Self(26);

    /// Profiling timer expired (`SIGPROF`).
    ///
    /// Corresponds to signal number `27`.
    ///
    /// Generated by a profiling timer, typically used for profiling applications.
    pub const PROFILING_TIMER: Self = Self(27);

    /// Window changed (`SIGWINCH`).
    ///
    /// Corresponds to signal number `28`.
    ///
    /// Sent to the foreground process group when the terminal window size has changed.
    pub const WINDOW_CHANGED: Self = Self(28);

    /// I/O is possible (`SIGIO`).
    ///
    /// Corresponds to signal number `29`.
    ///
    /// Indicates that asynchronous I/O is possible on a file descriptor.
    pub const IO_POSSIBLE: Self = Self(29);

    /// Power failure restart (`SIGPWR`).
    ///
    /// Corresponds to signal number `30`.
    ///
    /// (Linux specific) Indicates a power failure.
    pub const POWER_FAILURE: Self = Self(30);

    /// Bad system call (`SIGSYS`).
    ///
    /// Corresponds to signal number `31`.
    ///
    /// Indicates an invalid system call.
    pub const BAD_SYSTEM_CALL: Self = Self(31);
}

impl From<u8> for Signal {
    fn from(signal: u8) -> Self {
        Signal::from_raw(signal)
    }
}

impl Display for Signal {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        self.0.fmt(f)
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_from_raw() {
        assert_eq!(Signal::from_raw(1).to_raw(), 1);
        assert_eq!(Signal::from_raw(15).to_raw(), 15);
        assert_eq!(Signal::from_raw(31).to_raw(), 31);
    }

    #[test]
    fn test_to_raw() {
        let signal = Signal::HANGUP;
        assert_eq!(signal.to_raw(), 1);
    }

    #[test]
    fn test_from_u8() {
        let signal: Signal = 2.into();
        assert_eq!(signal.to_raw(), 2);
    }
}

#[cfg(all(test, feature = "serde"))]
mod serde_tests {
    use super::*;
    use serde_test::{Token, assert_tokens};

    #[test]
    fn test_serde() {
        let signal = Signal::HANGUP;
        assert_tokens(&signal, &[Token::U8(1)]);

        let signal = Signal::from_raw(15);
        assert_tokens(&signal, &[Token::U8(15)]);
    }
}