use crate::io::ErrorKind;
use core::fmt::{self, Display, Formatter};
#[cfg(feature = "alloc")]
use alloc::boxed::Box;
#[cfg(feature = "alloc")]
use alloc::collections::TryReserveError;
#[cfg(feature = "alloc")]
use alloc::ffi::NulError;
#[cfg(feature = "std")]
use std::fs::TryLockError;
#[derive(Debug)]
pub struct Error(Inner);
impl Error {
#[cfg(feature = "alloc")]
#[inline]
#[must_use]
pub fn new<E: Into<Box<dyn core::error::Error + Send + Sync>>>(kind: ErrorKind, source: E) -> Self {
#[cfg(feature = "std")]
let e = Inner::new(kind.into(), source).into();
#[cfg(not(feature = "std"))]
let e = Self::new_large(kind, source);
e
}
#[cfg(not(feature = "std"))]
#[inline]
#[must_use]
pub(crate) const fn new_small(kind: ErrorKind, message: Option<&'static str>) -> Self {
let inner = Inner::Small { kind, message };
Self(inner)
}
#[cfg(all(not(feature = "std"), feature = "alloc"))]
#[inline]
#[must_use]
pub(crate) fn new_large<E: Into<Box<dyn core::error::Error + Send + Sync>>>(kind: ErrorKind, source: E) -> Self {
let inner = Inner::Large { kind, source: source.into() };
Self(inner)
}
#[cfg(feature = "std")]
#[inline]
#[must_use]
pub fn from_raw_os_error(raw: i32) -> Self {
let inner = Inner::from_raw_os_error(raw);
Self(inner)
}
#[cfg(feature = "std")]
#[inline]
#[must_use]
pub fn last_os_error() -> Self {
let inner = Inner::last_os_error();
Self(inner)
}
#[must_use]
pub fn get_ref(&self) -> Option<&(dyn core::error::Error + Send + Sync + 'static)> {
#[cfg(feature = "std")]
let e = self.0.get_ref();
#[cfg(not(feature = "std"))]
let e = match self.0 {
#[cfg(feature = "alloc")]
Inner::Large { ref source, .. } => Some(&**source),
_ => None,
};
e
}
#[must_use]
pub fn get_mut(&mut self) -> Option<&mut (dyn core::error::Error + Send + Sync + 'static)> {
#[cfg(feature = "std")]
let e = self.0.get_mut();
#[cfg(not(feature = "std"))]
let e = match self.0 {
#[cfg(feature = "alloc")]
Inner::Large { ref mut source, .. } => Some(&mut **source),
_ => None,
};
e
}
#[must_use]
pub fn kind(&self) -> ErrorKind {
#[cfg(feature = "std")]
let kind = self.0.kind().into();
#[cfg(not(feature = "std"))]
let kind = match self.0 {
Inner::Small { kind, .. } => kind,
#[cfg(feature = "alloc")]
Inner::Large { kind, .. } => kind,
};
kind
}
#[cfg(feature = "std")]
#[inline]
#[must_use]
pub fn raw_os_error(&self) -> Option<i32> {
self.0.raw_os_error()
}
#[inline]
#[must_use]
pub(crate) fn is_interrupted(&self) -> bool {
matches!(self.kind(), ErrorKind::Interrupted)
}
#[cfg(feature = "alloc")]
#[must_use]
pub fn into_inner(self) -> Option<Box<dyn core::error::Error + Send + Sync>> {
#[cfg(feature = "std")]
let e = self.0.into_inner();
#[cfg(not(feature = "std"))]
let e = match self.0 {
Inner::Large { source, .. } => Some(source),
_ => None,
};
e
}
}
impl Display for Error {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
Display::fmt(&self.0, f)
}
}
impl core::error::Error for Error {
fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
#[cfg(feature = "std")]
let e = self.0.source();
#[cfg(not(feature = "std"))]
let e = match self.0 {
#[cfg(feature = "alloc")]
Inner::Large { ref source, .. } => source.source(),
_ => None,
};
e
}
}
#[cfg(feature = "std")]
impl From<std::io::Error> for Error {
#[inline]
fn from(value: std::io::Error) -> Self {
Self(value)
}
}
impl From<ErrorKind> for Error {
#[inline]
fn from(value: ErrorKind) -> Self {
#[cfg(feature = "std")]
let e = Self(std::io::ErrorKind::from(value).into());
#[cfg(not(feature = "std"))]
let e = Self::new_small(value, None);
e
}
}
#[cfg(feature = "alloc")]
impl From<NulError> for Error {
#[cfg_attr(not(feature = "std"), expect(unused))]
#[inline]
fn from(value: NulError) -> Self {
#[cfg(feature = "std")]
let e = Self(value.into());
#[cfg(not(feature = "std"))]
let e = Self::new(ErrorKind::InvalidData, "nul byte found");
e
}
}
#[cfg(feature = "std")]
impl From<TryLockError> for Error {
#[inline]
fn from(value: TryLockError) -> Self {
Self(value.into())
}
}
#[cfg(feature = "alloc")]
impl From<TryReserveError> for Error {
#[cfg_attr(not(feature = "std"), expect(unused))]
#[inline]
fn from(value: TryReserveError) -> Self {
#[cfg(feature = "std")]
let e = Self(value.into());
#[cfg(not(feature = "std"))]
let e = ErrorKind::OutOfMemory.into();
e
}
}
#[cfg(feature = "std")]
type Inner = std::io::Error;
#[cfg(not(feature = "std"))]
#[derive(Debug)]
enum Inner {
Small {
kind: ErrorKind,
message: Option<&'static str>,
},
#[cfg(feature = "alloc")]
Large {
kind: ErrorKind,
source: Box<dyn core::error::Error + Send + Sync>,
},
}
#[cfg(not(feature = "std"))]
impl Display for Inner {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match *self {
#[cfg(not(feature = "std"))]
Self::Small { ref kind, message: None } => {
write!(f, "{kind}")
}
#[cfg(not(feature = "std"))]
Self::Small { ref kind, message: Some(message) } => {
write!(f, "{kind}: {message}")
}
#[cfg(all(not(feature = "std"), feature = "alloc"))]
Self::Large { ref kind, ref source } => {
write!(f, "{kind}: {source}")
}
#[cfg(feature = "std")]
Self::Std(ref e) => {
write!(f, "{e}")
}
}
}
}
#[cfg(feature = "std")]
impl From<Error> for std::io::Error {
#[inline]
fn from(value: Error) -> Self {
value.0
}
}