1#![cfg_attr(not(feature = "std"), no_std)]
10
11use core::fmt::Display;
12
13use raw::RawExitCode;
14
15pub mod raw;
16pub mod unix;
17pub mod windows;
18
19#[allow(dead_code)]
21mod doc_tests {
22 #[doc = include_str!("../README.md")]
23 struct Readme;
24}
25
26#[derive(Clone, Copy, Debug, PartialEq, Eq)]
28#[non_exhaustive]
29pub enum ProcResult {
30 Unix(unix::WaitStatus),
32
33 Windows(windows::ExitCode),
35}
36
37impl ProcResult {
38 #[cfg(all(feature = "std", unix))]
40 #[must_use]
41 pub fn default_success() -> Self {
42 Self::Unix(unix::WaitStatus::default())
43 }
44
45 #[cfg(all(feature = "std", windows))]
47 #[must_use]
48 pub fn default_success() -> Self {
49 Self::Windows(windows::ExitCode::default())
50 }
51
52 #[cfg(all(feature = "std", unix))]
54 #[must_use]
55 pub fn default_failure() -> Self {
56 Self::Unix(unix::WaitStatus::from_raw(1)) }
58
59 #[cfg(all(feature = "std", windows))]
61 #[must_use]
62 pub fn default_failure() -> Self {
63 Self::Windows(windows::ExitCode::from_raw(1)) }
65
66 pub fn ok(&self) -> Result<(), Self> {
72 if self.is_success() {
73 Ok(())
74 } else {
75 Err(*self)
76 }
77 }
78
79 #[must_use]
81 pub fn is_success(&self) -> bool {
82 match self {
83 ProcResult::Unix(status) => status.exit_code().is_some_and(|code| code.is_success()),
84 ProcResult::Windows(code) => code.is_success(),
85 }
86 }
87
88 #[must_use]
90 pub fn is_failure(&self) -> bool {
91 !self.is_success()
92 }
93}
94
95#[cfg(feature = "std")]
96impl Display for ProcResult {
97 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
98 match self {
99 Self::Unix(status) => write!(f, "Unix exit status: {}", status.to_raw()),
100 Self::Windows(code) => write!(f, "Windows exit code: {}", code.to_raw()),
101 }
102 }
103}
104
105impl core::error::Error for ProcResult {}
106
107#[cfg(all(feature = "std", unix))]
108impl From<std::process::ExitStatus> for ProcResult {
109 #[allow(unreachable_code)]
110 fn from(status: std::process::ExitStatus) -> Self {
111 Self::Unix(status.into())
112 }
113}
114
115#[cfg(all(feature = "std", windows))]
116impl From<std::process::ExitStatus> for ProcResult {
117 #[allow(unreachable_code)]
118 fn from(status: std::process::ExitStatus) -> Self {
119 Self::Windows(status.into())
120 }
121}
122
123#[cfg(test)]
124mod tests {
125 #[test]
126 #[cfg(feature = "std")]
127 fn test_default_success_proc_result() {
128 use super::ProcResult;
129
130 let result = ProcResult::default_success();
131 assert!(result.is_success());
132 }
133
134 #[test]
135 #[cfg(feature = "std")]
136 fn test_default_failure_proc_result() {
137 use super::ProcResult;
138
139 let result = ProcResult::default_failure();
140 assert!(result.is_failure());
141 }
142}