safe_http_async 0.1.0-beta.4

Simple and safe asynchronous HTTP types.
Documentation
use super::Body;
use futures::future::poll_fn;
use shared_bytes::{SharedBytes, SharedStr};
use std::{
    convert::Infallible,
    fmt::Debug,
    io::{self, Cursor},
    iter,
    pin::Pin,
    sync::Arc,
};

pub(crate) trait DebugBody: Body + Debug + Unpin + Send + Sync + 'static {}

impl<R> DebugBody for R where R: Body + Debug + Unpin + Send + Sync + 'static {}

#[derive(Debug)]
pub struct BodyBox {
    inner: Pin<Box<dyn DebugBody>>,
}

impl BodyBox {
    pub fn new<B>(body: B) -> Self
    where
        B: Body + Debug + Unpin + Send + Sync + 'static,
    {
        Self {
            inner: Box::pin(body),
        }
    }

    pub fn empty() -> Self {
        Self::new(())
    }

    pub async fn read_chunk(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        poll_fn(|cx| Body::poll_chunk(Pin::new(&mut *self.inner), cx, buf)).await
    }

    pub async fn chunk_size_hint(&mut self) -> io::Result<(usize, Option<usize>)> {
        poll_fn(|cx| Body::poll_chunk_size_hint(Pin::new(&mut *self.inner), cx)).await
    }

    pub fn size_hint(&self) -> (usize, Option<usize>) {
        Body::size_hint(&*self.inner)
    }

    pub async fn read_chunk_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
        buf.reserve(self.chunk_size_hint().await?.0);
        let start_length = buf.len();
        let mut filled_bytes = start_length;
        loop {
            if buf.capacity() == filled_bytes {
                buf.reserve(32)
            }
            buf.extend(iter::repeat(0).take(buf.capacity() - buf.len()));
            match self.read_chunk(&mut buf[filled_bytes..]).await? {
                0 => {
                    buf.truncate(filled_bytes);
                    return Ok(filled_bytes - start_length);
                }
                x => filled_bytes += x,
            }
        }
    }

    pub async fn read_chunk_vec(&mut self) -> io::Result<Vec<u8>> {
        let mut buf = Vec::new();
        self.read_chunk_to_end(&mut buf).await?;
        Ok(buf)
    }

    pub fn from_bytes(bytes: Vec<u8>) -> Self {
        Self::new(Cursor::new(bytes))
    }

    pub async fn read_vec(&mut self) -> io::Result<Vec<u8>> {
        let mut buf = Vec::with_capacity(self.size_hint().0);
        let read_bytes = self.read_chunk_to_end(&mut buf).await?;
        let mut finished_chunk = read_bytes == 0;
        loop {
            let read_bytes = self.read_chunk_to_end(&mut buf).await?;
            let read_nothing = read_bytes == 0;
            if read_nothing && finished_chunk {
                return Ok(buf);
            }
            finished_chunk = read_nothing;
        }
    }

    pub async fn read_into_vec(mut self) -> io::Result<Vec<u8>> {
        self.read_vec().await
    }

    pub fn from_string(string: String) -> Self {
        Self::new(Cursor::new(string))
    }

    pub async fn read_string(&mut self) -> io::Result<String> {
        let vec = self.read_vec().await?;
        String::from_utf8(vec).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
    }

    pub async fn read_into_string(mut self) -> io::Result<String> {
        self.read_string().await
    }
}

impl Default for BodyBox {
    fn default() -> Self {
        Self::empty()
    }
}

impl From<Vec<u8>> for BodyBox {
    fn from(x: Vec<u8>) -> Self {
        Self::from_bytes(x)
    }
}

impl From<String> for BodyBox {
    fn from(x: String) -> Self {
        Self::from_string(x)
    }
}

impl From<&'static [u8]> for BodyBox {
    fn from(x: &'static [u8]) -> Self {
        Self::new(Cursor::new(x))
    }
}

impl From<&'static str> for BodyBox {
    fn from(x: &'static str) -> Self {
        Self::new(Cursor::new(x))
    }
}

impl From<Arc<String>> for BodyBox {
    fn from(x: Arc<String>) -> Self {
        Self::new(Cursor::new(ArcAsRef(x)))
    }
}

impl From<Arc<str>> for BodyBox {
    fn from(x: Arc<str>) -> Self {
        Self::new(Cursor::new(ArcAsRef(x)))
    }
}

impl From<SharedStr> for BodyBox {
    fn from(x: SharedStr) -> Self {
        Self::new(Cursor::new(x))
    }
}

impl From<Arc<Vec<u8>>> for BodyBox {
    fn from(x: Arc<Vec<u8>>) -> Self {
        Self::new(Cursor::new(ArcAsRef(x)))
    }
}

impl From<Arc<[u8]>> for BodyBox {
    fn from(x: Arc<[u8]>) -> Self {
        Self::new(Cursor::new(ArcAsRef(x)))
    }
}

impl From<SharedBytes> for BodyBox {
    fn from(x: SharedBytes) -> Self {
        Self::new(Cursor::new(x))
    }
}

impl From<Infallible> for BodyBox {
    fn from(_: Infallible) -> Self {
        Self::empty()
    }
}

impl<T, E> From<Result<T, E>> for BodyBox
where
    T: Into<Self>,
    E: Into<Self>,
{
    fn from(x: Result<T, E>) -> Self {
        match x {
            Ok(t) => t.into(),
            Err(e) => e.into(),
        }
    }
}

impl<T> From<Option<T>> for BodyBox
where
    T: Into<Self>,
{
    fn from(x: Option<T>) -> Self {
        match x {
            Some(t) => t.into(),
            None => Self::empty(),
        }
    }
}

impl From<()> for BodyBox {
    fn from(_: ()) -> Self {
        Self::empty()
    }
}

#[derive(Debug)]
struct ArcAsRef<T: ?Sized>(Arc<T>);

impl<T> AsRef<[u8]> for ArcAsRef<T>
where
    T: AsRef<[u8]> + ?Sized,
{
    fn as_ref(&self) -> &[u8] {
        self.0.as_ref().as_ref()
    }
}