#[cfg(feature = "use_libc")]
use libc;
use std::num::NonZeroI32;
use strum;
#[derive(
Clone,
Copy,
Debug,
Eq,
Hash,
Ord,
PartialEq,
PartialOrd,
strum::Display,
strum::EnumString,
strum::EnumIter,
strum::FromRepr,
strum::IntoStaticStr,
strum::VariantArray,
)]
#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
#[repr(i32)]
#[non_exhaustive]
pub enum ErrorCode {
Cancelled = 1,
Unknown = 2,
InvalidArgument = 3,
DeadlineExceeded = 4,
NotFound = 5,
AlreadyExists = 6,
PermissionDenied = 7,
ResourceExhausted = 8,
FailedPrecondition = 9,
Aborted = 10,
OutOfRange = 11,
Unimplemented = 12,
Internal = 13,
Unavailable = 14,
DataLoss = 15,
Unauthenticated = 16,
}
impl ErrorCode {
#[cfg(feature = "use_libc")]
pub fn from_errno(errno: i32) -> Option<ErrorCode> {
match errno {
0 => None,
libc::EINVAL | libc::ENAMETOOLONG | libc::E2BIG | libc::EDESTADDRREQ | libc::EDOM | libc::EFAULT | libc::EILSEQ | libc::ENOPROTOOPT | libc::ENOTSOCK | libc::ENOTTY | libc::EPROTOTYPE | libc::ESPIPE => Some(Self::InvalidArgument),
libc::ETIMEDOUT => Some(Self::DeadlineExceeded),
libc::ENODEV | libc::ENOENT | libc::ENOMEDIUM | libc::ENXIO | libc::ESRCH => Some(Self::NotFound),
libc::EEXIST | libc::EADDRNOTAVAIL | libc::EALREADY | libc::ENOTUNIQ => Some(Self::AlreadyExists),
libc::EPERM | libc::EACCES | libc::ENOKEY | libc::EROFS => Some(Self::PermissionDenied),
libc::ENOTEMPTY | libc::EISDIR | libc::ENOTDIR | libc::EADDRINUSE | libc::EBADF | libc::EBADFD | libc::EBUSY | libc::ECHILD | libc::EISCONN | libc::EISNAM | libc::ENOTBLK | libc::ENOTCONN | libc::EPIPE | libc::ESHUTDOWN | libc::ETXTBSY | libc::EUNATCH => Some(Self::FailedPrecondition),
libc::ENOSPC | libc::EDQUOT | libc::EMFILE | libc::EMLINK | libc::ENFILE | libc::ENOBUFS | libc::ENOMEM | libc::EUSERS => Some(Self::ResourceExhausted),
libc::ECHRNG | libc::EFBIG | libc::EOVERFLOW | libc::ERANGE => Some(Self::OutOfRange),
libc::ENOPKG | libc::ENOSYS | libc::ENOTSUP | libc::EAFNOSUPPORT | libc::EPFNOSUPPORT | libc::EPROTONOSUPPORT | libc::ESOCKTNOSUPPORT | libc::EXDEV => Some(Self::Unimplemented),
libc::EAGAIN | libc::ECOMM | libc::ECONNREFUSED | libc::ECONNABORTED | libc::ECONNRESET | libc::EINTR | libc::EHOSTDOWN | libc::EHOSTUNREACH | libc::ENETDOWN | libc::ENETRESET | libc::ENETUNREACH | libc::ENOLCK | libc::ENOLINK | libc::ENONET => Some(Self::Unavailable),
libc::EDEADLK | libc::ESTALE => Some(Self::Aborted),
libc::ECANCELED => Some(Self::Cancelled),
_ => Some(Self::Unknown),
}
}
#[cfg(feature = "use_libc")]
pub fn from_raw_os_error(err: &std::io::Error) -> Option<ErrorCode> {
err.raw_os_error().and_then(Self::from_errno)
}
}
impl From<ErrorCode> for NonZeroI32 {
fn from(code: ErrorCode) -> Self {
NonZeroI32::new(code as i32).expect(&format!(
"The enum value of an ErrorCode must be nonzero, but got '{:?}'",
code
))
}
}
impl TryFrom<i32> for ErrorCode {
type Error = ();
fn try_from(code: i32) -> Result<Self, ()> {
Self::from_repr(code).ok_or(())
}
}
#[cfg(test)]
mod thin_status_tests {
use super::*;
#[cfg(feature = "use_libc")]
#[test]
fn test_cloud_rpc_status_conversions() {
assert_eq!(ErrorCode::from_errno(0), None);
assert_eq!(
ErrorCode::from_errno(libc::ENOENT),
Some(ErrorCode::NotFound)
);
}
}