#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
#[cfg(feature = "remote")]
pub mod client;
pub mod composite;
#[cfg(feature = "host-net")]
pub mod host;
pub mod loopback;
pub mod meta;
#[cfg(feature = "remote")]
pub mod rx_tx;
#[cfg(feature = "remote")]
pub mod server;
pub mod tcp_pair;
#[cfg(feature = "tokio")]
#[cfg(test)]
mod tests;
#[cfg(feature = "remote")]
pub use client::{RemoteNetworkingClient, RemoteNetworkingClientDriver};
pub use composite::CompositeTcpListener;
pub use loopback::LoopbackNetworking;
use pin_project_lite::pin_project;
#[cfg(feature = "rkyv")]
use rkyv::{Archive, CheckBytes, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize};
#[cfg(feature = "remote")]
pub use server::{RemoteNetworkingServer, RemoteNetworkingServerDriver};
use std::fmt;
use std::mem::MaybeUninit;
use std::net::IpAddr;
use std::net::Ipv4Addr;
use std::net::Ipv6Addr;
use std::net::Shutdown;
use std::net::SocketAddr;
use std::pin::Pin;
use std::sync::Arc;
use std::task::Context;
use std::task::Poll;
use std::time::Duration;
use thiserror::Error;
#[cfg(feature = "tokio")]
use tokio::io::AsyncRead;
#[cfg(feature = "tokio")]
use tokio::io::AsyncWrite;
pub use bytes::Bytes;
pub use bytes::BytesMut;
use serde::{Deserialize, Serialize};
pub use virtual_mio::{handler_into_waker, InterestHandler};
#[cfg(feature = "host-net")]
pub use virtual_mio::{InterestGuard, InterestHandlerWaker, InterestType};
pub type Result<T> = std::result::Result<T, NetworkError>;
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize, Deserialize)]
#[cfg_attr(feature = "rkyv", derive(RkyvSerialize, RkyvDeserialize, Archive))]
#[cfg_attr(feature = "rkyv", archive_attr(derive(CheckBytes)))]
pub struct IpCidr {
    pub ip: IpAddr,
    pub prefix: u8,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
#[cfg_attr(feature = "rkyv", derive(RkyvSerialize, RkyvDeserialize, Archive))]
#[cfg_attr(feature = "rkyv", archive_attr(derive(CheckBytes)))]
pub struct IpRoute {
    pub cidr: IpCidr,
    pub via_router: IpAddr,
    pub preferred_until: Option<Duration>,
    pub expires_at: Option<Duration>,
}
pub trait VirtualIoSource: fmt::Debug + Send + Sync + 'static {
    fn remove_handler(&mut self);
    fn poll_read_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<usize>>;
    fn poll_write_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<usize>>;
}
#[async_trait::async_trait]
#[allow(unused_variables)]
pub trait VirtualNetworking: fmt::Debug + Send + Sync + 'static {
    async fn bridge(
        &self,
        network: &str,
        access_token: &str,
        security: StreamSecurity,
    ) -> Result<()> {
        Err(NetworkError::Unsupported)
    }
    async fn unbridge(&self) -> Result<()> {
        Err(NetworkError::Unsupported)
    }
    async fn dhcp_acquire(&self) -> Result<Vec<IpAddr>> {
        Err(NetworkError::Unsupported)
    }
    async fn ip_add(&self, ip: IpAddr, prefix: u8) -> Result<()> {
        Err(NetworkError::Unsupported)
    }
    async fn ip_remove(&self, ip: IpAddr) -> Result<()> {
        Err(NetworkError::Unsupported)
    }
    async fn ip_clear(&self) -> Result<()> {
        Err(NetworkError::Unsupported)
    }
    async fn ip_list(&self) -> Result<Vec<IpCidr>> {
        Err(NetworkError::Unsupported)
    }
    async fn mac(&self) -> Result<[u8; 6]> {
        Err(NetworkError::Unsupported)
    }
    async fn gateway_set(&self, ip: IpAddr) -> Result<()> {
        Err(NetworkError::Unsupported)
    }
    async fn route_add(
        &self,
        cidr: IpCidr,
        via_router: IpAddr,
        preferred_until: Option<Duration>,
        expires_at: Option<Duration>,
    ) -> Result<()> {
        Err(NetworkError::Unsupported)
    }
    async fn route_remove(&self, cidr: IpAddr) -> Result<()> {
        Err(NetworkError::Unsupported)
    }
    async fn route_clear(&self) -> Result<()> {
        Err(NetworkError::Unsupported)
    }
    async fn route_list(&self) -> Result<Vec<IpRoute>> {
        Err(NetworkError::Unsupported)
    }
    async fn bind_raw(&self) -> Result<Box<dyn VirtualRawSocket + Sync>> {
        Err(NetworkError::Unsupported)
    }
    async fn listen_tcp(
        &self,
        addr: SocketAddr,
        only_v6: bool,
        reuse_port: bool,
        reuse_addr: bool,
    ) -> Result<Box<dyn VirtualTcpListener + Sync>> {
        Err(NetworkError::Unsupported)
    }
    async fn bind_udp(
        &self,
        addr: SocketAddr,
        reuse_port: bool,
        reuse_addr: bool,
    ) -> Result<Box<dyn VirtualUdpSocket + Sync>> {
        Err(NetworkError::Unsupported)
    }
    async fn bind_icmp(&self, addr: IpAddr) -> Result<Box<dyn VirtualIcmpSocket + Sync>> {
        Err(NetworkError::Unsupported)
    }
    async fn connect_tcp(
        &self,
        addr: SocketAddr,
        peer: SocketAddr,
    ) -> Result<Box<dyn VirtualTcpSocket + Sync>> {
        Err(NetworkError::Unsupported)
    }
    async fn resolve(
        &self,
        host: &str,
        port: Option<u16>,
        dns_server: Option<IpAddr>,
    ) -> Result<Vec<IpAddr>> {
        Err(NetworkError::Unsupported)
    }
}
pub type DynVirtualNetworking = Arc<dyn VirtualNetworking>;
pub trait VirtualTcpListener: VirtualIoSource + fmt::Debug + Send + Sync + 'static {
    fn try_accept(&mut self) -> Result<(Box<dyn VirtualTcpSocket + Sync>, SocketAddr)>;
    fn set_handler(&mut self, handler: Box<dyn InterestHandler + Send + Sync>) -> Result<()>;
    fn addr_local(&self) -> Result<SocketAddr>;
    fn set_ttl(&mut self, ttl: u8) -> Result<()>;
    fn ttl(&self) -> Result<u8>;
}
#[async_trait::async_trait]
pub trait VirtualTcpListenerExt: VirtualTcpListener {
    async fn accept(&mut self) -> Result<(Box<dyn VirtualTcpSocket + Sync>, SocketAddr)>;
}
#[async_trait::async_trait]
impl<R: VirtualTcpListener + ?Sized> VirtualTcpListenerExt for R {
    async fn accept(&mut self) -> Result<(Box<dyn VirtualTcpSocket + Sync>, SocketAddr)> {
        struct Poller<'a, R>
        where
            R: VirtualTcpListener + ?Sized,
        {
            listener: &'a mut R,
        }
        impl<'a, R> std::future::Future for Poller<'a, R>
        where
            R: VirtualTcpListener + ?Sized,
        {
            type Output = Result<(Box<dyn VirtualTcpSocket + Sync>, SocketAddr)>;
            fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
                let handler: Box<dyn InterestHandler + Send + Sync> = cx.waker().into();
                if let Err(err) = self.listener.set_handler(handler) {
                    return Poll::Ready(Err(err));
                }
                match self.listener.try_accept() {
                    Ok(ret) => Poll::Ready(Ok(ret)),
                    Err(NetworkError::WouldBlock) => Poll::Pending,
                    Err(err) => Poll::Ready(Err(err)),
                }
            }
        }
        Poller { listener: self }.await
    }
}
pub trait VirtualSocket: VirtualIoSource + fmt::Debug + Send + Sync + 'static {
    fn set_ttl(&mut self, ttl: u32) -> Result<()>;
    fn ttl(&self) -> Result<u32>;
    fn addr_local(&self) -> Result<SocketAddr>;
    fn status(&self) -> Result<SocketStatus>;
    fn set_handler(&mut self, handler: Box<dyn InterestHandler + Send + Sync>) -> Result<()>;
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum SocketStatus {
    Opening,
    Opened,
    Closed,
    Failed,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum StreamSecurity {
    Unencrypted,
    AnyEncyption,
    ClassicEncryption,
    DoubleEncryption,
}
pub trait VirtualConnectedSocket: VirtualSocket + fmt::Debug + Send + Sync + 'static {
    fn set_linger(&mut self, linger: Option<Duration>) -> Result<()>;
    fn linger(&self) -> Result<Option<Duration>>;
    fn try_send(&mut self, data: &[u8]) -> Result<usize>;
    fn try_flush(&mut self) -> Result<()>;
    fn close(&mut self) -> Result<()>;
    fn try_recv(&mut self, buf: &mut [MaybeUninit<u8>]) -> Result<usize>;
}
#[async_trait::async_trait]
pub trait VirtualConnectedSocketExt: VirtualConnectedSocket {
    async fn send(&mut self, data: &[u8]) -> Result<usize>;
    async fn recv(&mut self, buf: &mut [MaybeUninit<u8>]) -> Result<usize>;
    async fn flush(&mut self) -> Result<()>;
}
#[async_trait::async_trait]
impl<R: VirtualConnectedSocket + ?Sized> VirtualConnectedSocketExt for R {
    async fn send(&mut self, data: &[u8]) -> Result<usize> {
        pin_project! {
            struct Poller<'a, 'b, R: ?Sized>
            where
                R: VirtualConnectedSocket,
            {
                socket: &'a mut R,
                data: &'b [u8],
            }
        }
        impl<'a, 'b, R> std::future::Future for Poller<'a, 'b, R>
        where
            R: VirtualConnectedSocket + ?Sized,
        {
            type Output = Result<usize>;
            fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
                let this = self.project();
                let handler: Box<dyn InterestHandler + Send + Sync> = cx.waker().into();
                if let Err(err) = this.socket.set_handler(handler) {
                    return Poll::Ready(Err(err));
                }
                match this.socket.try_send(this.data) {
                    Ok(ret) => Poll::Ready(Ok(ret)),
                    Err(NetworkError::WouldBlock) => Poll::Pending,
                    Err(err) => Poll::Ready(Err(err)),
                }
            }
        }
        Poller { socket: self, data }.await
    }
    async fn recv(&mut self, buf: &mut [MaybeUninit<u8>]) -> Result<usize> {
        pin_project! {
            struct Poller<'a, 'b, R: ?Sized>
            where
                R: VirtualConnectedSocket,
            {
                socket: &'a mut R,
                buf: &'b mut [MaybeUninit<u8>],
            }
        }
        impl<'a, 'b, R> std::future::Future for Poller<'a, 'b, R>
        where
            R: VirtualConnectedSocket + ?Sized,
        {
            type Output = Result<usize>;
            fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
                let this = self.project();
                let handler: Box<dyn InterestHandler + Send + Sync> = cx.waker().into();
                if let Err(err) = this.socket.set_handler(handler) {
                    return Poll::Ready(Err(err));
                }
                match this.socket.try_recv(this.buf) {
                    Ok(ret) => Poll::Ready(Ok(ret)),
                    Err(NetworkError::WouldBlock) => Poll::Pending,
                    Err(err) => Poll::Ready(Err(err)),
                }
            }
        }
        Poller { socket: self, buf }.await
    }
    async fn flush(&mut self) -> Result<()> {
        struct Poller<'a, R>
        where
            R: VirtualConnectedSocket + ?Sized,
        {
            socket: &'a mut R,
        }
        impl<'a, R> std::future::Future for Poller<'a, R>
        where
            R: VirtualConnectedSocket + ?Sized,
        {
            type Output = Result<()>;
            fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
                let handler: Box<dyn InterestHandler + Send + Sync> = cx.waker().into();
                if let Err(err) = self.socket.set_handler(handler) {
                    return Poll::Ready(Err(err));
                }
                match self.socket.try_flush() {
                    Ok(ret) => Poll::Ready(Ok(ret)),
                    Err(NetworkError::WouldBlock) => Poll::Pending,
                    Err(err) => Poll::Ready(Err(err)),
                }
            }
        }
        Poller { socket: self }.await
    }
}
pub trait VirtualConnectionlessSocket: VirtualSocket + fmt::Debug + Send + Sync + 'static {
    fn try_send_to(&mut self, data: &[u8], addr: SocketAddr) -> Result<usize>;
    fn try_recv_from(&mut self, buf: &mut [MaybeUninit<u8>]) -> Result<(usize, SocketAddr)>;
}
#[async_trait::async_trait]
pub trait VirtualConnectionlessSocketExt: VirtualConnectionlessSocket {
    async fn send_to(&mut self, data: &[u8], addr: SocketAddr) -> Result<usize>;
    async fn recv_from(&mut self, buf: &mut [MaybeUninit<u8>]) -> Result<(usize, SocketAddr)>;
}
#[async_trait::async_trait]
impl<R: VirtualConnectionlessSocket + ?Sized> VirtualConnectionlessSocketExt for R {
    async fn send_to(&mut self, data: &[u8], addr: SocketAddr) -> Result<usize> {
        pin_project! {
            struct Poller<'a, 'b, R: ?Sized>
            where
                R: VirtualConnectionlessSocket,
            {
                socket: &'a mut R,
                data: &'b [u8],
                addr: SocketAddr,
            }
        }
        impl<'a, 'b, R> std::future::Future for Poller<'a, 'b, R>
        where
            R: VirtualConnectionlessSocket + ?Sized,
        {
            type Output = Result<usize>;
            fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
                let this = self.project();
                let handler: Box<dyn InterestHandler + Send + Sync> = cx.waker().into();
                if let Err(err) = this.socket.set_handler(handler) {
                    return Poll::Ready(Err(err));
                }
                match this.socket.try_send_to(this.data, *this.addr) {
                    Ok(ret) => Poll::Ready(Ok(ret)),
                    Err(NetworkError::WouldBlock) => Poll::Pending,
                    Err(err) => Poll::Ready(Err(err)),
                }
            }
        }
        Poller {
            socket: self,
            data,
            addr,
        }
        .await
    }
    async fn recv_from(&mut self, buf: &mut [MaybeUninit<u8>]) -> Result<(usize, SocketAddr)> {
        pin_project! {
            struct Poller<'a, 'b, R: ?Sized>
            where
                R: VirtualConnectionlessSocket,
            {
                socket: &'a mut R,
                buf: &'b mut [MaybeUninit<u8>],
            }
        }
        impl<'a, 'b, R> std::future::Future for Poller<'a, 'b, R>
        where
            R: VirtualConnectionlessSocket + ?Sized,
        {
            type Output = Result<(usize, SocketAddr)>;
            fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
                let this = self.project();
                let handler: Box<dyn InterestHandler + Send + Sync> = cx.waker().into();
                if let Err(err) = this.socket.set_handler(handler) {
                    return Poll::Ready(Err(err));
                }
                match this.socket.try_recv_from(this.buf) {
                    Ok(ret) => Poll::Ready(Ok(ret)),
                    Err(NetworkError::WouldBlock) => Poll::Pending,
                    Err(err) => Poll::Ready(Err(err)),
                }
            }
        }
        Poller { socket: self, buf }.await
    }
}
pub trait VirtualIcmpSocket:
    VirtualConnectionlessSocket + fmt::Debug + Send + Sync + 'static
{
}
#[async_trait::async_trait]
pub trait VirtualRawSocket: VirtualSocket + fmt::Debug + Send + Sync + 'static {
    fn try_send(&mut self, data: &[u8]) -> Result<usize>;
    fn try_flush(&mut self) -> Result<()>;
    fn try_recv(&mut self, buf: &mut [MaybeUninit<u8>]) -> Result<usize>;
    fn set_promiscuous(&mut self, promiscuous: bool) -> Result<()>;
    fn promiscuous(&self) -> Result<bool>;
}
pub trait VirtualTcpSocket: VirtualConnectedSocket + fmt::Debug + Send + Sync + 'static {
    fn set_recv_buf_size(&mut self, size: usize) -> Result<()>;
    fn recv_buf_size(&self) -> Result<usize>;
    fn set_send_buf_size(&mut self, size: usize) -> Result<()>;
    fn send_buf_size(&self) -> Result<usize>;
    fn set_nodelay(&mut self, reuse: bool) -> Result<()>;
    fn nodelay(&self) -> Result<bool>;
    fn set_keepalive(&mut self, keepalive: bool) -> Result<()>;
    fn keepalive(&self) -> Result<bool>;
    fn set_dontroute(&mut self, keepalive: bool) -> Result<()>;
    fn dontroute(&self) -> Result<bool>;
    fn addr_peer(&self) -> Result<SocketAddr>;
    fn shutdown(&mut self, how: Shutdown) -> Result<()>;
    fn is_closed(&self) -> bool;
}
#[cfg(feature = "tokio")]
impl<'a> AsyncRead for Box<dyn VirtualTcpSocket + Sync + 'a> {
    fn poll_read(
        self: Pin<&mut Self>,
        cx: &mut Context<'_>,
        buf: &mut tokio::io::ReadBuf<'_>,
    ) -> Poll<std::io::Result<()>> {
        let this = self.get_mut();
        let handler: Box<dyn InterestHandler + Send + Sync> = cx.waker().into();
        if let Err(err) = this.set_handler(handler) {
            return Poll::Ready(Err(net_error_into_io_err(err)));
        }
        let buf_unsafe = unsafe { buf.unfilled_mut() };
        match this.try_recv(buf_unsafe) {
            Ok(ret) => {
                unsafe { buf.assume_init(ret) };
                buf.set_filled(ret);
                Poll::Ready(Ok(()))
            }
            Err(NetworkError::WouldBlock) => Poll::Pending,
            Err(err) => Poll::Ready(Err(net_error_into_io_err(err))),
        }
    }
}
#[cfg(feature = "tokio")]
impl<'a> AsyncWrite for Box<dyn VirtualTcpSocket + Sync + 'a> {
    fn poll_write(
        self: Pin<&mut Self>,
        cx: &mut Context<'_>,
        buf: &[u8],
    ) -> Poll<std::io::Result<usize>> {
        let this = self.get_mut();
        let handler: Box<dyn InterestHandler + Send + Sync> = cx.waker().into();
        if let Err(err) = this.set_handler(handler) {
            return Poll::Ready(Err(net_error_into_io_err(err)));
        }
        match this.try_send(buf) {
            Ok(ret) => Poll::Ready(Ok(ret)),
            Err(NetworkError::WouldBlock) => Poll::Pending,
            Err(err) => Poll::Ready(Err(net_error_into_io_err(err))),
        }
    }
    fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<std::io::Result<()>> {
        let this = self.get_mut();
        let handler: Box<dyn InterestHandler + Send + Sync> = cx.waker().into();
        if let Err(err) = this.set_handler(handler) {
            return Poll::Ready(Err(net_error_into_io_err(err)));
        }
        match this.try_flush() {
            Ok(()) => Poll::Ready(Ok(())),
            Err(NetworkError::WouldBlock) => Poll::Pending,
            Err(err) => Poll::Ready(Err(net_error_into_io_err(err))),
        }
    }
    fn poll_shutdown(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<std::io::Result<()>> {
        Poll::Ready(
            self.shutdown(Shutdown::Write)
                .map_err(net_error_into_io_err),
        )
    }
}
pub trait VirtualUdpSocket:
    VirtualConnectionlessSocket + fmt::Debug + Send + Sync + 'static
{
    fn set_broadcast(&mut self, broadcast: bool) -> Result<()>;
    fn broadcast(&self) -> Result<bool>;
    fn set_multicast_loop_v4(&mut self, val: bool) -> Result<()>;
    fn multicast_loop_v4(&self) -> Result<bool>;
    fn set_multicast_loop_v6(&mut self, val: bool) -> Result<()>;
    fn multicast_loop_v6(&self) -> Result<bool>;
    fn set_multicast_ttl_v4(&mut self, ttl: u32) -> Result<()>;
    fn multicast_ttl_v4(&self) -> Result<u32>;
    fn join_multicast_v4(&mut self, multiaddr: Ipv4Addr, iface: Ipv4Addr) -> Result<()>;
    fn leave_multicast_v4(&mut self, multiaddr: Ipv4Addr, iface: Ipv4Addr) -> Result<()>;
    fn join_multicast_v6(&mut self, multiaddr: Ipv6Addr, iface: u32) -> Result<()>;
    fn leave_multicast_v6(&mut self, multiaddr: Ipv6Addr, iface: u32) -> Result<()>;
    fn addr_peer(&self) -> Result<Option<SocketAddr>>;
}
#[derive(Debug, Default)]
pub struct UnsupportedVirtualNetworking {}
#[async_trait::async_trait]
impl VirtualNetworking for UnsupportedVirtualNetworking {}
#[derive(Error, Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum NetworkError {
    #[error("invalid fd")]
    InvalidFd,
    #[error("file exists")]
    AlreadyExists,
    #[error("lock error")]
    Lock,
    #[error("io error")]
    IOError,
    #[error("address is in use")]
    AddressInUse,
    #[error("address could not be found")]
    AddressNotAvailable,
    #[error("broken pipe (was closed)")]
    BrokenPipe,
    #[error("Insufficient memory")]
    InsufficientMemory,
    #[error("connection aborted")]
    ConnectionAborted,
    #[error("connection refused")]
    ConnectionRefused,
    #[error("connection reset")]
    ConnectionReset,
    #[error("operation interrupted")]
    Interrupted,
    #[error("invalid internal data")]
    InvalidData,
    #[error("invalid input")]
    InvalidInput,
    #[error("connection is not open")]
    NotConnected,
    #[error("can't access device")]
    NoDevice,
    #[error("permission denied")]
    PermissionDenied,
    #[error("time out")]
    TimedOut,
    #[error("unexpected eof")]
    UnexpectedEof,
    #[error("blocking operation. try again")]
    WouldBlock,
    #[error("write returned 0")]
    WriteZero,
    #[error("too many open files")]
    TooManyOpenFiles,
    #[error("unsupported")]
    Unsupported,
    #[error("unknown error found")]
    UnknownError,
}
pub fn io_err_into_net_error(net_error: std::io::Error) -> NetworkError {
    use std::io::ErrorKind;
    match net_error.kind() {
        ErrorKind::BrokenPipe => NetworkError::BrokenPipe,
        ErrorKind::AlreadyExists => NetworkError::AlreadyExists,
        ErrorKind::AddrInUse => NetworkError::AddressInUse,
        ErrorKind::AddrNotAvailable => NetworkError::AddressNotAvailable,
        ErrorKind::ConnectionAborted => NetworkError::ConnectionAborted,
        ErrorKind::ConnectionRefused => NetworkError::ConnectionRefused,
        ErrorKind::ConnectionReset => NetworkError::ConnectionReset,
        ErrorKind::Interrupted => NetworkError::Interrupted,
        ErrorKind::InvalidData => NetworkError::InvalidData,
        ErrorKind::InvalidInput => NetworkError::InvalidInput,
        ErrorKind::NotConnected => NetworkError::NotConnected,
        ErrorKind::PermissionDenied => NetworkError::PermissionDenied,
        ErrorKind::TimedOut => NetworkError::TimedOut,
        ErrorKind::UnexpectedEof => NetworkError::UnexpectedEof,
        ErrorKind::WouldBlock => NetworkError::WouldBlock,
        ErrorKind::WriteZero => NetworkError::WriteZero,
        ErrorKind::Unsupported => NetworkError::Unsupported,
        #[cfg(all(target_family = "unix", feature = "libc"))]
        _ => {
            if let Some(code) = net_error.raw_os_error() {
                match code {
                    libc::EPERM => NetworkError::PermissionDenied,
                    libc::EBADF => NetworkError::InvalidFd,
                    libc::ECHILD => NetworkError::InvalidFd,
                    libc::EMFILE => NetworkError::TooManyOpenFiles,
                    libc::EINTR => NetworkError::Interrupted,
                    libc::EIO => NetworkError::IOError,
                    libc::ENXIO => NetworkError::IOError,
                    libc::EAGAIN => NetworkError::WouldBlock,
                    libc::ENOMEM => NetworkError::InsufficientMemory,
                    libc::EACCES => NetworkError::PermissionDenied,
                    libc::ENODEV => NetworkError::NoDevice,
                    libc::EINVAL => NetworkError::InvalidInput,
                    libc::EPIPE => NetworkError::BrokenPipe,
                    err => {
                        tracing::trace!("unknown os error {}", err);
                        NetworkError::UnknownError
                    }
                }
            } else {
                NetworkError::UnknownError
            }
        }
        #[cfg(not(all(target_family = "unix", feature = "libc")))]
        _ => NetworkError::UnknownError,
    }
}
pub fn net_error_into_io_err(net_error: NetworkError) -> std::io::Error {
    use std::io::ErrorKind;
    match net_error {
        NetworkError::InvalidFd => ErrorKind::BrokenPipe.into(),
        NetworkError::AlreadyExists => ErrorKind::AlreadyExists.into(),
        NetworkError::Lock => ErrorKind::BrokenPipe.into(),
        NetworkError::IOError => ErrorKind::BrokenPipe.into(),
        NetworkError::AddressInUse => ErrorKind::AddrInUse.into(),
        NetworkError::AddressNotAvailable => ErrorKind::AddrNotAvailable.into(),
        NetworkError::BrokenPipe => ErrorKind::BrokenPipe.into(),
        NetworkError::ConnectionAborted => ErrorKind::ConnectionAborted.into(),
        NetworkError::ConnectionRefused => ErrorKind::ConnectionRefused.into(),
        NetworkError::ConnectionReset => ErrorKind::ConnectionReset.into(),
        NetworkError::Interrupted => ErrorKind::Interrupted.into(),
        NetworkError::InvalidData => ErrorKind::InvalidData.into(),
        NetworkError::InvalidInput => ErrorKind::InvalidInput.into(),
        NetworkError::NotConnected => ErrorKind::NotConnected.into(),
        NetworkError::NoDevice => ErrorKind::BrokenPipe.into(),
        NetworkError::PermissionDenied => ErrorKind::PermissionDenied.into(),
        NetworkError::TimedOut => ErrorKind::TimedOut.into(),
        NetworkError::UnexpectedEof => ErrorKind::UnexpectedEof.into(),
        NetworkError::WouldBlock => ErrorKind::WouldBlock.into(),
        NetworkError::WriteZero => ErrorKind::WriteZero.into(),
        NetworkError::Unsupported => ErrorKind::Unsupported.into(),
        NetworkError::UnknownError => ErrorKind::BrokenPipe.into(),
        NetworkError::InsufficientMemory => ErrorKind::OutOfMemory.into(),
        NetworkError::TooManyOpenFiles => {
            #[cfg(all(target_family = "unix", feature = "libc"))]
            {
                std::io::Error::from_raw_os_error(libc::EMFILE)
            }
            #[cfg(not(all(target_family = "unix", feature = "libc")))]
            {
                ErrorKind::Other.into()
            }
        }
    }
}