#![allow(dead_code)]
use crate::uapi;
use fuchsia_zircon as zx;
use static_assertions::const_assert_eq;
use std::fmt::{Debug, Display, Formatter};
pub struct Errno {
pub code: ErrnoCode,
anyhow: Option<anyhow::Error>,
}
impl Errno {
#[track_caller]
pub fn new(code: ErrnoCode, name: &'static str, context: Option<String>) -> Errno {
Errno {
code,
anyhow: Some(anyhow::format_err!(
"{} ({}), source: {}, context: {}",
name,
code,
std::panic::Location::caller(),
context.as_ref().unwrap_or(&"None".to_string())
)),
}
}
pub fn fail<A>(code: ErrnoCode) -> Result<A, Errno> {
Err(Errno { code, anyhow: None })
}
pub fn return_value(&self) -> u64 {
self.code.return_value()
}
}
impl Clone for Errno {
fn clone(&self) -> Self {
let anyhow = self.anyhow.as_ref().map(|e| anyhow::anyhow!(e.to_string()));
Errno { code: self.code, anyhow }
}
}
impl PartialEq for Errno {
fn eq(&self, other: &Self) -> bool {
self.code == other.code
}
}
impl PartialEq<ErrnoCode> for Errno {
fn eq(&self, other: &ErrnoCode) -> bool {
self.code == *other
}
}
impl Eq for Errno {}
impl Display for Errno {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match &self.anyhow {
Some(details) => {
write!(f, "errno {}, details: {details}", self.code)
}
None => {
write!(f, "errno {} from unknown location", self.code)
}
}
}
}
impl std::error::Error for Errno {}
impl From<Errno> for zx::Status {
fn from(e: Errno) -> Self {
match e.code.error_code() {
uapi::ENOENT => zx::Status::NOT_FOUND,
uapi::ENOMEM => zx::Status::NO_MEMORY,
uapi::EINVAL => zx::Status::INVALID_ARGS,
uapi::ETIMEDOUT => zx::Status::TIMED_OUT,
uapi::EBUSY => zx::Status::UNAVAILABLE,
uapi::EEXIST => zx::Status::ALREADY_EXISTS,
uapi::EPIPE => zx::Status::PEER_CLOSED,
uapi::ENAMETOOLONG => zx::Status::BAD_PATH,
uapi::EIO => zx::Status::IO,
uapi::EISDIR => zx::Status::NOT_FILE,
uapi::ENOTDIR => zx::Status::NOT_DIR,
uapi::EOPNOTSUPP => zx::Status::NOT_SUPPORTED,
uapi::EBADF => zx::Status::BAD_HANDLE,
uapi::EACCES => zx::Status::ACCESS_DENIED,
uapi::EAGAIN => zx::Status::SHOULD_WAIT,
uapi::EFBIG => zx::Status::FILE_BIG,
uapi::ENOSPC => zx::Status::NO_SPACE,
uapi::ENOTEMPTY => zx::Status::NOT_EMPTY,
uapi::EPROTONOSUPPORT => zx::Status::PROTOCOL_NOT_SUPPORTED,
uapi::ENETUNREACH => zx::Status::ADDRESS_UNREACHABLE,
uapi::EADDRINUSE => zx::Status::ADDRESS_IN_USE,
uapi::ENOTCONN => zx::Status::NOT_CONNECTED,
uapi::ECONNREFUSED => zx::Status::CONNECTION_REFUSED,
uapi::ECONNRESET => zx::Status::CONNECTION_RESET,
uapi::ECONNABORTED => zx::Status::CONNECTION_ABORTED,
_ => zx::Status::NOT_SUPPORTED,
}
}
}
impl Debug for Errno {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
if let Some(err) = self.anyhow.as_ref() {
Debug::fmt(&err, f)
} else {
write!(f, "error {} from unknown location", self.code)
}
}
}
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
pub struct ErrnoCode(u32);
impl ErrnoCode {
pub fn from_return_value(retval: u64) -> Self {
let retval = retval as i64;
if retval >= 0 {
return Self(0);
}
Self(-retval as u32)
}
pub fn from_error_code(code: i16) -> Self {
Self(code as u32)
}
pub fn return_value(&self) -> u64 {
-(self.0 as i32) as u64
}
pub fn error_code(&self) -> u32 {
self.0
}
}
impl Display for ErrnoCode {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
pub const ERESTARTSYS: ErrnoCode = ErrnoCode(512);
pub const ERESTARTNOINTR: ErrnoCode = ErrnoCode(513);
pub const ERESTARTNOHAND: ErrnoCode = ErrnoCode(514);
pub const ERESTART_RESTARTBLOCK: ErrnoCode = ErrnoCode(516);
pub trait ErrnoResultExt<T> {
fn map_eintr(self, errno: Errno) -> Result<T, Errno>;
}
impl<T> ErrnoResultExt<T> for Result<T, Errno> {
fn map_eintr(self, errno: Errno) -> Result<T, Errno> {
self.map_err(|err| if err == EINTR { errno } else { err })
}
}
pub const EPERM: ErrnoCode = ErrnoCode(uapi::EPERM);
pub const ENOENT: ErrnoCode = ErrnoCode(uapi::ENOENT);
pub const ESRCH: ErrnoCode = ErrnoCode(uapi::ESRCH);
pub const EINTR: ErrnoCode = ErrnoCode(uapi::EINTR);
pub const EIO: ErrnoCode = ErrnoCode(uapi::EIO);
pub const ENXIO: ErrnoCode = ErrnoCode(uapi::ENXIO);
pub const E2BIG: ErrnoCode = ErrnoCode(uapi::E2BIG);
pub const ENOEXEC: ErrnoCode = ErrnoCode(uapi::ENOEXEC);
pub const EBADF: ErrnoCode = ErrnoCode(uapi::EBADF);
pub const ECHILD: ErrnoCode = ErrnoCode(uapi::ECHILD);
pub const EAGAIN: ErrnoCode = ErrnoCode(uapi::EAGAIN);
pub const ENOMEM: ErrnoCode = ErrnoCode(uapi::ENOMEM);
pub const EACCES: ErrnoCode = ErrnoCode(uapi::EACCES);
pub const EFAULT: ErrnoCode = ErrnoCode(uapi::EFAULT);
pub const ENOTBLK: ErrnoCode = ErrnoCode(uapi::ENOTBLK);
pub const EBUSY: ErrnoCode = ErrnoCode(uapi::EBUSY);
pub const EEXIST: ErrnoCode = ErrnoCode(uapi::EEXIST);
pub const EXDEV: ErrnoCode = ErrnoCode(uapi::EXDEV);
pub const ENODEV: ErrnoCode = ErrnoCode(uapi::ENODEV);
pub const ENOTDIR: ErrnoCode = ErrnoCode(uapi::ENOTDIR);
pub const EISDIR: ErrnoCode = ErrnoCode(uapi::EISDIR);
pub const EINVAL: ErrnoCode = ErrnoCode(uapi::EINVAL);
pub const ENFILE: ErrnoCode = ErrnoCode(uapi::ENFILE);
pub const EMFILE: ErrnoCode = ErrnoCode(uapi::EMFILE);
pub const ENOTTY: ErrnoCode = ErrnoCode(uapi::ENOTTY);
pub const ETXTBSY: ErrnoCode = ErrnoCode(uapi::ETXTBSY);
pub const EFBIG: ErrnoCode = ErrnoCode(uapi::EFBIG);
pub const ENOSPC: ErrnoCode = ErrnoCode(uapi::ENOSPC);
pub const ESPIPE: ErrnoCode = ErrnoCode(uapi::ESPIPE);
pub const EROFS: ErrnoCode = ErrnoCode(uapi::EROFS);
pub const EMLINK: ErrnoCode = ErrnoCode(uapi::EMLINK);
pub const EPIPE: ErrnoCode = ErrnoCode(uapi::EPIPE);
pub const EDOM: ErrnoCode = ErrnoCode(uapi::EDOM);
pub const ERANGE: ErrnoCode = ErrnoCode(uapi::ERANGE);
pub const EDEADLK: ErrnoCode = ErrnoCode(uapi::EDEADLK);
pub const ENAMETOOLONG: ErrnoCode = ErrnoCode(uapi::ENAMETOOLONG);
pub const ENOLCK: ErrnoCode = ErrnoCode(uapi::ENOLCK);
pub const ENOSYS: ErrnoCode = ErrnoCode(uapi::ENOSYS);
pub const ENOTEMPTY: ErrnoCode = ErrnoCode(uapi::ENOTEMPTY);
pub const ELOOP: ErrnoCode = ErrnoCode(uapi::ELOOP);
pub const EWOULDBLOCK: ErrnoCode = ErrnoCode(uapi::EWOULDBLOCK);
pub const ENOMSG: ErrnoCode = ErrnoCode(uapi::ENOMSG);
pub const EIDRM: ErrnoCode = ErrnoCode(uapi::EIDRM);
pub const ECHRNG: ErrnoCode = ErrnoCode(uapi::ECHRNG);
pub const EL2NSYNC: ErrnoCode = ErrnoCode(uapi::EL2NSYNC);
pub const EL3HLT: ErrnoCode = ErrnoCode(uapi::EL3HLT);
pub const EL3RST: ErrnoCode = ErrnoCode(uapi::EL3RST);
pub const ELNRNG: ErrnoCode = ErrnoCode(uapi::ELNRNG);
pub const EUNATCH: ErrnoCode = ErrnoCode(uapi::EUNATCH);
pub const ENOCSI: ErrnoCode = ErrnoCode(uapi::ENOCSI);
pub const EL2HLT: ErrnoCode = ErrnoCode(uapi::EL2HLT);
pub const EBADE: ErrnoCode = ErrnoCode(uapi::EBADE);
pub const EBADR: ErrnoCode = ErrnoCode(uapi::EBADR);
pub const EXFULL: ErrnoCode = ErrnoCode(uapi::EXFULL);
pub const ENOANO: ErrnoCode = ErrnoCode(uapi::ENOANO);
pub const EBADRQC: ErrnoCode = ErrnoCode(uapi::EBADRQC);
pub const EBADSLT: ErrnoCode = ErrnoCode(uapi::EBADSLT);
pub const EDEADLOCK: ErrnoCode = ErrnoCode(uapi::EDEADLOCK);
pub const EBFONT: ErrnoCode = ErrnoCode(uapi::EBFONT);
pub const ENOSTR: ErrnoCode = ErrnoCode(uapi::ENOSTR);
pub const ENODATA: ErrnoCode = ErrnoCode(uapi::ENODATA);
pub const ETIME: ErrnoCode = ErrnoCode(uapi::ETIME);
pub const ENOSR: ErrnoCode = ErrnoCode(uapi::ENOSR);
pub const ENONET: ErrnoCode = ErrnoCode(uapi::ENONET);
pub const ENOPKG: ErrnoCode = ErrnoCode(uapi::ENOPKG);
pub const EREMOTE: ErrnoCode = ErrnoCode(uapi::EREMOTE);
pub const ENOLINK: ErrnoCode = ErrnoCode(uapi::ENOLINK);
pub const EADV: ErrnoCode = ErrnoCode(uapi::EADV);
pub const ESRMNT: ErrnoCode = ErrnoCode(uapi::ESRMNT);
pub const ECOMM: ErrnoCode = ErrnoCode(uapi::ECOMM);
pub const EPROTO: ErrnoCode = ErrnoCode(uapi::EPROTO);
pub const EMULTIHOP: ErrnoCode = ErrnoCode(uapi::EMULTIHOP);
pub const EDOTDOT: ErrnoCode = ErrnoCode(uapi::EDOTDOT);
pub const EBADMSG: ErrnoCode = ErrnoCode(uapi::EBADMSG);
pub const EOVERFLOW: ErrnoCode = ErrnoCode(uapi::EOVERFLOW);
pub const ENOTUNIQ: ErrnoCode = ErrnoCode(uapi::ENOTUNIQ);
pub const EBADFD: ErrnoCode = ErrnoCode(uapi::EBADFD);
pub const EREMCHG: ErrnoCode = ErrnoCode(uapi::EREMCHG);
pub const ELIBACC: ErrnoCode = ErrnoCode(uapi::ELIBACC);
pub const ELIBBAD: ErrnoCode = ErrnoCode(uapi::ELIBBAD);
pub const ELIBSCN: ErrnoCode = ErrnoCode(uapi::ELIBSCN);
pub const ELIBMAX: ErrnoCode = ErrnoCode(uapi::ELIBMAX);
pub const ELIBEXEC: ErrnoCode = ErrnoCode(uapi::ELIBEXEC);
pub const EILSEQ: ErrnoCode = ErrnoCode(uapi::EILSEQ);
pub const ERESTART: ErrnoCode = ErrnoCode(uapi::ERESTART);
pub const ESTRPIPE: ErrnoCode = ErrnoCode(uapi::ESTRPIPE);
pub const EUSERS: ErrnoCode = ErrnoCode(uapi::EUSERS);
pub const ENOTSOCK: ErrnoCode = ErrnoCode(uapi::ENOTSOCK);
pub const EDESTADDRREQ: ErrnoCode = ErrnoCode(uapi::EDESTADDRREQ);
pub const EMSGSIZE: ErrnoCode = ErrnoCode(uapi::EMSGSIZE);
pub const EPROTOTYPE: ErrnoCode = ErrnoCode(uapi::EPROTOTYPE);
pub const ENOPROTOOPT: ErrnoCode = ErrnoCode(uapi::ENOPROTOOPT);
pub const EPROTONOSUPPORT: ErrnoCode = ErrnoCode(uapi::EPROTONOSUPPORT);
pub const ESOCKTNOSUPPORT: ErrnoCode = ErrnoCode(uapi::ESOCKTNOSUPPORT);
pub const EOPNOTSUPP: ErrnoCode = ErrnoCode(uapi::EOPNOTSUPP);
pub const EPFNOSUPPORT: ErrnoCode = ErrnoCode(uapi::EPFNOSUPPORT);
pub const EAFNOSUPPORT: ErrnoCode = ErrnoCode(uapi::EAFNOSUPPORT);
pub const EADDRINUSE: ErrnoCode = ErrnoCode(uapi::EADDRINUSE);
pub const EADDRNOTAVAIL: ErrnoCode = ErrnoCode(uapi::EADDRNOTAVAIL);
pub const ENETDOWN: ErrnoCode = ErrnoCode(uapi::ENETDOWN);
pub const ENETUNREACH: ErrnoCode = ErrnoCode(uapi::ENETUNREACH);
pub const ENETRESET: ErrnoCode = ErrnoCode(uapi::ENETRESET);
pub const ECONNABORTED: ErrnoCode = ErrnoCode(uapi::ECONNABORTED);
pub const ECONNRESET: ErrnoCode = ErrnoCode(uapi::ECONNRESET);
pub const ENOBUFS: ErrnoCode = ErrnoCode(uapi::ENOBUFS);
pub const EISCONN: ErrnoCode = ErrnoCode(uapi::EISCONN);
pub const ENOTCONN: ErrnoCode = ErrnoCode(uapi::ENOTCONN);
pub const ESHUTDOWN: ErrnoCode = ErrnoCode(uapi::ESHUTDOWN);
pub const ETOOMANYREFS: ErrnoCode = ErrnoCode(uapi::ETOOMANYREFS);
pub const ETIMEDOUT: ErrnoCode = ErrnoCode(uapi::ETIMEDOUT);
pub const ECONNREFUSED: ErrnoCode = ErrnoCode(uapi::ECONNREFUSED);
pub const EHOSTDOWN: ErrnoCode = ErrnoCode(uapi::EHOSTDOWN);
pub const EHOSTUNREACH: ErrnoCode = ErrnoCode(uapi::EHOSTUNREACH);
pub const EALREADY: ErrnoCode = ErrnoCode(uapi::EALREADY);
pub const EINPROGRESS: ErrnoCode = ErrnoCode(uapi::EINPROGRESS);
pub const ESTALE: ErrnoCode = ErrnoCode(uapi::ESTALE);
pub const EUCLEAN: ErrnoCode = ErrnoCode(uapi::EUCLEAN);
pub const ENOTNAM: ErrnoCode = ErrnoCode(uapi::ENOTNAM);
pub const ENAVAIL: ErrnoCode = ErrnoCode(uapi::ENAVAIL);
pub const EISNAM: ErrnoCode = ErrnoCode(uapi::EISNAM);
pub const EREMOTEIO: ErrnoCode = ErrnoCode(uapi::EREMOTEIO);
pub const EDQUOT: ErrnoCode = ErrnoCode(uapi::EDQUOT);
pub const ENOMEDIUM: ErrnoCode = ErrnoCode(uapi::ENOMEDIUM);
pub const EMEDIUMTYPE: ErrnoCode = ErrnoCode(uapi::EMEDIUMTYPE);
pub const ECANCELED: ErrnoCode = ErrnoCode(uapi::ECANCELED);
pub const ENOKEY: ErrnoCode = ErrnoCode(uapi::ENOKEY);
pub const EKEYEXPIRED: ErrnoCode = ErrnoCode(uapi::EKEYEXPIRED);
pub const EKEYREVOKED: ErrnoCode = ErrnoCode(uapi::EKEYREVOKED);
pub const EKEYREJECTED: ErrnoCode = ErrnoCode(uapi::EKEYREJECTED);
pub const EOWNERDEAD: ErrnoCode = ErrnoCode(uapi::EOWNERDEAD);
pub const ENOTRECOVERABLE: ErrnoCode = ErrnoCode(uapi::ENOTRECOVERABLE);
pub const ERFKILL: ErrnoCode = ErrnoCode(uapi::ERFKILL);
pub const EHWPOISON: ErrnoCode = ErrnoCode(uapi::EHWPOISON);
pub const ENOTSUP: ErrnoCode = EOPNOTSUPP;
#[macro_export]
macro_rules! errno {
($err:ident) => {
$crate::errors::Errno::new($crate::errors::$err, stringify!($err), None)
};
($err:ident, $context:expr) => {
$crate::errors::Errno::new(
$crate::errors::$err,
stringify!($err),
Some($context.to_string()),
)
};
}
#[macro_export]
macro_rules! error {
($($args:tt)*) => { Err($crate::errno!($($args)*)) };
}
#[macro_export]
macro_rules! errno_from_code {
($err:expr) => {{
let errno = $crate::errors::ErrnoCode::from_error_code($err);
$crate::errors::Errno::new(errno, stringify!($err), None)
}};
}
#[macro_export]
macro_rules! errno_from_zxio_code {
($err:expr) => {{
let code = $err.raw();
$crate::errno_from_code!(code)
}};
}
#[macro_export]
macro_rules! from_status_like_fdio {
($status:ident) => {{
$crate::from_status_like_fdio!($status, "")
}};
($status:ident, $context:expr) => {{
use fuchsia_zircon as zx;
match $status {
zx::Status::NOT_FOUND => $crate::errno!(ENOENT, $context),
zx::Status::NO_MEMORY => $crate::errno!(ENOMEM, $context),
zx::Status::INVALID_ARGS => $crate::errno!(EINVAL, $context),
zx::Status::BUFFER_TOO_SMALL => $crate::errno!(EINVAL, $context),
zx::Status::TIMED_OUT => $crate::errno!(ETIMEDOUT, $context),
zx::Status::UNAVAILABLE => $crate::errno!(EBUSY, $context),
zx::Status::ALREADY_EXISTS => $crate::errno!(EEXIST, $context),
zx::Status::PEER_CLOSED => $crate::errno!(EPIPE, $context),
zx::Status::BAD_STATE => $crate::errno!(EPIPE, $context),
zx::Status::BAD_PATH => $crate::errno!(ENAMETOOLONG, $context),
zx::Status::IO => $crate::errno!(EIO, $context),
zx::Status::NOT_FILE => $crate::errno!(EISDIR, $context),
zx::Status::NOT_DIR => $crate::errno!(ENOTDIR, $context),
zx::Status::NOT_SUPPORTED => $crate::errno!(EOPNOTSUPP, $context),
zx::Status::WRONG_TYPE => $crate::errno!(EOPNOTSUPP, $context),
zx::Status::OUT_OF_RANGE => $crate::errno!(EINVAL, $context),
zx::Status::NO_RESOURCES => $crate::errno!(ENOMEM, $context),
zx::Status::BAD_HANDLE => $crate::errno!(EBADF, $context),
zx::Status::ACCESS_DENIED => $crate::errno!(EACCES, $context),
zx::Status::SHOULD_WAIT => $crate::errno!(EAGAIN, $context),
zx::Status::FILE_BIG => $crate::errno!(EFBIG, $context),
zx::Status::NO_SPACE => $crate::errno!(ENOSPC, $context),
zx::Status::NOT_EMPTY => $crate::errno!(ENOTEMPTY, $context),
zx::Status::IO_REFUSED => $crate::errno!(ECONNREFUSED, $context),
zx::Status::IO_INVALID => $crate::errno!(EIO, $context),
zx::Status::CANCELED => $crate::errno!(EBADF, $context),
zx::Status::PROTOCOL_NOT_SUPPORTED => {
$crate::errno!(EPROTONOSUPPORT, $context)
}
zx::Status::ADDRESS_UNREACHABLE => $crate::errno!(ENETUNREACH, $context),
zx::Status::ADDRESS_IN_USE => $crate::errno!(EADDRINUSE, $context),
zx::Status::NOT_CONNECTED => $crate::errno!(ENOTCONN, $context),
zx::Status::CONNECTION_REFUSED => $crate::errno!(ECONNREFUSED, $context),
zx::Status::CONNECTION_RESET => $crate::errno!(ECONNRESET, $context),
zx::Status::CONNECTION_ABORTED => $crate::errno!(ECONNABORTED, $context),
_ => $crate::errno!(EIO, $context),
}
}};
}
const_assert_eq!(syncio::zxio::EPERM, uapi::EPERM);
const_assert_eq!(syncio::zxio::ENOENT, uapi::ENOENT);
const_assert_eq!(syncio::zxio::ESRCH, uapi::ESRCH);
const_assert_eq!(syncio::zxio::EINTR, uapi::EINTR);
const_assert_eq!(syncio::zxio::EIO, uapi::EIO);
const_assert_eq!(syncio::zxio::ENXIO, uapi::ENXIO);
const_assert_eq!(syncio::zxio::ENOEXEC, uapi::ENOEXEC);
const_assert_eq!(syncio::zxio::EBADF, uapi::EBADF);
const_assert_eq!(syncio::zxio::ECHILD, uapi::ECHILD);
const_assert_eq!(syncio::zxio::EAGAIN, uapi::EAGAIN);
const_assert_eq!(syncio::zxio::ENOMEM, uapi::ENOMEM);
const_assert_eq!(syncio::zxio::EACCES, uapi::EACCES);
const_assert_eq!(syncio::zxio::EFAULT, uapi::EFAULT);
const_assert_eq!(syncio::zxio::ENOTBLK, uapi::ENOTBLK);
const_assert_eq!(syncio::zxio::EBUSY, uapi::EBUSY);
const_assert_eq!(syncio::zxio::EEXIST, uapi::EEXIST);
const_assert_eq!(syncio::zxio::EXDEV, uapi::EXDEV);
const_assert_eq!(syncio::zxio::ENODEV, uapi::ENODEV);
const_assert_eq!(syncio::zxio::ENOTDIR, uapi::ENOTDIR);
const_assert_eq!(syncio::zxio::EISDIR, uapi::EISDIR);
const_assert_eq!(syncio::zxio::EINVAL, uapi::EINVAL);
const_assert_eq!(syncio::zxio::ENFILE, uapi::ENFILE);
const_assert_eq!(syncio::zxio::EMFILE, uapi::EMFILE);
const_assert_eq!(syncio::zxio::ENOTTY, uapi::ENOTTY);
const_assert_eq!(syncio::zxio::ETXTBSY, uapi::ETXTBSY);
const_assert_eq!(syncio::zxio::EFBIG, uapi::EFBIG);
const_assert_eq!(syncio::zxio::ENOSPC, uapi::ENOSPC);
const_assert_eq!(syncio::zxio::ESPIPE, uapi::ESPIPE);
const_assert_eq!(syncio::zxio::EROFS, uapi::EROFS);
const_assert_eq!(syncio::zxio::EMLINK, uapi::EMLINK);
const_assert_eq!(syncio::zxio::EPIPE, uapi::EPIPE);
const_assert_eq!(syncio::zxio::EDOM, uapi::EDOM);
const_assert_eq!(syncio::zxio::ERANGE, uapi::ERANGE);
const_assert_eq!(syncio::zxio::EDEADLK, uapi::EDEADLK);
const_assert_eq!(syncio::zxio::ENAMETOOLONG, uapi::ENAMETOOLONG);
const_assert_eq!(syncio::zxio::ENOLCK, uapi::ENOLCK);
const_assert_eq!(syncio::zxio::ENOSYS, uapi::ENOSYS);
const_assert_eq!(syncio::zxio::ENOTEMPTY, uapi::ENOTEMPTY);
const_assert_eq!(syncio::zxio::ELOOP, uapi::ELOOP);
const_assert_eq!(syncio::zxio::ENOMSG, uapi::ENOMSG);
const_assert_eq!(syncio::zxio::EIDRM, uapi::EIDRM);
const_assert_eq!(syncio::zxio::ECHRNG, uapi::ECHRNG);
const_assert_eq!(syncio::zxio::ELNRNG, uapi::ELNRNG);
const_assert_eq!(syncio::zxio::EUNATCH, uapi::EUNATCH);
const_assert_eq!(syncio::zxio::ENOCSI, uapi::ENOCSI);
const_assert_eq!(syncio::zxio::EBADE, uapi::EBADE);
const_assert_eq!(syncio::zxio::EBADR, uapi::EBADR);
const_assert_eq!(syncio::zxio::EXFULL, uapi::EXFULL);
const_assert_eq!(syncio::zxio::ENOANO, uapi::ENOANO);
const_assert_eq!(syncio::zxio::EBADRQC, uapi::EBADRQC);
const_assert_eq!(syncio::zxio::EBADSLT, uapi::EBADSLT);
const_assert_eq!(syncio::zxio::EBFONT, uapi::EBFONT);
const_assert_eq!(syncio::zxio::ENOSTR, uapi::ENOSTR);
const_assert_eq!(syncio::zxio::ENODATA, uapi::ENODATA);
const_assert_eq!(syncio::zxio::ETIME, uapi::ETIME);
const_assert_eq!(syncio::zxio::ENOSR, uapi::ENOSR);
const_assert_eq!(syncio::zxio::ENONET, uapi::ENONET);
const_assert_eq!(syncio::zxio::ENOPKG, uapi::ENOPKG);
const_assert_eq!(syncio::zxio::EREMOTE, uapi::EREMOTE);
const_assert_eq!(syncio::zxio::ENOLINK, uapi::ENOLINK);
const_assert_eq!(syncio::zxio::EADV, uapi::EADV);
const_assert_eq!(syncio::zxio::ESRMNT, uapi::ESRMNT);
const_assert_eq!(syncio::zxio::ECOMM, uapi::ECOMM);
const_assert_eq!(syncio::zxio::EPROTO, uapi::EPROTO);
const_assert_eq!(syncio::zxio::EMULTIHOP, uapi::EMULTIHOP);
const_assert_eq!(syncio::zxio::EDOTDOT, uapi::EDOTDOT);
const_assert_eq!(syncio::zxio::EBADMSG, uapi::EBADMSG);
const_assert_eq!(syncio::zxio::EOVERFLOW, uapi::EOVERFLOW);
const_assert_eq!(syncio::zxio::ENOTUNIQ, uapi::ENOTUNIQ);
const_assert_eq!(syncio::zxio::EBADFD, uapi::EBADFD);
const_assert_eq!(syncio::zxio::EREMCHG, uapi::EREMCHG);
const_assert_eq!(syncio::zxio::ELIBACC, uapi::ELIBACC);
const_assert_eq!(syncio::zxio::ELIBBAD, uapi::ELIBBAD);
const_assert_eq!(syncio::zxio::ELIBSCN, uapi::ELIBSCN);
const_assert_eq!(syncio::zxio::ELIBMAX, uapi::ELIBMAX);
const_assert_eq!(syncio::zxio::ELIBEXEC, uapi::ELIBEXEC);
const_assert_eq!(syncio::zxio::EILSEQ, uapi::EILSEQ);
const_assert_eq!(syncio::zxio::ERESTART, uapi::ERESTART);
const_assert_eq!(syncio::zxio::ESTRPIPE, uapi::ESTRPIPE);
const_assert_eq!(syncio::zxio::EUSERS, uapi::EUSERS);
const_assert_eq!(syncio::zxio::ENOTSOCK, uapi::ENOTSOCK);
const_assert_eq!(syncio::zxio::EDESTADDRREQ, uapi::EDESTADDRREQ);
const_assert_eq!(syncio::zxio::EMSGSIZE, uapi::EMSGSIZE);
const_assert_eq!(syncio::zxio::EPROTOTYPE, uapi::EPROTOTYPE);
const_assert_eq!(syncio::zxio::ENOPROTOOPT, uapi::ENOPROTOOPT);
const_assert_eq!(syncio::zxio::EPROTONOSUPPORT, uapi::EPROTONOSUPPORT);
const_assert_eq!(syncio::zxio::ESOCKTNOSUPPORT, uapi::ESOCKTNOSUPPORT);
const_assert_eq!(syncio::zxio::EOPNOTSUPP, uapi::EOPNOTSUPP);
const_assert_eq!(syncio::zxio::EPFNOSUPPORT, uapi::EPFNOSUPPORT);
const_assert_eq!(syncio::zxio::EAFNOSUPPORT, uapi::EAFNOSUPPORT);
const_assert_eq!(syncio::zxio::EADDRINUSE, uapi::EADDRINUSE);
const_assert_eq!(syncio::zxio::EADDRNOTAVAIL, uapi::EADDRNOTAVAIL);
const_assert_eq!(syncio::zxio::ENETDOWN, uapi::ENETDOWN);
const_assert_eq!(syncio::zxio::ENETUNREACH, uapi::ENETUNREACH);
const_assert_eq!(syncio::zxio::ENETRESET, uapi::ENETRESET);
const_assert_eq!(syncio::zxio::ECONNABORTED, uapi::ECONNABORTED);
const_assert_eq!(syncio::zxio::ECONNRESET, uapi::ECONNRESET);
const_assert_eq!(syncio::zxio::ENOBUFS, uapi::ENOBUFS);
const_assert_eq!(syncio::zxio::EISCONN, uapi::EISCONN);
const_assert_eq!(syncio::zxio::ENOTCONN, uapi::ENOTCONN);
const_assert_eq!(syncio::zxio::ESHUTDOWN, uapi::ESHUTDOWN);
const_assert_eq!(syncio::zxio::ETOOMANYREFS, uapi::ETOOMANYREFS);
const_assert_eq!(syncio::zxio::ETIMEDOUT, uapi::ETIMEDOUT);
const_assert_eq!(syncio::zxio::ECONNREFUSED, uapi::ECONNREFUSED);
const_assert_eq!(syncio::zxio::EHOSTDOWN, uapi::EHOSTDOWN);
const_assert_eq!(syncio::zxio::EHOSTUNREACH, uapi::EHOSTUNREACH);
const_assert_eq!(syncio::zxio::EALREADY, uapi::EALREADY);
const_assert_eq!(syncio::zxio::EINPROGRESS, uapi::EINPROGRESS);
const_assert_eq!(syncio::zxio::ESTALE, uapi::ESTALE);
const_assert_eq!(syncio::zxio::EUCLEAN, uapi::EUCLEAN);
const_assert_eq!(syncio::zxio::ENOTNAM, uapi::ENOTNAM);
const_assert_eq!(syncio::zxio::ENAVAIL, uapi::ENAVAIL);
const_assert_eq!(syncio::zxio::EISNAM, uapi::EISNAM);
const_assert_eq!(syncio::zxio::EREMOTEIO, uapi::EREMOTEIO);
const_assert_eq!(syncio::zxio::EDQUOT, uapi::EDQUOT);
const_assert_eq!(syncio::zxio::ENOMEDIUM, uapi::ENOMEDIUM);
const_assert_eq!(syncio::zxio::EMEDIUMTYPE, uapi::EMEDIUMTYPE);
const_assert_eq!(syncio::zxio::ECANCELED, uapi::ECANCELED);
const_assert_eq!(syncio::zxio::ENOKEY, uapi::ENOKEY);
const_assert_eq!(syncio::zxio::EKEYEXPIRED, uapi::EKEYEXPIRED);
const_assert_eq!(syncio::zxio::EKEYREVOKED, uapi::EKEYREVOKED);
const_assert_eq!(syncio::zxio::EKEYREJECTED, uapi::EKEYREJECTED);
const_assert_eq!(syncio::zxio::EOWNERDEAD, uapi::EOWNERDEAD);
const_assert_eq!(syncio::zxio::ENOTRECOVERABLE, uapi::ENOTRECOVERABLE);
const_assert_eq!(syncio::zxio::ERFKILL, uapi::ERFKILL);
const_assert_eq!(syncio::zxio::EHWPOISON, uapi::EHWPOISON);
pub use errno;
pub use errno_from_code;
pub use errno_from_zxio_code;
pub use error;
pub use from_status_like_fdio;
pub trait SourceContext<T, E> {
#[track_caller]
fn with_source_context(self, context: impl FnOnce() -> String) -> anyhow::Result<T>;
#[track_caller]
fn source_context<C>(self, context: C) -> anyhow::Result<T>
where
C: Display + Send + Sync + 'static;
}
impl<T, E> SourceContext<T, E> for Result<T, E>
where
Result<T, E>: anyhow::Context<T, E>,
{
fn with_source_context(self, context: impl FnOnce() -> String) -> anyhow::Result<T> {
use anyhow::Context;
let caller = std::panic::Location::caller();
self.with_context(move || format!("{}, {}", context(), caller))
}
fn source_context<C>(self, context: C) -> anyhow::Result<T>
where
C: Display + Send + Sync + 'static,
{
use anyhow::Context;
let caller = std::panic::Location::caller();
self.context(format!("{}, {}", context, caller))
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::panic::Location;
#[test]
fn with_source_context() {
let errno = Errno { code: ENOENT, anyhow: None };
let result: Result<(), Errno> = Err(errno);
let error = result.with_source_context(|| format!("42")).unwrap_err();
let line_after_error = Location::caller();
let expected_prefix =
format!("42, {}:{}:", line_after_error.file(), line_after_error.line() - 1,);
assert!(
error.to_string().starts_with(&expected_prefix),
"{:?} must start with {:?}",
error,
expected_prefix
);
}
#[test]
fn source_context() {
let errno = Errno { code: ENOENT, anyhow: None };
let result: Result<(), Errno> = Err(errno);
let error = result.source_context("42").unwrap_err();
let line_after_error = Location::caller();
let expected_prefix =
format!("42, {}:{}:", line_after_error.file(), line_after_error.line() - 1,);
assert!(
error.to_string().starts_with(&expected_prefix),
"{:?} must start with {:?}",
error,
expected_prefix
);
}
}