use core::{fmt, marker::PhantomData};
#[allow(unused_imports)]
use crate::abi;
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct Error<Kind = ()> {
code: ErrorCode,
_phantom: PhantomData<Kind>,
}
pub trait ErrorKind: Copy {
fn from_error_code(code: ErrorCode) -> Option<Self>;
}
impl<Kind: ErrorKind> Error<Kind> {
#[inline]
pub unsafe fn new_unchecked(code: ErrorCode) -> Self {
debug_assert!(Kind::from_error_code(code).is_some());
Self {
code,
_phantom: PhantomData,
}
}
#[inline]
pub(crate) unsafe fn err_if_negative(code: abi::ER) -> Result<abi::ER, Self> {
if let Some(e) = ErrorCode::new(code) {
Err(unsafe { Self::new_unchecked(e) })
} else {
Ok(code)
}
}
#[inline]
pub fn kind(self) -> Kind {
unsafe {
Kind::from_error_code(self.code).unwrap_or_else(|| core::hint::unreachable_unchecked())
}
}
#[inline]
pub fn code(self) -> ErrorCode {
self.code
}
}
impl<Kind> fmt::Debug for Error<Kind> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self.code, f)
}
}
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct ErrorCode(abi::NonZeroER);
impl ErrorCode {
#[inline]
pub const fn new(code: abi::ER) -> Option<Self> {
if code >= 0 {
None
} else if let Some(x) = abi::NonZeroER::new(code) {
Some(Self(x))
} else {
None
}
}
#[inline]
pub const unsafe fn new_unchecked(code: abi::ER) -> Self {
Self(unsafe { abi::NonZeroER::new_unchecked(code) })
}
#[inline]
pub const fn get(self) -> abi::ER {
self.0.get()
}
}
impl fmt::Debug for ErrorCode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let name = match () {
#[cfg(any(
feature = "asp3",
feature = "fmp3",
feature = "solid_asp3",
feature = "solid_fmp3"
))]
() => match self.get() {
abi::E_SYS => Some("E_SYS"),
abi::E_NOSPT => Some("E_NOSPT"),
abi::E_RSFN => Some("E_RSFN"),
abi::E_RSATR => Some("E_RSATR"),
abi::E_PAR => Some("E_PAR"),
abi::E_ID => Some("E_ID"),
abi::E_CTX => Some("E_CTX"),
abi::E_MACV => Some("E_MACV"),
abi::E_OACV => Some("E_OACV"),
abi::E_ILUSE => Some("E_ILUSE"),
abi::E_NOMEM => Some("E_NOMEM"),
abi::E_NOID => Some("E_NOID"),
abi::E_NORES => Some("E_NORES"),
abi::E_OBJ => Some("E_OBJ"),
abi::E_NOEXS => Some("E_NOEXS"),
abi::E_QOVR => Some("E_QOVR"),
abi::E_RLWAI => Some("E_RLWAI"),
abi::E_TMOUT => Some("E_TMOUT"),
abi::E_DLT => Some("E_DLT"),
abi::E_CLS => Some("E_CLS"),
abi::E_RASTER => Some("E_RASTER"),
abi::E_WBLK => Some("E_WBLK"),
abi::E_BOVR => Some("E_BOVR"),
abi::E_COMM => Some("E_COMM"),
_ => None,
},
#[cfg(feature = "none")]
() => None,
};
if let Some(name) = name {
f.write_str(name)
} else {
write!(f, "{}", self.get())
}
}
}
impl<Kind: ErrorKind> From<Error<Kind>> for ErrorCode {
#[inline]
fn from(x: Error<Kind>) -> Self {
x.code()
}
}
pub type MaybeKind = ();
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Kind(pub __Unstable);
impl Kind {
#[inline]
pub(crate) fn from_error_code(_: ErrorCode) -> Self {
Self(__Unstable)
}
}
#[doc(hidden)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct __Unstable;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Never {}
macro_rules! define_error_kind {
(
$( #[$meta:meta] )*
pub enum $name:ident {
$(
$( #[doc = $doc:literal] )*
#[cfg( $($cfg:tt)* )]
$variant:ident
),*
$(,)*
}
) => {
$( #[$meta] )*
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum $name {
$(
$( #[doc = $doc] )*
#[doc = ""]
#[doc = concat!("<i>Requires</i>: `cfg(", stringify!($($cfg)*), ")`")]
#[cfg(doc)]
$variant(crate::error::MaybeKind),
#[cfg(all(not(doc), $($cfg)* ))]
$variant(crate::error::Kind),
#[cfg(all(not(doc), not( $($cfg)* )))]
$variant(crate::error::Never),
)*
}
};
}