proc_result/
lib.rs

1//! A tiny cross-platforrm library containing exit status and code types.
2//!
3//! Unlike `std::process`, this crate does not require the standard library[^1], nor
4//! `libc`, and can create and interpret exit codes of non-current platforms. For
5//! example, on Windows, it can read and interpret exit codes that may have been
6//! recorded from a Linux process, or vice versa.
7//!
8//! [^1]: The `std` feature is enabled by default, but can be disabled.
9#![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// Import README.md so that doc tests run on it.
20#[allow(dead_code)]
21mod doc_tests {
22    #[doc = include_str!("../README.md")]
23    struct Readme;
24}
25
26/// An exit code or exit state returned by a program.
27#[derive(Clone, Copy, Debug, PartialEq, Eq)]
28#[non_exhaustive]
29pub enum Error {
30    /// An unclassified exit status on a Unix platform.
31    Unix(unix::WaitStatus),
32
33    /// An unclassified exit status on a Windows platform.
34    Windows(windows::ExitCode),
35}
36
37#[cfg(feature = "std")]
38impl Display for Error {
39    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
40        match self {
41            Error::Unix(status) => write!(f, "Unix exit status: {}", status.to_raw()),
42            Error::Windows(code) => write!(f, "Windows exit code: {}", code.to_raw()),
43        }
44    }
45}
46
47#[cfg(feature = "std")]
48impl std::error::Error for Error {}
49
50/// A possible result of running and waiting for a process to terminate.
51#[cfg(feature = "std")]
52pub type ProcResult<T> = std::result::Result<T, Error>;
53
54/// A trait that converts a result of running a process into a [`ProcResult`].
55#[cfg(feature = "std")]
56pub trait ToProcResult<T> {
57    /// Converts the current result of running a process to a [`ProcResult`].
58    ///
59    /// # Errors
60    ///
61    /// If the result was a non-zero exit code, returns [`Error`].
62    fn to_proc_result(&self) -> ProcResult<T>;
63}
64
65#[cfg(feature = "std")]
66impl ToProcResult<()> for std::process::ExitStatus {
67    #[allow(unreachable_code)]
68    fn to_proc_result(&self) -> ProcResult<()> {
69        if self.success() {
70            Ok(())
71        } else {
72            #[cfg(unix)]
73            {
74                let err: unix::WaitStatus = self.into();
75                return Err(Error::Unix(err));
76            }
77            #[cfg(windows)]
78            {
79                let err: windows::ExitCode = self.into();
80                return Err(Error::Windows(err));
81            }
82            panic!("Cannot convert exit status to error on this platform");
83        }
84    }
85}