mirror of
https://github.com/fafhrd91/actix-web
synced 2025-02-24 12:53:21 +01:00
90 lines
2.0 KiB
Rust
90 lines
2.0 KiB
Rust
use std::{
|
|
mem,
|
|
pin::Pin,
|
|
task::{Context, Poll},
|
|
};
|
|
|
|
use bytes::Bytes;
|
|
use futures_core::{ready, Stream};
|
|
use pin_project::pin_project;
|
|
|
|
use crate::error::Error;
|
|
|
|
use super::{Body, BodySize, MessageBody};
|
|
|
|
#[pin_project(project = ResponseBodyProj)]
|
|
pub enum ResponseBody<B> {
|
|
Body(#[pin] B),
|
|
Other(Body),
|
|
}
|
|
|
|
impl ResponseBody<Body> {
|
|
pub fn into_body<B>(self) -> ResponseBody<B> {
|
|
match self {
|
|
ResponseBody::Body(b) => ResponseBody::Other(b),
|
|
ResponseBody::Other(b) => ResponseBody::Other(b),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<B> ResponseBody<B> {
|
|
pub fn take_body(&mut self) -> ResponseBody<B> {
|
|
mem::replace(self, ResponseBody::Other(Body::None))
|
|
}
|
|
}
|
|
|
|
impl<B: MessageBody> ResponseBody<B> {
|
|
pub fn as_ref(&self) -> Option<&B> {
|
|
if let ResponseBody::Body(ref b) = self {
|
|
Some(b)
|
|
} else {
|
|
None
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<B> MessageBody for ResponseBody<B>
|
|
where
|
|
B: MessageBody,
|
|
B::Error: Into<Error>,
|
|
{
|
|
type Error = Error;
|
|
|
|
fn size(&self) -> BodySize {
|
|
match self {
|
|
ResponseBody::Body(ref body) => body.size(),
|
|
ResponseBody::Other(ref body) => body.size(),
|
|
}
|
|
}
|
|
|
|
fn poll_next(
|
|
self: Pin<&mut Self>,
|
|
cx: &mut Context<'_>,
|
|
) -> Poll<Option<Result<Bytes, Self::Error>>> {
|
|
Stream::poll_next(self, cx)
|
|
}
|
|
}
|
|
|
|
impl<B> Stream for ResponseBody<B>
|
|
where
|
|
B: MessageBody,
|
|
B::Error: Into<Error>,
|
|
{
|
|
type Item = Result<Bytes, Error>;
|
|
|
|
fn poll_next(
|
|
self: Pin<&mut Self>,
|
|
cx: &mut Context<'_>,
|
|
) -> Poll<Option<Self::Item>> {
|
|
match self.project() {
|
|
// TODO: MSRV 1.51: poll_map_err
|
|
ResponseBodyProj::Body(body) => match ready!(body.poll_next(cx)) {
|
|
Some(Err(err)) => Poll::Ready(Some(Err(err.into()))),
|
|
Some(Ok(val)) => Poll::Ready(Some(Ok(val))),
|
|
None => Poll::Ready(None),
|
|
},
|
|
ResponseBodyProj::Other(body) => Pin::new(body).poll_next(cx),
|
|
}
|
|
}
|
|
}
|