nu_system/
exit_status.rs

1use std::process;
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq)]
4pub enum ExitStatus {
5    Exited(i32),
6    #[cfg(unix)]
7    Signaled {
8        signal: i32,
9        core_dumped: bool,
10    },
11}
12
13impl ExitStatus {
14    pub fn code(self) -> i32 {
15        match self {
16            ExitStatus::Exited(code) => code,
17            #[cfg(unix)]
18            ExitStatus::Signaled { signal, .. } => -signal,
19        }
20    }
21}
22
23#[cfg(unix)]
24impl From<process::ExitStatus> for ExitStatus {
25    fn from(status: process::ExitStatus) -> Self {
26        use std::os::unix::process::ExitStatusExt;
27
28        match (status.code(), status.signal()) {
29            (Some(code), None) => Self::Exited(code),
30            (None, Some(signal)) => Self::Signaled {
31                signal,
32                core_dumped: status.core_dumped(),
33            },
34            (None, None) => {
35                debug_assert!(false, "ExitStatus should have either a code or a signal");
36                Self::Exited(-1)
37            }
38            (Some(code), Some(signal)) => {
39                // Should be unreachable, as `code()` will be `None` if `signal()` is `Some`
40                // according to the docs for `ExitStatus::code`.
41                debug_assert!(
42                    false,
43                    "ExitStatus cannot have both a code ({code}) and a signal ({signal})"
44                );
45                Self::Signaled {
46                    signal,
47                    core_dumped: status.core_dumped(),
48                }
49            }
50        }
51    }
52}
53
54#[cfg(not(unix))]
55impl From<process::ExitStatus> for ExitStatus {
56    fn from(status: process::ExitStatus) -> Self {
57        let code = status.code();
58        debug_assert!(
59            code.is_some(),
60            "`ExitStatus::code` cannot return `None` on windows"
61        );
62        Self::Exited(code.unwrap_or(-1))
63    }
64}