rd-std 0.1.0

std for rabbit-digger
Documentation
use std::{
    io::{self, ErrorKind},
    net::SocketAddr,
};

use rd_interface::{
    async_trait, impl_async_read_write,
    registry::{EmptyConfig, NetFactory},
    Address, INet, IntoDyn, Result, TcpListener, TcpStream, UdpSocket,
};
use tokio::net;

pub struct LocalNet;
pub struct CompatTcp(pub(crate) net::TcpStream);
pub struct Listener(net::TcpListener);
pub struct Udp(net::UdpSocket);

impl LocalNet {
    fn new() -> LocalNet {
        LocalNet
    }
}
async fn lookup_host(domain: String, port: u16) -> io::Result<SocketAddr> {
    use tokio::net::lookup_host;

    let domain = (domain.as_ref(), port);
    lookup_host(domain)
        .await?
        .next()
        .ok_or(ErrorKind::AddrNotAvailable.into())
}

impl_async_read_write!(CompatTcp, 0);

#[async_trait]
impl rd_interface::ITcpStream for CompatTcp {
    async fn peer_addr(&self) -> Result<SocketAddr> {
        self.0.peer_addr().map_err(Into::into)
    }
    async fn local_addr(&self) -> Result<SocketAddr> {
        self.0.local_addr().map_err(Into::into)
    }
}
impl CompatTcp {
    fn new(t: net::TcpStream) -> CompatTcp {
        CompatTcp(t)
    }
}

#[async_trait]
impl rd_interface::ITcpListener for Listener {
    async fn accept(&self) -> Result<(TcpStream, SocketAddr)> {
        let (socket, addr) = self.0.accept().await?;
        Ok((CompatTcp::new(socket).into_dyn(), addr))
    }

    async fn local_addr(&self) -> Result<SocketAddr> {
        self.0.local_addr().map_err(Into::into)
    }
}

#[async_trait]
impl rd_interface::IUdpSocket for Udp {
    async fn recv_from(&self, buf: &mut [u8]) -> Result<(usize, SocketAddr)> {
        self.0.recv_from(buf).await.map_err(Into::into)
    }

    async fn send_to(&self, buf: &[u8], addr: Address) -> Result<usize> {
        let addr = addr.resolve(lookup_host).await?;
        self.0.send_to(buf, addr).await.map_err(Into::into)
    }

    async fn local_addr(&self) -> Result<SocketAddr> {
        self.0.local_addr().map_err(Into::into)
    }
}

#[async_trait]
impl INet for LocalNet {
    async fn tcp_connect(
        &self,
        _ctx: &mut rd_interface::Context,
        addr: Address,
    ) -> Result<TcpStream> {
        #[cfg(feature = "local_log")]
        log::trace!("local::tcp_connect {:?} {:?}", _ctx, addr);
        let addr = addr.resolve(lookup_host).await?;
        Ok(CompatTcp::new(net::TcpStream::connect(addr).await?).into_dyn())
    }

    async fn tcp_bind(
        &self,
        _ctx: &mut rd_interface::Context,
        addr: Address,
    ) -> Result<TcpListener> {
        #[cfg(feature = "local_log")]
        log::trace!("local::tcp_bind {:?} {:?}", _ctx, addr);
        let addr = addr.resolve(lookup_host).await?;
        Ok(Listener(net::TcpListener::bind(addr).await?).into_dyn())
    }

    async fn udp_bind(&self, _ctx: &mut rd_interface::Context, addr: Address) -> Result<UdpSocket> {
        #[cfg(feature = "local_log")]
        log::trace!("local::udp_bind {:?} {:?}", _ctx, addr);
        let addr = addr.resolve(lookup_host).await?;
        Ok(Udp(net::UdpSocket::bind(addr).await?).into_dyn())
    }
}

impl NetFactory for LocalNet {
    const NAME: &'static str = "local";
    type Config = EmptyConfig;
    type Net = Self;

    fn new(_nets: Vec<rd_interface::Net>, _config: Self::Config) -> Result<Self> {
        Ok(LocalNet::new())
    }
}