safe_http_async 0.1.0-beta.4

Simple and safe asynchronous HTTP types.
Documentation
use std::{
    io::{self, Cursor, Read},
    pin::Pin,
    task::{Context, Poll},
};

pub trait Body {
    fn poll_chunk(
        self: Pin<&mut Self>,
        cx: &mut Context<'_>,
        buf: &mut [u8],
    ) -> Poll<io::Result<usize>>;

    fn poll_chunk_size_hint(
        self: Pin<&mut Self>,
        cx: &mut Context<'_>,
    ) -> Poll<io::Result<(usize, Option<usize>)>>;

    fn size_hint(&self) -> (usize, Option<usize>);
}

impl Body for () {
    fn poll_chunk(
        self: Pin<&mut Self>,
        _cx: &mut Context<'_>,
        _buf: &mut [u8],
    ) -> Poll<io::Result<usize>> {
        Poll::Ready(Ok(0))
    }

    fn poll_chunk_size_hint(
        self: Pin<&mut Self>,
        _cx: &mut Context<'_>,
    ) -> Poll<io::Result<(usize, Option<usize>)>> {
        Poll::Ready(Ok(self.size_hint()))
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        exact_size_hint(0)
    }
}

impl<T> Body for Cursor<T>
where
    T: AsRef<[u8]> + Unpin,
{
    fn poll_chunk(
        mut self: Pin<&mut Self>,
        _cx: &mut Context<'_>,
        buf: &mut [u8],
    ) -> Poll<io::Result<usize>> {
        Poll::Ready(self.as_mut().read(buf))
    }

    fn poll_chunk_size_hint(
        self: Pin<&mut Self>,
        _cx: &mut Context<'_>,
    ) -> Poll<io::Result<(usize, Option<usize>)>> {
        Poll::Ready(Ok(self.size_hint()))
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let position: usize = self.position().try_into().unwrap();
        let length = self.get_ref().as_ref().len().saturating_sub(position);
        exact_size_hint(length)
    }
}

fn exact_size_hint(size: usize) -> (usize, Option<usize>) {
    (size, Some(size))
}