#![no_std]
#![warn(missing_docs)]
#![cfg_attr(feature = "cargo-clippy", allow(clippy::style))]
#[cfg(feature = "std")]
extern crate std;
const UNKNOWN_ERROR: &str = "Unknown error";
#[allow(unused)]
const FAIL_FORMAT: &str = "Failed to format OS Error";
use core::fmt;
use core::marker::PhantomData;
pub type Str = str_buf::StrBuf::<[u8; 128]>;
mod posix;
pub use posix::PosixCategory;
mod system;
pub use system::SystemCategory;
pub trait Category {
const NAME: &'static str;
fn message(code: i32) -> Str;
}
impl Category for () {
const NAME: &'static str = "Error code";
#[inline(always)]
fn message<'a>(_: i32) -> Str {
Str::new()
}
}
pub type PosixError = ErrorCode<PosixCategory>;
pub type SystemError = ErrorCode<SystemCategory>;
pub type PlainError = ErrorCode<()>;
pub trait IntoCategory<C: Category>: Category + Sized {
fn map_code(code: ErrorCode<Self>) -> ErrorCode<C>;
}
impl IntoCategory<SystemCategory> for PosixCategory {
#[inline]
fn map_code(code: ErrorCode<Self>) -> ErrorCode<SystemCategory> {
ErrorCode::<SystemCategory>::new(code.raw_code())
}
}
impl<T: Category> IntoCategory<T> for T {
#[inline(always)]
fn map_code(code: ErrorCode<Self>) -> ErrorCode<Self> {
code
}
}
pub trait ErrorCodeEnum: Into<i32> {
type Category: Category;
#[inline]
fn error_code(self) -> ErrorCode<Self::Category> {
self.into().into()
}
}
#[repr(transparent)]
pub struct ErrorCode<C> {
code: i32,
_category: PhantomData<C>,
}
impl ErrorCode<PosixCategory> {
#[inline]
pub fn last() -> Self {
Self::new(posix::get_last_error())
}
#[inline]
pub const fn unimplemented() -> Self {
Self::new(posix::get_unimplemented_error())
}
#[inline]
pub const fn is_would_block(self) -> bool {
posix::is_would_block(self.code)
}
}
impl ErrorCode<SystemCategory> {
#[inline]
pub fn last() -> Self {
Self::new(system::get_last_error())
}
#[inline]
pub const fn unimplemented() -> Self {
Self::new(system::get_unimplemented_error())
}
#[inline]
pub const fn is_would_block(self) -> bool {
system::is_would_block(self.code)
}
}
impl<C> ErrorCode<C> {
#[inline]
pub const fn new(code: i32) -> Self {
Self {
code,
_category: PhantomData,
}
}
#[inline]
pub const fn raw_code(self) -> i32 {
self.code
}
#[inline]
pub const fn is_zero(self) -> bool {
self.code == 0
}
}
impl<C: Category> ErrorCode<C> {
#[inline(always)]
pub fn message(self) -> Str {
C::message(self.code)
}
#[inline]
pub fn into_another<O: Category>(self) -> ErrorCode<O> where C: IntoCategory<O> {
C::map_code(self)
}
}
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> {
#[inline]
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> {
#[inline]
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)
}
}
impl<C: Category> fmt::Display for ErrorCode<C> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{} {}: {}", C::NAME, self.code, self.message())
}
}
unsafe impl<C> Send for ErrorCode<C> {}
unsafe impl<C> Sync for ErrorCode<C> {}
impl<C> Unpin for ErrorCode<C> {}
#[cfg(feature = "std")]
impl<C: Category> std::error::Error for ErrorCode<C> {}
#[cfg(feature = "std")]
impl From<ErrorCode<PosixCategory>> for std::io::Error {
#[inline]
fn from(err: ErrorCode<PosixCategory>) -> Self {
Self::from_raw_os_error(err.raw_code())
}
}
#[cfg(feature = "std")]
impl From<std::io::Error> for ErrorCode<PosixCategory> {
#[inline]
fn from(err: std::io::Error) -> Self {
match err.raw_os_error() {
Some(err) => Self::new(err),
None => Self::new(-1),
}
}
}
#[cfg(feature = "std")]
impl PartialEq<std::io::Error> for ErrorCode<PosixCategory> {
#[inline]
fn eq(&self, other: &std::io::Error) -> bool {
if let Some(other) = other.raw_os_error() {
self.code == other
} else {
false
}
}
}
#[cfg(feature = "std")]
impl From<ErrorCode<SystemCategory>> for std::io::Error {
#[inline]
fn from(err: ErrorCode<SystemCategory>) -> Self {
Self::from_raw_os_error(err.raw_code())
}
}
#[cfg(feature = "std")]
impl From<std::io::Error> for ErrorCode<SystemCategory> {
#[inline]
fn from(err: std::io::Error) -> Self {
match err.raw_os_error() {
Some(err) => Self::new(err),
None => Self::new(-1),
}
}
}
#[cfg(feature = "std")]
impl PartialEq<std::io::Error> for ErrorCode<SystemCategory> {
#[inline]
fn eq(&self, other: &std::io::Error) -> bool {
if let Some(other) = other.raw_os_error() {
self.code == other
} else {
false
}
}
}