#![no_std]
#![warn(missing_docs)]
extern crate alloc;
#[cfg(feature = "std")]
extern crate std;
const UNKNOWN_ERROR: &str = "Unknown error";
use core::fmt;
use core::marker::PhantomData;
mod posix;
pub use posix::PosixCategory;
mod system;
pub use system::SystemCategory;
pub trait Category {
const NAME: &'static str;
fn message<'a>(code: i32) -> alloc::borrow::Cow<'a, str>;
}
impl Category for () {
const NAME: &'static str = "Error code";
#[inline(always)]
fn message<'a>(_: i32) -> alloc::borrow::Cow<'a, str> {
alloc::borrow::Cow::Borrowed("")
}
}
pub type PosixError = ErrorCode<PosixCategory>;
pub type SystemError = ErrorCode<SystemCategory>;
pub type PlainError = ErrorCode<()>;
pub struct ErrorCode<C> {
code: i32,
_category: PhantomData<C>,
}
impl ErrorCode<PosixCategory> {
#[inline]
pub fn last() -> Self {
Self::new(posix::get_last_error())
}
}
impl ErrorCode<SystemCategory> {
#[inline]
pub fn last() -> Self {
Self::new(system::get_last_error())
}
}
impl<C: Category> ErrorCode<C> {
#[inline]
pub fn new(code: i32) -> Self {
Self {
code,
_category: PhantomData,
}
}
}
impl<C> From<i32> for ErrorCode<C> {
#[inline]
fn from(code: i32) -> Self {
ErrorCode {
code,
_category: PhantomData
}
}
}
impl<C> Clone for ErrorCode<C> {
#[inline]
fn clone(&self) -> Self {
self.code.into()
}
#[inline]
fn clone_from(&mut self, other: &Self) {
self.code = other.code
}
}
impl<C> Copy for ErrorCode<C> {}
impl<C> PartialEq for ErrorCode<C> {
fn eq(&self, other: &Self) -> bool {
self.code == other.code
}
}
impl<C> PartialOrd for ErrorCode<C> {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
self.code.partial_cmp(&other.code)
}
}
impl<C> Ord for ErrorCode<C> {
#[inline]
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
self.code.cmp(&other.code)
}
}
impl<C> Eq for ErrorCode<C> {}
impl<C> core::hash::Hash for ErrorCode<C> {
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
self.code.hash(state);
}
}
impl<C: Category> fmt::Debug for ErrorCode<C> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{} {}: {}", C::NAME, self.code, C::message(self.code))
}
}
impl<C: Category> fmt::Display for ErrorCode<C> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
<Self as core::fmt::Debug>::fmt(self, f)
}
}
#[cfg(feature = "ufmt")]
impl<C: Category> ufmt::uDebug for ErrorCode<C> {
fn fmt<W: ufmt::uWrite + ?Sized>(&self, f: &mut ufmt::Formatter<'_, W>) -> Result<(), W::Error> {
f.write_str(C::NAME)?;
{
match self.code {
0 => f.write_str("0: "),
mut code => {
let is_neg = if code < 0 {
code = -code;
true
} else {
false
};
let mut buffer = unsafe {
core::mem::MaybeUninit::<[u8; 12]>::uninit().assume_init()
};
let mut buffer_idx = 0;
while code != 0 {
let rem = code % 10;
unsafe {
*buffer.get_unchecked_mut(buffer_idx) = rem as u8 + b'0';
}
buffer_idx += 1;
code = code / 10;
}
if is_neg {
unsafe {
*buffer.get_unchecked_mut(buffer_idx) = b'-';
}
buffer_idx += 1;
}
f.write_str(unsafe {
let buffer = &mut buffer[..buffer_idx];
buffer.reverse();
core::str::from_utf8_unchecked(buffer)
})?;
f.write_str(": ")
},
}?
}
f.write_str(&C::message(self.code))
}
}
#[cfg(feature = "ufmt")]
impl<C: Category> ufmt::uDisplay for ErrorCode<C> {
#[inline]
fn fmt<W: ufmt::uWrite + ?Sized>(&self, f: &mut ufmt::Formatter<'_, W>) -> Result<(), W::Error> {
<Self as ufmt::uDebug>::fmt(self, f)
}
}
#[cfg(feature = "std")]
impl<C: Category> std::error::Error for ErrorCode<C> {}