Skip to content

Commit

Permalink
MessageBody::boxed (actix#2520)
Browse files Browse the repository at this point in the history
Co-authored-by: Rob Ede <[email protected]>
  • Loading branch information
aliemjay and robjtede authored Dec 17, 2021
1 parent 44b7302 commit 3c0d059
Show file tree
Hide file tree
Showing 8 changed files with 40 additions and 10 deletions.
2 changes: 2 additions & 0 deletions actix-http/CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
* `Request::take_req_data()`. [#2487]
* `impl Clone` for `RequestHead`. [#2487]
* New methods on `MessageBody` trait, `is_complete_body` and `take_complete_body`, both with default implementations, for optimisations on body types that are done in exactly one poll/chunk. [#2497]
* New `boxed` method on `MessageBody` trait for wrapping body type. [#2520]

### Changed
* Rename `body::BoxBody::{from_body => new}`. [#2468]
Expand Down Expand Up @@ -56,6 +57,7 @@
[#2488]: https://github.com/actix/actix-web/pull/2488
[#2491]: https://github.com/actix/actix-web/pull/2491
[#2497]: https://github.com/actix/actix-web/pull/2497
[#2520]: https://github.com/actix/actix-web/pull/2520


## 3.0.0-beta.14 - 2021-11-30
Expand Down
16 changes: 15 additions & 1 deletion actix-http/src/body/boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@ use crate::Error;
pub struct BoxBody(Pin<Box<dyn MessageBody<Error = Box<dyn StdError>>>>);

impl BoxBody {
/// Boxes a `MessageBody` and any errors it generates.
/// Same as `MessageBody::boxed`.
///
/// If the body type to wrap is unknown or generic it is better to use [`MessageBody::boxed`] to
/// avoid double boxing.
#[inline]
pub fn new<B>(body: B) -> Self
where
B: MessageBody + 'static,
Expand All @@ -24,6 +28,7 @@ impl BoxBody {
}

/// Returns a mutable pinned reference to the inner message body type.
#[inline]
pub fn as_pin_mut(&mut self) -> Pin<&mut (dyn MessageBody<Error = Box<dyn StdError>>)> {
self.0.as_mut()
}
Expand All @@ -38,10 +43,12 @@ impl fmt::Debug for BoxBody {
impl MessageBody for BoxBody {
type Error = Error;

#[inline]
fn size(&self) -> BodySize {
self.0.size()
}

#[inline]
fn poll_next(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
Expand All @@ -52,13 +59,20 @@ impl MessageBody for BoxBody {
.map_err(|err| Error::new_body().with_cause(err))
}

#[inline]
fn is_complete_body(&self) -> bool {
self.0.is_complete_body()
}

#[inline]
fn take_complete_body(&mut self) -> Bytes {
self.0.take_complete_body()
}

#[inline]
fn boxed(self) -> BoxBody {
self
}
}

#[cfg(test)]
Expand Down
8 changes: 8 additions & 0 deletions actix-http/src/body/either.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,14 @@ where
EitherBody::Right { body } => body.take_complete_body(),
}
}

#[inline]
fn boxed(self) -> BoxBody {
match self {
EitherBody::Left { body } => body.boxed(),
EitherBody::Right { body } => body.boxed(),
}
}
}

#[cfg(test)]
Expand Down
13 changes: 11 additions & 2 deletions actix-http/src/body/message_body.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use bytes::{Bytes, BytesMut};
use futures_core::ready;
use pin_project_lite::pin_project;

use super::BodySize;
use super::{BodySize, BoxBody};

/// An interface types that can converted to bytes and used as response bodies.
// TODO: examples
Expand Down Expand Up @@ -77,6 +77,15 @@ pub trait MessageBody {
std::any::type_name::<Self>()
);
}

/// Converts this body into `BoxBody`.
#[inline]
fn boxed(self) -> BoxBody
where
Self: Sized + 'static,
{
BoxBody::new(self)
}
}

mod foreign_impls {
Expand Down Expand Up @@ -656,7 +665,7 @@ mod tests {
assert_eq!(body.take_complete_body(), b"test".as_ref());

// subsequent poll_next returns None
let waker = futures_util::task::noop_waker();
let waker = futures_task::noop_waker();
let mut cx = Context::from_waker(&waker);
assert!(Pin::new(&mut body).poll_next(&mut cx).map_err(drop) == Poll::Ready(None));
}
Expand Down
2 changes: 1 addition & 1 deletion actix-http/src/response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ impl<B> Response<B> {
where
B: MessageBody + 'static,
{
self.map_body(|_, body| BoxBody::new(body))
self.map_body(|_, body| body.boxed())
}

/// Returns body, consuming this response.
Expand Down
4 changes: 1 addition & 3 deletions awc/src/any_body.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,7 @@ impl AnyBody {
where
B: MessageBody + 'static,
{
Self::Body {
body: BoxBody::new(body),
}
Self::Body { body: body.boxed() }
}

/// Constructs new `AnyBody` instance from a slice of bytes by copying it.
Expand Down
3 changes: 1 addition & 2 deletions src/response/response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -244,8 +244,7 @@ impl<B> HttpResponse<B> {
where
B: MessageBody + 'static,
{
// TODO: avoid double boxing with down-casting, if it improves perf
self.map_body(|_, body| BoxBody::new(body))
self.map_body(|_, body| body.boxed())
}

/// Extract response body
Expand Down
2 changes: 1 addition & 1 deletion src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,7 @@ impl<B> ServiceResponse<B> {
where
B: MessageBody + 'static,
{
self.map_body(|_, body| BoxBody::new(body))
self.map_body(|_, body| body.boxed())
}
}

Expand Down

0 comments on commit 3c0d059

Please sign in to comment.