use std::{ mem, pin::Pin, task::{Context, Poll}, }; use bytes::Bytes; use futures_core::Stream; use crate::error::PayloadError; /// A boxed payload stream. pub type BoxedPayloadStream = Pin>>>; #[deprecated(since = "4.0.0", note = "Renamed to `BoxedPayloadStream`.")] pub type PayloadStream = BoxedPayloadStream; pin_project_lite::pin_project! { /// A streaming payload. #[project = PayloadProj] pub enum Payload { None, H1 { payload: crate::h1::Payload }, H2 { payload: crate::h2::Payload }, Stream { #[pin] payload: S }, } } impl From for Payload { fn from(payload: crate::h1::Payload) -> Self { Payload::H1 { payload } } } impl From for Payload { fn from(payload: crate::h2::Payload) -> Self { Payload::H2 { payload } } } impl From for Payload { fn from(stream: h2::RecvStream) -> Self { Payload::H2 { payload: crate::h2::Payload::new(stream), } } } impl From for Payload { fn from(payload: BoxedPayloadStream) -> Self { Payload::Stream { payload } } } impl Payload { /// Takes current payload and replaces it with `None` value pub fn take(&mut self) -> Payload { mem::replace(self, Payload::None) } } impl Stream for Payload where S: Stream>, { type Item = Result; #[inline] fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { match self.project() { PayloadProj::None => Poll::Ready(None), PayloadProj::H1 { payload } => Pin::new(payload).poll_next(cx), PayloadProj::H2 { payload } => Pin::new(payload).poll_next(cx), PayloadProj::Stream { payload } => payload.poll_next(cx), } } } #[cfg(test)] mod tests { use std::panic::{RefUnwindSafe, UnwindSafe}; use static_assertions::{assert_impl_all, assert_not_impl_any}; use super::*; assert_impl_all!(Payload: Unpin); assert_not_impl_any!(Payload: Send, Sync, UnwindSafe, RefUnwindSafe); }