relax unpin bound on messagebody impl for anybody

This commit is contained in:
Rob Ede 2021-11-16 20:33:07 +00:00
parent b3e187fe19
commit 1d3684f6b7
No known key found for this signature in database
GPG Key ID: 97C636207D3EF933
1 changed files with 37 additions and 14 deletions

View File

@ -8,6 +8,7 @@ use std::{
use bytes::{Bytes, BytesMut}; use bytes::{Bytes, BytesMut};
use futures_core::Stream; use futures_core::Stream;
use pin_project::pin_project;
use crate::error::Error; use crate::error::Error;
@ -16,16 +17,17 @@ use super::{BodySize, BodyStream, MessageBody, MessageBodyMapErr, SizedStream};
pub type Body = AnyBody; pub type Body = AnyBody;
/// Represents various types of HTTP message body. /// Represents various types of HTTP message body.
#[pin_project(project = AnyBodyProj)]
#[derive(Clone)] #[derive(Clone)]
pub enum AnyBody<B = BoxBody> { pub enum AnyBody<B = BoxBody> {
/// Empty response. `Content-Length` header is not set. /// Empty response. `Content-Length` header is not set.
None, None,
/// Specific response body. /// Complete, in-memory response body.
Bytes(Bytes), Bytes(Bytes),
/// Generic / Other message body. /// Generic / Other message body.
Body(B), Body(#[pin] B),
} }
impl AnyBody { impl AnyBody {
@ -78,7 +80,7 @@ where
impl<B> MessageBody for AnyBody<B> impl<B> MessageBody for AnyBody<B>
where where
B: MessageBody + Unpin, B: MessageBody,
B::Error: Into<Box<dyn StdError>> + 'static, B::Error: Into<Box<dyn StdError>> + 'static,
{ {
type Error = Error; type Error = Error;
@ -95,9 +97,9 @@ where
self: Pin<&mut Self>, self: Pin<&mut Self>,
cx: &mut Context<'_>, cx: &mut Context<'_>,
) -> Poll<Option<Result<Bytes, Self::Error>>> { ) -> Poll<Option<Result<Bytes, Self::Error>>> {
match self.get_mut() { match self.project() {
AnyBody::None => Poll::Ready(None), AnyBodyProj::None => Poll::Ready(None),
AnyBody::Bytes(ref mut bin) => { AnyBodyProj::Bytes(bin) => {
let len = bin.len(); let len = bin.len();
if len == 0 { if len == 0 {
Poll::Ready(None) Poll::Ready(None)
@ -106,7 +108,7 @@ where
} }
} }
AnyBody::Body(body) => Pin::new(body) AnyBodyProj::Body(body) => body
.poll_next(cx) .poll_next(cx)
.map_err(|err| Error::new_body().with_cause(err)), .map_err(|err| Error::new_body().with_cause(err)),
} }
@ -257,19 +259,40 @@ impl MessageBody for BoxBody {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::marker::PhantomPinned;
use static_assertions::{assert_impl_all, assert_not_impl_all}; use static_assertions::{assert_impl_all, assert_not_impl_all};
use super::*; use super::*;
use crate::body::to_bytes; use crate::body::to_bytes;
assert_impl_all!(AnyBody<()>: MessageBody, fmt::Debug, Send, Sync); struct PinType(PhantomPinned);
assert_impl_all!(AnyBody<AnyBody<()>>: MessageBody, fmt::Debug, Send, Sync);
assert_impl_all!(AnyBody<Bytes>: MessageBody, fmt::Debug, Send, Sync);
assert_impl_all!(AnyBody: MessageBody, fmt::Debug);
assert_impl_all!(BoxBody: MessageBody, fmt::Debug);
assert_not_impl_all!(AnyBody: Send, Sync); impl MessageBody for PinType {
assert_not_impl_all!(BoxBody: Send, Sync); type Error = crate::Error;
fn size(&self) -> BodySize {
unimplemented!()
}
fn poll_next(
self: Pin<&mut Self>,
_cx: &mut Context<'_>,
) -> Poll<Option<Result<Bytes, Self::Error>>> {
unimplemented!()
}
}
assert_impl_all!(AnyBody<()>: MessageBody, fmt::Debug, Send, Sync, Unpin);
assert_impl_all!(AnyBody<AnyBody<()>>: MessageBody, fmt::Debug, Send, Sync, Unpin);
assert_impl_all!(AnyBody<Bytes>: MessageBody, fmt::Debug, Send, Sync, Unpin);
assert_impl_all!(AnyBody: MessageBody, fmt::Debug, Unpin);
assert_impl_all!(BoxBody: MessageBody, fmt::Debug, Unpin);
assert_impl_all!(AnyBody<PinType>: MessageBody);
assert_not_impl_all!(AnyBody: Send, Sync, Unpin);
assert_not_impl_all!(BoxBody: Send, Sync, Unpin);
assert_not_impl_all!(AnyBody<PinType>: Send, Sync, Unpin);
#[actix_rt::test] #[actix_rt::test]
async fn nested_boxed_body() { async fn nested_boxed_body() {