#![allow(unused)]
#[cfg(feature = "std")]
extern crate std;
pub type SysexitsResult<T> = core::result::Result<T, SysexitsError>;
#[allow(non_camel_case_types)]
#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[repr(u8)]
pub enum SysexitsError {
#[default]
EX_OK = 0,
EX_USAGE = 64,
EX_DATAERR = 65,
EX_NOINPUT = 66,
EX_NOUSER = 67,
EX_NOHOST = 68,
EX_UNAVAILABLE = 69,
EX_SOFTWARE = 70,
EX_OSERR = 71,
EX_OSFILE = 72,
EX_CANTCREAT = 73,
EX_IOERR = 74,
EX_TEMPFAIL = 75,
EX_PROTOCOL = 76,
EX_NOPERM = 77,
EX_CONFIG = 78,
}
impl SysexitsError {
pub fn is_success(&self) -> bool {
*self == Self::EX_OK
}
pub fn is_failure(&self) -> bool {
!self.is_success()
}
pub fn as_u8(&self) -> u8 {
*self as u8
}
pub fn as_i32(&self) -> i32 {
*self as i32
}
pub fn as_str(&self) -> &'static str {
self.name()
}
#[cfg(feature = "std")]
pub fn as_exit_code(&self) -> std::process::ExitCode {
std::process::ExitCode::from(self.as_u8())
}
#[cfg(feature = "std")]
fn as_exit_status(&self) -> Option<std::process::ExitStatus> {
match *self {
Self::EX_OK => Some(std::process::ExitStatus::default()),
_ => None,
}
}
pub fn code(&self) -> Option<i32> {
Some(self.as_i32())
}
pub fn name(&self) -> &'static str {
use SysexitsError::*;
match *self {
EX_OK => "EX_OK",
EX_USAGE => "EX_USAGE",
EX_DATAERR => "EX_DATAERR",
EX_NOINPUT => "EX_NOINPUT",
EX_NOUSER => "EX_NOUSER",
EX_NOHOST => "EX_NOHOST",
EX_UNAVAILABLE => "EX_UNAVAILABLE",
EX_SOFTWARE => "EX_SOFTWARE",
EX_OSERR => "EX_OSERR",
EX_OSFILE => "EX_OSFILE",
EX_CANTCREAT => "EX_CANTCREAT",
EX_IOERR => "EX_IOERR",
EX_TEMPFAIL => "EX_TEMPFAIL",
EX_PROTOCOL => "EX_PROTOCOL",
EX_NOPERM => "EX_NOPERM",
EX_CONFIG => "EX_CONFIG",
}
}
pub fn summary(&self) -> &'static str {
use SysexitsError::*;
match *self {
EX_OK => "successful termination",
EX_USAGE => "command line usage error",
EX_DATAERR => "data format error",
EX_NOINPUT => "cannot open input",
EX_NOUSER => "addressee unknown",
EX_NOHOST => "host name unknown",
EX_UNAVAILABLE => "service unavailable",
EX_SOFTWARE => "internal software error",
EX_OSERR => "system error",
EX_OSFILE => "critical OS file missing",
EX_CANTCREAT => "can't create (user) output file",
EX_IOERR => "input/output error",
EX_TEMPFAIL => "temporary failure",
EX_PROTOCOL => "remote error in protocol",
EX_NOPERM => "permission denied",
EX_CONFIG => "configuration error",
}
}
}
impl core::fmt::Display for SysexitsError {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
write!(f, "{}", self.as_str())
}
}
impl core::str::FromStr for SysexitsError {
type Err = ();
fn from_str(input: &str) -> Result<Self, Self::Err> {
use SysexitsError::*;
Ok(match input {
"EX_OK" => EX_OK,
"EX_USAGE" => EX_USAGE,
"EX_DATAERR" => EX_DATAERR,
"EX_NOINPUT" => EX_NOINPUT,
"EX_NOUSER" => EX_NOUSER,
"EX_NOHOST" => EX_NOHOST,
"EX_UNAVAILABLE" => EX_UNAVAILABLE,
"EX_SOFTWARE" => EX_SOFTWARE,
"EX_OSERR" => EX_OSERR,
"EX_OSFILE" => EX_OSFILE,
"EX_CANTCREAT" => EX_CANTCREAT,
"EX_IOERR" => EX_IOERR,
"EX_TEMPFAIL" => EX_TEMPFAIL,
"EX_PROTOCOL" => EX_PROTOCOL,
"EX_NOPERM" => EX_NOPERM,
"EX_CONFIG" => EX_CONFIG,
_ => match u8::from_str(input) {
Ok(code) => return Self::try_from(code).map_err(|_| ()),
Err(_) => return Err(()),
},
})
}
}
impl TryFrom<u8> for SysexitsError {
type Error = u8;
fn try_from(code: u8) -> Result<Self, Self::Error> {
use SysexitsError::*;
Ok(match code {
0 => EX_OK,
64 => EX_USAGE,
65 => EX_DATAERR,
66 => EX_NOINPUT,
67 => EX_NOUSER,
68 => EX_NOHOST,
69 => EX_UNAVAILABLE,
70 => EX_SOFTWARE,
71 => EX_OSERR,
72 => EX_OSFILE,
73 => EX_CANTCREAT,
74 => EX_IOERR,
75 => EX_TEMPFAIL,
76 => EX_PROTOCOL,
77 => EX_NOPERM,
78 => EX_CONFIG,
_ => return Err(code),
})
}
}
impl TryFrom<i32> for SysexitsError {
type Error = i32;
fn try_from(code: i32) -> Result<Self, Self::Error> {
Self::try_from(code as u8).map_err(|_| code)
}
}
#[cfg(feature = "std")]
impl TryFrom<std::process::ExitStatus> for SysexitsError {
type Error = Option<i32>;
fn try_from(status: std::process::ExitStatus) -> Result<Self, Self::Error> {
match status.code() {
Some(code) => Self::try_from(code).map_err(|_| Some(code)),
None => Err(None),
}
}
}
#[cfg(feature = "std")]
impl From<std::boxed::Box<dyn std::error::Error>> for SysexitsError {
fn from(error: std::boxed::Box<dyn std::error::Error>) -> Self {
Self::from(&error)
}
}
#[cfg(feature = "std")]
impl From<&std::boxed::Box<dyn std::error::Error>> for SysexitsError {
fn from(_error: &std::boxed::Box<dyn std::error::Error>) -> Self {
Self::EX_SOFTWARE
}
}
#[cfg(feature = "std")]
impl From<std::io::Error> for SysexitsError {
fn from(error: std::io::Error) -> Self {
Self::from(&error)
}
}
#[cfg(feature = "std")]
impl From<&std::io::Error> for SysexitsError {
fn from(error: &std::io::Error) -> Self {
use std::io::ErrorKind::*;
match error.kind() {
AddrInUse => Self::EX_TEMPFAIL,
AddrNotAvailable => Self::EX_USAGE,
AlreadyExists => Self::EX_CANTCREAT,
BrokenPipe => Self::EX_IOERR,
ConnectionAborted => Self::EX_PROTOCOL,
ConnectionRefused => Self::EX_UNAVAILABLE,
ConnectionReset => Self::EX_PROTOCOL,
Interrupted => Self::EX_TEMPFAIL,
InvalidData => Self::EX_DATAERR,
InvalidInput => Self::EX_DATAERR,
NotConnected => Self::EX_PROTOCOL,
NotFound => Self::EX_NOINPUT,
Other => Self::EX_UNAVAILABLE,
OutOfMemory => Self::EX_TEMPFAIL,
PermissionDenied => Self::EX_NOPERM,
TimedOut => Self::EX_IOERR,
UnexpectedEof => Self::EX_IOERR,
Unsupported => Self::EX_SOFTWARE,
WouldBlock => Self::EX_IOERR,
WriteZero => Self::EX_IOERR,
_ => Self::EX_UNAVAILABLE, }
}
}
#[cfg(feature = "gofer")]
impl From<gofer::Error> for SysexitsError {
fn from(error: gofer::Error) -> Self {
Self::from(&error)
}
}
#[cfg(feature = "gofer")]
impl From<&gofer::Error> for SysexitsError {
fn from(error: &gofer::Error) -> Self {
use gofer::Error::*;
match error {
InvalidUrl(_) => Self::EX_DATAERR,
UnknownScheme(_) => Self::EX_DATAERR,
_ => Self::EX_SOFTWARE, }
}
}
#[cfg(feature = "serde-json")]
impl From<serde_json::Error> for SysexitsError {
fn from(error: serde_json::Error) -> Self {
Self::from(&error)
}
}
#[cfg(feature = "serde-json")]
impl From<&serde_json::Error> for SysexitsError {
fn from(error: &serde_json::Error) -> Self {
use serde_json::error::Category::*;
match error.classify() {
Io => Self::EX_IOERR,
Syntax => Self::EX_DATAERR,
Data => Self::EX_DATAERR,
Eof => Self::EX_NOINPUT,
_ => Self::EX_SOFTWARE, }
}
}
#[cfg(feature = "tokio")]
impl From<tokio::task::JoinError> for SysexitsError {
fn from(error: tokio::task::JoinError) -> Self {
Self::from(&error)
}
}
#[cfg(feature = "tokio")]
impl From<&tokio::task::JoinError> for SysexitsError {
fn from(_error: &tokio::task::JoinError) -> Self {
Self::EX_SOFTWARE
}
}
#[cfg(feature = "std")]
impl std::process::Termination for SysexitsError {
fn report(self) -> std::process::ExitCode {
(self as u8).into()
}
}
#[cfg(feature = "std")]
impl std::error::Error for SysexitsError {}
#[cfg(feature = "error-stack")]
impl error_stack::Context for SysexitsError {}
#[cfg(feature = "std")]
pub fn exit(code: SysexitsError) -> ! {
std::process::exit(code as i32);
}
#[cfg(feature = "std")]
#[macro_export]
macro_rules! abort {
($code:expr, $($t:tt)*) => {{
std::eprintln!($($t)*);
exit($code)
}};
}