error-repr 0.1.1

Generalization of std::io::Error
Documentation
//!
#[cfg(feature = "std")]
use crate::kind::FromIoKind;
use crate::kind::{ErrorKind, FromRawOsError};

/// Convience trait for implementing [`FromRawOsError`] and [`FromIoKind`]
pub trait FromOsError: ErrorKind {
    /// COnstructs `Self` from an [`OsError`]
    fn from_os_error(err: OsError) -> Self;
}

impl<E: FromOsError> FromRawOsError for E {
    fn from_raw_os_error(raw: crate::RawOsError) -> Self {
        Self::from_os_error(OsError::from_raw_os_error(raw))
    }
}


#[cfg(feature = "std")]
impl<E: FromOsError> FromIoKind for E {
    fn from_io_error_kind(kind: std::io::ErrorKind) -> Self {
        Self::from_os_error(OsError::from_io_error_kind(kind))
    }
}


/// Variant for encoding most os errors as a generic enum that can be matched upon in code - suitable for implementing [`FromRawOsError`]
///
/// [`OsError`] itself implements [`ErrorKind`] and [`FromRawOsError`]. However, it does not implement or [`IntoIoKind`][crate::kind::IntoIoKind]
///
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
#[non_exhaustive]
pub enum OsError {
    #[doc(hidden)]
    __Uncategorized,
    /// Other errors not generated. Note that this is not produced by the impl for [`FromRawOsError`]
    Other,
    /// Permission Denied
    PermissionDenied,
    /// An Object was not found
    NotFound,
    /// A Process was not found
    NoSuchProcess,
    /// System Call interrupted by signal/remote action
    Interrupted,
    /// Input/Output Error
    InputOutputError,
    /// A name, a record, or list was too large for a system call
    TooBig,
    /// An process being spawned refers to an executable file that cannot be read
    ExecFormatError,
    /// A Handle or File Descriptor is invalid/wrong type
    InvalidHandle,
    /// A Child process was not found
    NoChild,
    /// An operation that was required not to block would have blocked
    WouldBlock,
    /// Memory is unavailable or cannot be allocated
    NoMemory,
    /// A memory address passed to a system call was invalid/not mapped
    InvalidMemory,
    /// A different kind of device was required
    WrongDeviceKind,
    /// An Object being accessed was Busy
    Busy,
    /// An object that was required not to exist was located
    ObjectExists,
    /// An operation crosses devices when it is required not to
    CrossDevice,
    /// A device being identified does not exist
    NoSuchDevice,
    /// An object being used as a directory was not a directory
    NotADirectory,
    /// An object that is required not to be a directory was a directory
    IsADirectory,
    /// Invalid Argument/Operation
    InvalidArgument,
    /// A Global Handle Limit was exceeded
    GlobalHandleExhaustion,
    /// A Local Handle Limit was exceeded
    HandleExhaustion,
    /// Invalid extended operation
    Ioctl,
    /// An executable file is busy
    TextFileBusy,
    /// No Space Left on Device
    NoSpaceLeft,
    /// Seek on Non-Seekable Object
    InvalidSeek,
    /// Read-Only Filesystem
    ReadOnlyFilesystem,
    /// Too many links to the same object
    TooManyLinks,
    /// Symbolic Link Loop or excessive symbolic link chain
    SymbolicLinkChain,
    /// Broken Pipe
    BrokenPipe,
    /// Domain Error
    DomainError,
    /// Range Error
    RangeError,
    /// Deadlock (Avoided)
    Deadlock,
    /// A resource other than handle count, is exhausted
    ResourceExhaustion,

    /// Unsupported System Call
    UnsupportedSystemOp,

    /// Connection Refused
    ConnectionRefused,

    /// Connection Reset
    ConnectionReset,

    /// Invalid Filename
    InvalidFilename,
    /// Operation In-progress
    InProgress,
    /// Quota Exceeded
    QuotaExceeded,
    
    /// Destination Host Unreachable
    HostUnreachable,
    /// Destination Network Unreachable
    NetworkUnreachable,
    /// Connection Aborted
    ConnectionAborted,
    /// Socket not connected
    NotConnected,
    /// Bind address in use
    AddrInUse,
    /// Bind address not available
    AddrNotAvailable,
    /// Network down
    NetworkDown,
    /// Invalid Data
    InvalidData,
    /// Operation timed out
    TimedOut,
    /// Stale File handle
    StaleNetworkFileHandle,
    /// Directory not empty
    DirectoryNotEmpty,
    /// Unexpected Eof
    UnexpectedEof,
    /// Write returned zero
    WriteZero,

    /// Operation Already In progress
    AlreadyInProgress,
}

impl core::fmt::Display for OsError {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        match self {
            OsError::__Uncategorized => f.write_str("Uncategorized Error"),
            OsError::Other => f.write_str("Other Error"),
            OsError::PermissionDenied => f.write_str("Permission Denied"),
            OsError::NotFound => f.write_str("Object not found"),
            OsError::NoSuchProcess => f.write_str("No such process"),
            OsError::Interrupted => f.write_str("Interrupted"),
            OsError::InputOutputError => f.write_str("I/O Error"),
            OsError::TooBig => f.write_str("Object too big"),
            OsError::ExecFormatError => f.write_str("Executable format error"),
            OsError::InvalidHandle => f.write_str("Invalid Handle/Descriptor"),
            OsError::NoChild => f.write_str("No Child Found"),
            OsError::WouldBlock => f.write_str("Operation would block"),
            OsError::NoMemory => f.write_str("Out of memory"),
            OsError::InvalidMemory => f.write_str("Invalid Memory"),
            OsError::WrongDeviceKind => f.write_str("Wrong Device Kind"),
            OsError::Busy => f.write_str("Device or Object Busy"),
            OsError::ObjectExists => f.write_str("Object Exists"),
            OsError::CrossDevice => f.write_str("Operation crosses devices"),
            OsError::NoSuchDevice => f.write_str("No such device"),
            OsError::NotADirectory => f.write_str("Not a Directory"),
            OsError::IsADirectory => f.write_str("Is a Directory"),
            OsError::InvalidArgument => f.write_str("Invalid Argument"),
            OsError::GlobalHandleExhaustion => f.write_str("Too many Global Handles/Descriptors"),
            OsError::HandleExhaustion => f.write_str("Too many Local Handles/Descriptors"),
            OsError::Ioctl => f.write_str("Invalid Ioctl for device"),
            OsError::TextFileBusy => f.write_str("Executable File Busy"),
            OsError::NoSpaceLeft => f.write_str("No Space Left on Device"),
            OsError::InvalidSeek => f.write_str("Invalid Seek on Non-seekable Handle"),
            OsError::ReadOnlyFilesystem => f.write_str("Read-only Filesystem"),
            OsError::SymbolicLinkChain => f.write_str("Symbolic Link Loop or Chain"),
            OsError::BrokenPipe => f.write_str("Broken Pipe"),
            OsError::UnsupportedSystemOp => f.write_str("Unsupported System Call"),
            OsError::TooManyLinks => f.write_str("Too many links"),
            OsError::DomainError => f.write_str("Domain Error"),
            OsError::RangeError => f.write_str("Output out of range"),
            OsError::Deadlock => f.write_str("Deadlock Detected"),
            OsError::ResourceExhaustion => f.write_str("Other Resource Exhaustion"),
            OsError::ConnectionRefused => f.write_str("Connection Refused"),
            OsError::ConnectionReset => f.write_str("Connection Reset"),
            OsError::InvalidFilename => f.write_str("Invalid File Name"),
            OsError::InProgress => f.write_str("Operation In Progress"),
            OsError::QuotaExceeded => f.write_str("Quota/Resource Limit Exceeded"),
            OsError::HostUnreachable => f.write_str("Destination Host Unreachable"),
            OsError::NetworkUnreachable => f.write_str("Destination Network Unreachable"),
            OsError::ConnectionAborted => f.write_str("Connection Aborted"),
            OsError::NotConnected => f.write_str("Not Connected"),
            OsError::AddrInUse => f.write_str("Address In Use"),
            OsError::AddrNotAvailable => f.write_str("Address Not Available"),
            OsError::NetworkDown => f.write_str("Network Down"),
            OsError::InvalidData => f.write_str("Invalid Data"),
            OsError::TimedOut => f.write_str("Operation Timed Out"),
            OsError::StaleNetworkFileHandle => f.write_str("Stale File Handle"),
            OsError::DirectoryNotEmpty => f.write_str("Directory Not Empty"),
            OsError::UnexpectedEof => f.write_str("Unexpected Eof"),
            OsError::WriteZero => f.write_str("Write returned 0"),
            OsError::AlreadyInProgress => f.write_str(" Operation Already Pending"),
        }
    }
}

impl ErrorKind for OsError {
    const OTHER: Self = OsError::Other;
    fn uncategorized() -> Self {
        Self::__Uncategorized
    }
}

impl FromRawOsError for OsError {
    fn from_raw_os_error(raw: crate::RawOsError) -> Self {
        os_error(raw)
    }
}

#[cfg(feature = "std")]
impl FromIoKind for OsError {
    fn from_io_error_kind(kind: std::io::ErrorKind) -> Self {
        match kind {
            std::io::ErrorKind::NotFound => OsError::NotFound,
            std::io::ErrorKind::PermissionDenied => OsError::PermissionDenied,
            std::io::ErrorKind::ConnectionRefused => OsError::ConnectionRefused,
            std::io::ErrorKind::ConnectionReset => OsError::ConnectionReset,
            
            std::io::ErrorKind::BrokenPipe => OsError::BrokenPipe,
            std::io::ErrorKind::AlreadyExists => OsError::ObjectExists,
            std::io::ErrorKind::WouldBlock => OsError::WouldBlock,
            std::io::ErrorKind::NotADirectory => OsError::NotADirectory,
            std::io::ErrorKind::IsADirectory => OsError::IsADirectory,
            std::io::ErrorKind::ReadOnlyFilesystem => OsError::ReadOnlyFilesystem,
            std::io::ErrorKind::InvalidInput => OsError::InvalidArgument,
            std::io::ErrorKind::StorageFull => OsError::NoSpaceLeft,
            std::io::ErrorKind::NotSeekable => OsError::InvalidSeek,
            std::io::ErrorKind::FileTooLarge => OsError::TooBig,
            std::io::ErrorKind::ResourceBusy => OsError::Busy,
            std::io::ErrorKind::ExecutableFileBusy => OsError::TextFileBusy,
            std::io::ErrorKind::Deadlock => OsError::Deadlock,
            std::io::ErrorKind::CrossesDevices => OsError::CrossDevice,
            std::io::ErrorKind::TooManyLinks => OsError::TooManyLinks,
            std::io::ErrorKind::ArgumentListTooLong => OsError::TooBig,
            std::io::ErrorKind::Interrupted => OsError::Interrupted,
            std::io::ErrorKind::Unsupported => OsError::UnsupportedSystemOp,
            std::io::ErrorKind::OutOfMemory => OsError::NoMemory,
            #[cfg(feature = "nightly-io_error_more")]
            std::io::ErrorKind::FilesystemLoop => OsError::SymbolicLinkChain,
            #[cfg(feature = "nightly-io_error_more")]
            std::io::ErrorKind::InProgress => OsError::InProgress,
            std::io::ErrorKind::QuotaExceeded => OsError::QuotaExceeded,
            std::io::ErrorKind::InvalidFilename => OsError::InvalidFilename,
            std::io::ErrorKind::UnexpectedEof => OsError::UnexpectedEof,
            std::io::ErrorKind::HostUnreachable => OsError::HostUnreachable,
            std::io::ErrorKind::NetworkUnreachable => OsError::NetworkUnreachable,
            std::io::ErrorKind::ConnectionAborted => OsError::ConnectionAborted,
            std::io::ErrorKind::NotConnected => OsError::NotConnected,
            std::io::ErrorKind::AddrInUse => OsError::AddrInUse,
            std::io::ErrorKind::AddrNotAvailable => OsError::AddrNotAvailable,
            std::io::ErrorKind::NetworkDown => OsError::NetworkDown,
            std::io::ErrorKind::InvalidData => OsError::InvalidData,
            std::io::ErrorKind::TimedOut => OsError::TimedOut,
            std::io::ErrorKind::WriteZero => OsError::WriteZero,
            std::io::ErrorKind::StaleNetworkFileHandle => OsError::StaleNetworkFileHandle,
            std::io::ErrorKind::DirectoryNotEmpty => OsError::DirectoryNotEmpty,
            std::io::ErrorKind::Other => OsError::Other,
            _ => OsError::__Uncategorized,
        }
    }
}

cfg_select! {
    target_os = "linux" => {
        fn os_error(error: crate::RawOsError) -> OsError {
            use linux_errno::*;
            match u16::try_from(error).ok().and_then(Error::new) {
                Some(err) => {
                    match err {
                        EPERM | EACCES => OsError::PermissionDenied,
                        ENOENT  => OsError::NotFound,
                        ESRCH => OsError::NoSuchProcess,
                        E2BIG | EFBIG | ENAMETOOLONG => OsError::TooBig,
                        EBADF => OsError::InvalidHandle,
                        ECHILD => OsError::NoChild,
                        EAGAIN => OsError::WouldBlock,
                        ENOMEM => OsError::NoMemory,
                        EFAULT => OsError::InvalidMemory,
                        ENOTBLK => OsError::WrongDeviceKind,
                        EBUSY => OsError::Busy,
                        EXDEV => OsError::CrossDevice,
                        ENODEV | ENXIO => OsError::NoSuchDevice,
                        ENOTDIR => OsError::NotADirectory,
                        EISDIR => OsError::IsADirectory,
                        EINVAL => OsError::InvalidArgument,
                        ENFILE => OsError::GlobalHandleExhaustion,
                        EMFILE => OsError::HandleExhaustion,
                        ENOTTY => OsError::Ioctl,
                        ETXTBSY => OsError::TextFileBusy,
                        ENOSPC => OsError::NoSpaceLeft,
                        ESPIPE => OsError::InvalidSeek,
                        EMLINK => OsError::TooManyLinks,
                        EPIPE => OsError::BrokenPipe,
                        EDOM => OsError::DomainError,
                        ERANGE => OsError::RangeError,
                        EDEADLK => OsError::Deadlock,
                        ENOLCK => OsError::ResourceExhaustion,
                        ENOSYS => OsError::UnsupportedSystemOp,
                        EINPROGRESS => OsError::InProgress,
                        EALREADY => OsError::AlreadyInProgress,
                        ETIME => OsError::TimedOut,
                        
                        _ => OsError::__Uncategorized,
                    }
                }
                None => OsError::__Uncategorized
            }
        }
    }
    target_os = "lilium" => {
        fn os_error(error: crate::RawOsError) -> OsError {
            todo!()
        }
    }
    target_os = "windows" => {
        fn os_error(error: crate::RawOsError) -> OsError {
            todo!()
        }
    }
    _ => {
        fn os_error(error: crate::RawOsError) -> OsError {

        }
    }
}