net 0.0.2

core types for async-net
#![feature(trait_alias)]

mod web;
mod addr;

use tokio::{
    io::{AsyncRead, AsyncWrite, ReadBuf, Result as IoResult},
};
pub use crate::addr::Addr;
pub use crate::web::addr::{LocalAddr, RemoteAddr};
use futures_util::{future::BoxFuture, Future, FutureExt, TryFutureExt};
use http::uri::Scheme;

use std::{
    convert::Infallible,
    io::Error,
    pin::Pin,
    task::{Context, Poll},
};

pub trait Conn = AsyncRead + AsyncWrite + Send + Unpin + 'static;

/// Represents a acceptor type.
pub trait Acceptor: Send {
    /// IO stream type.
    type Io: Conn;

    /// Returns the local address that this listener is bound to.
    fn local_addr(&self) -> Vec<LocalAddr>;

    /// Accepts a new incoming connection from this listener.
    ///
    /// This function will yield once a new TCP connection is established. When
    /// established, the corresponding IO stream and the remote peer’s
    /// address will be returned.
    fn accept(
        &mut self,
    ) -> impl Future<Output = IoResult<(Self::Io, LocalAddr, RemoteAddr, Scheme)>> + Send;
}

/// An IO type for BoxAcceptor.
pub struct BoxIo {
    reader: Box<dyn AsyncRead + Send + Unpin + 'static>,
    writer: Box<dyn AsyncWrite + Send + Unpin + 'static>,
}

impl BoxIo {
    pub fn new(io: impl Conn) -> Self {
        let (reader, writer) = tokio::io::split(io);
        Self {
            reader: Box::new(reader),
            writer: Box::new(writer),
        }
    }
}

impl AsyncRead for BoxIo {
    fn poll_read(
        mut self: Pin<&mut Self>,
        cx: &mut Context<'_>,
        buf: &mut ReadBuf<'_>,
    ) -> Poll<IoResult<()>> {
        let this = &mut *self;
        Pin::new(&mut this.reader).poll_read(cx, buf)
    }
}

impl AsyncWrite for BoxIo {
    fn poll_write(
        mut self: Pin<&mut Self>,
        cx: &mut Context<'_>,
        buf: &[u8],
    ) -> Poll<Result<usize, Error>> {
        let this = &mut *self;
        Pin::new(&mut this.writer).poll_write(cx, buf)
    }

    fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Error>> {
        let this = &mut *self;
        Pin::new(&mut this.writer).poll_flush(cx)
    }

    fn poll_shutdown(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Error>> {
        let this = &mut *self;
        Pin::new(&mut this.writer).poll_shutdown(cx)
    }
}

impl Acceptor for Infallible {
    type Io = BoxIo;

    fn local_addr(&self) -> Vec<LocalAddr> {
        vec![]
    }

    async fn accept(&mut self) -> IoResult<(Self::Io, LocalAddr, RemoteAddr, Scheme)> {
        unreachable!()
    }
}

impl<T: Acceptor + ?Sized> Acceptor for Box<T> {
    type Io = T::Io;

    fn local_addr(&self) -> Vec<LocalAddr> {
        self.as_ref().local_addr()
    }

    async fn accept(&mut self) -> IoResult<(Self::Io, LocalAddr, RemoteAddr, Scheme)> {
        self.as_mut().accept().await
    }
}

pub fn add(left: usize, right: usize) -> usize {
    left + right
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn it_works() {
        let result = add(2, 2);
        assert_eq!(result, 4);
    }
}