proc_result/unix/
wait_status.rs

1use super::{ExitCode, Signal, WaitState};
2
3/// A Unix-like wait status.
4///
5/// On Unix-like systems, processes can terminate with a combination of exit codes and signals;
6/// this struct encapsulates that information and can separate the exit code from the signal that
7/// caused the termination, or whether the process was stopped or continued.
8#[derive(Clone, Copy, Debug, PartialEq, Eq)]
9#[cfg_attr(
10    feature = "serde",
11    derive(serde::Serialize, serde::Deserialize),
12    serde(transparent)
13)]
14pub struct WaitStatus(i32);
15
16impl WaitStatus {
17    /// Creates a new `UnixWaitStatus` from the underlying `i32` status code.
18    #[must_use]
19    pub const fn from_raw(status: i32) -> Self {
20        Self(status)
21    }
22
23    /// Returns the underlying `i32` status code.
24    #[must_use]
25    pub const fn to_raw(&self) -> i32 {
26        self.0
27    }
28
29    /// Returns the state represented by this wait status.
30    #[must_use]
31    pub const fn state(&self) -> WaitState {
32        WaitState::from_raw(self.0)
33    }
34
35    /// Returns `true` if the process terminated, regardless of exiting normally or by a signal.
36    #[must_use]
37    pub const fn is_terminated(&self) -> bool {
38        matches!(
39            self.state(),
40            WaitState::Exited { .. } | WaitState::Signaled { .. }
41        )
42    }
43
44    /// Returns `true` if the process terminated normally (i.e., exited without a signal).
45    #[must_use]
46    pub const fn is_exited(&self) -> bool {
47        matches!(self.state(), WaitState::Exited { .. })
48    }
49
50    /// Returns `true` if the process was terminated by a signal.
51    #[must_use]
52    pub const fn is_signaled(&self) -> bool {
53        matches!(self.state(), WaitState::Signaled { .. })
54    }
55
56    /// Returns the exit code if the process terminated normally, or `None` otherwise.
57    #[must_use]
58    pub const fn exit_code(&self) -> Option<ExitCode> {
59        match self.state() {
60            WaitState::Exited { exit_code: code } => Some(code),
61            _ => None,
62        }
63    }
64
65    /// Returns the signal that resulted in this wait status, or `None` if the process exited.
66    #[must_use]
67    pub const fn signal(&self) -> Option<Signal> {
68        match self.state() {
69            WaitState::Signaled { signal, .. } => Some(signal),
70            _ => None,
71        }
72    }
73}
74
75#[cfg(all(unix, feature = "std"))]
76impl From<std::process::ExitStatus> for WaitStatus {
77    fn from(status: std::process::ExitStatus) -> Self {
78        if let Some(code) = status.code() {
79            WaitStatus::from_raw(code)
80        } else {
81            use std::os::unix::process::ExitStatusExt;
82            WaitStatus::from_raw(status.into_raw())
83        }
84    }
85}
86
87#[cfg(all(unix, feature = "std"))]
88impl From<WaitStatus> for std::process::ExitStatus {
89    fn from(status: WaitStatus) -> Self {
90        use std::os::unix::process::ExitStatusExt;
91        std::process::ExitStatus::from_raw(status.to_raw())
92    }
93}