wasi-hyperium 0.3.0

Hyperium for WASI Preview2 HTTP
Documentation
use std::task::{Context, Poll};

use bytes::Bytes;
use http_body1::Frame;

use crate::{
    incoming::{IncomingHttpBody, IncomingState},
    poll::PollableRegistry,
    wasi::{IncomingRequest, IncomingResponse},
    Error,
};

pub fn incoming_request<Registry>(
    request: IncomingRequest<Registry>,
) -> Result<http1::Request<IncomingHttpBody<Registry>>, Error>
where
    Registry: PollableRegistry,
{
    let uri = {
        let mut builder = http1::Uri::builder();
        if let Some(scheme) = request.scheme() {
            builder = builder.scheme(scheme);
        }
        if let Some(auth) = request.authority() {
            builder = builder.authority(auth)
        }
        if let Some(p_and_q) = request.path_with_query() {
            builder = builder.path_and_query(p_and_q);
        }
        builder.build()?
    };
    let mut builder = http1::Request::builder().method(request.method()).uri(uri);
    for (name, val) in request.headers() {
        builder = builder.header(name, val);
    }
    Ok(builder.body(request.into_body().into())?)
}

pub fn incoming_response<Registry>(
    response: IncomingResponse<Registry>,
) -> Result<http1::Response<IncomingHttpBody<Registry>>, Error>
where
    Registry: PollableRegistry,
{
    let mut builder = http1::Response::builder().status(response.status());
    for (name, val) in response.headers() {
        builder = builder.header(name, val);
    }
    Ok(builder.body(response.into_body().into())?)
}

impl<Registry> http_body1::Body for IncomingHttpBody<Registry>
where
    Registry: PollableRegistry,
{
    type Data = Bytes;
    type Error = Error;

    fn poll_frame(
        mut self: std::pin::Pin<&mut Self>,
        cx: &mut std::task::Context<'_>,
    ) -> Poll<Option<Result<Frame<Self::Data>, Self::Error>>> {
        match &self.state {
            IncomingState::Empty => Poll::Ready(None),
            IncomingState::Body { .. } => match self.poll_incoming_body(cx)? {
                Poll::Ready(Some(frame)) => Poll::Ready(Some(Ok(Frame::data(frame)))),
                Poll::Ready(None) => self.poll_hyperium1_trailers(cx),
                Poll::Pending => Poll::Pending,
            },
            IncomingState::Trailers(_) => self.poll_hyperium1_trailers(cx),
        }
    }
}

impl<Registry> IncomingHttpBody<Registry>
where
    Registry: PollableRegistry,
{
    #[allow(clippy::type_complexity)]
    fn poll_hyperium1_trailers(
        &mut self,
        cx: &mut Context,
    ) -> Poll<Option<Result<Frame<Bytes>, Error>>> {
        match self.poll_incoming_trailers(cx)? {
            Poll::Ready(Some(trailers)) => {
                Poll::Ready(Some(Ok(Frame::trailers(trailers.try_into()?))))
            }
            Poll::Ready(None) => Poll::Ready(None),
            Poll::Pending => Poll::Pending,
        }
    }
}