Documentation
use crate::linux::io_uring::IoUringError;
use crate::linux::sys::Errno;
use alloc::string::String;
use thiserror::Error;

#[derive(Error, Debug)]
pub enum NetworkError {
    #[error("io_uring error: {0}")]
    IoUring(#[from] IoUringError),

    #[error("Invalid address")]
    InvalidAddress,

    #[error("Address already in use")]
    AddressInUse,

    #[error("Connection refused")]
    ConnectionRefused,

    #[error("Connection reset by peer")]
    ConnectionReset,

    #[error("Connection timed out")]
    TimedOut,

    #[error("Network unreachable")]
    NetworkUnreachable,

    #[error("Host unreachable")]
    HostUnreachable,

    #[error("Broken pipe")]
    BrokenPipe,

    #[error("Not connected")]
    NotConnected,

    #[error("Already connected")]
    AlreadyConnected,

    #[error("Would block")]
    WouldBlock,

    #[error("Protocol error")]
    Protocol,

    #[error("Message too large")]
    MessageTooLarge,

    #[error("Buffer pool exhausted")]
    BufferPoolExhausted,

    #[error("System error: {0}")]
    System(i32),

    #[error("{0}")]
    Internal(String),
}

impl From<Errno> for NetworkError {
    fn from(errno: Errno) -> Self {
        match errno {
            Errno::Again => NetworkError::WouldBlock,
            Errno::ConnRefused => NetworkError::ConnectionRefused,
            Errno::ConnReset => NetworkError::ConnectionReset,
            Errno::TimedOut => NetworkError::TimedOut,
            Errno::NetUnreach => NetworkError::NetworkUnreachable,
            Errno::HostUnreach => NetworkError::HostUnreachable,
            Errno::Pipe => NetworkError::BrokenPipe,
            Errno::NotConn => NetworkError::NotConnected,
            Errno::IsConn => NetworkError::AlreadyConnected,
            Errno::Already => NetworkError::AddressInUse,
            _ => NetworkError::System(errno.as_raw()),
        }
    }
}

pub type Result<T> = core::result::Result<T, NetworkError>;