hyperium / http-body

Asynchronous HTTP body trait
MIT License
129 stars 50 forks source link

Add `Frame::map_data` #89

Closed davidpdrsn closed 1 year ago

davidpdrsn commented 1 year ago

When trying to port tower-http to http-body 1.0 I ran into this

impl<B> Body for CompressionBody<B>
where
    B: Body,
    B::Error: Into<BoxError>,
{
    type Data = Bytes;
    type Error = BoxError;

    fn poll_frame(
        self: Pin<&mut Self>,
        cx: &mut Context<'_>,
    ) -> Poll<Option<Result<Frame<Self::Data>, Self::Error>>> {
        match self.project().inner.project() {
            BodyInnerProj::Identity { inner } => {
                // `inner` is a body that we need to poll and copy the
                // bytes to a `Bytes`

                let frame = match ready!(inner.poll_frame(cx)) {
                    Some(Ok(frame)) => frame,
                    Some(Err(err)) => return Poll::Ready(Some(Err(err.into()))),
                    None => return Poll::Ready(None),
                };

                let frame = match frame.into_data() {
                    Ok(buf) => {
                        let bytes = buf.copy_to_bytes(buf.remaining());
                        return Poll::Ready(Some(Ok(Frame::data(bytes))));
                    }
                    Err(frame) => frame,
                };

                let frame = match frame.into_trailers() {
                    Ok(trailers) => {
                        return Poll::Ready(Some(Ok(Frame::trailers(trailers))));
                    }
                    Err(frame) => frame,
                };

                // what do we return here?
                // can't return `frame` because that is `Frame<B::Data>`, even though we did map the data
                Poll::Ready(Some(Ok(frame)))
            }
            // more variants here...
        }
    }
}

I'm thinking if we map Frame::map_data I could use that instead of Frame::into_data to actually change the data type for the trailer kind as well.