//! Wrapping `errno` error types use super::*; use std::os::raw::c_int; use std::{ fmt, error }; macro_rules! opaque { ($obj:expr => $msg:literal $(, $args:expr)*) => { { #[derive(Debug)] struct Opaque<'a, T: ?Sized + ::std::fmt::Debug>(::std::fmt::FormatArgs<'a>, T); impl<'a, T: ?Sized + ::std::fmt::Debug> ::std::fmt::Display for Opaque { #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { use ::std::fmt::Write; write!(f, "{}: {:?}", self.0, &self.1) } } impl<'a, T: ?Sized + ::std::fmt::Debug> error::Error for Opaque<'a, T>{} Opaque(::std::format_args!($msg, $(, $args)*), $obj) } }; } pub(crate) use opaque; /// Construct an ad-hoc error wrapping the last OS error. macro_rules! os_error { ($fmt:literal $(, $args:expr)*) => { { #[derive(Debug)] struct AdHoc<'a>(::std::fmt::Arguments<'a>); impl<'a> ::std::fmt::Display for AdHoc<'a> { #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", self.0) } } $crate::err::WrappedOSError::last_os_error(AdHoc(::std::format_args!($fmt $(, $args)*))) } }; ($(#[$outer:meta])* $vis:vis struct $name:ident => $fmt:literal $(; $($rest:tt)*)?) => { $(#[$outer])* #[derive(Debug)] #[repr(transparent)] $vis struct $name($crate::err::WrappedOSError<&'static str>); impl ::std::fmt::Display for $name { #[inline] fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> fmt::Result { f.write_str($fmt) } } impl ::std::error::Error for $name { #[inline] fn source(&self) -> Option<&(dyn ::std::error::Error + 'static)> { self.0.source() } } #[allow(unused)] impl $name { #[inline(always)] fn new() -> Self { Self($crate::err::WrappedOSError::last_os_error($fmt)) } #[inline(always)] fn into_inner(self) -> $crate::err::WrappedOSError<&'static str> { self.0 } } impl ::std::ops::Deref for $name { type Target = $crate::err::WrappedOSError<&'static str>; #[inline] fn deref(&self) -> &Self::Target { &self.0 } } impl ::std::ops::DerefMut for $name { #[inline] fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } } $( $crate::os_error! { $($rest)* } )? }; () => {}; } pub(crate) use os_error; const _: () = { os_error!(struct Test => "Test error"); const fn t() {} fn r(_: &E) {} fn test() { r(&os_error!("Some error message")); } t::() }; /// Wraps a piece of context over an OS error pub struct WrappedOSError(io::Error, E); impl WrappedOSError { pub(crate) fn last_os_error(ctx: E) -> Self { Self(io::Error::last_os_error(), ctx) } pub(crate) fn from_os_error(raw: c_int, ctx: E) -> Self { Self(io::Error::from_raw_os_error(raw), ctx) } } impl WrappedOSError { #[inline] pub fn error(&self) -> &io::Error { &self.0 } #[inline] pub fn raw_error(&self) -> c_int { self.0.raw_os_error().unwrap() } #[inline] pub fn context(&self) -> &E { &self.1 } } impl From> for io::Error { #[inline] fn from(from: WrappedOSError) -> Self { from.0 } } impl error::Error for WrappedOSError where WrappedOSError: fmt::Display + fmt::Debug { #[inline] fn source(&self) -> Option<&(dyn error::Error + 'static)> { Some(&self.0) } } impl fmt::Display for WrappedOSError where E: fmt::Debug { #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{:?}", &self.1) } } impl fmt::Debug for WrappedOSError where E: fmt::Display { #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", &self.1) } }