wip: body typeid full data
This commit is contained in:
@@ -285,6 +285,14 @@ impl Body {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn take_full_data(&mut self) -> Option<Chunk> {
|
||||
if let Kind::Once(ref mut chunk) = self.kind {
|
||||
chunk.take()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Body {
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
//! and returned by hyper as a "receive stream" (so, for server requests and
|
||||
//! client responses). It is also a decent default implementation if you don't
|
||||
//! have very custom needs of your send streams.
|
||||
|
||||
pub use self::body::{Body, Sender};
|
||||
pub use self::chunk::Chunk;
|
||||
pub use self::payload::Payload;
|
||||
@@ -22,6 +23,27 @@ mod body;
|
||||
mod chunk;
|
||||
mod payload;
|
||||
|
||||
/// An optimization to try to take a full body if immediately available.
|
||||
///
|
||||
/// This is currently limited to *only* `hyper::Body`s.
|
||||
pub(crate) fn take_full_data<T: Payload + 'static>(body: &mut T) -> Option<T::Data> {
|
||||
use std::any::{Any, TypeId};
|
||||
|
||||
// This static type check can be optimized at compile-time.
|
||||
if TypeId::of::<T>() == TypeId::of::<Body>() {
|
||||
let mut full = (body as &mut dyn Any)
|
||||
.downcast_mut::<Body>()
|
||||
.expect("must be Body")
|
||||
.take_full_data();
|
||||
(&mut full as &mut dyn Any)
|
||||
.downcast_mut::<Option<T::Data>>()
|
||||
.expect("must be T::Data")
|
||||
.take()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
// The full_data API is not stable, so these types are to try to prevent
|
||||
// users from being able to:
|
||||
//
|
||||
|
||||
@@ -248,7 +248,16 @@ where
|
||||
return Poll::Ready(Ok(()));
|
||||
} else if self.body_rx.is_none() && self.conn.can_write_head() && self.dispatch.should_poll() {
|
||||
if let Some(msg) = ready!(self.dispatch.poll_msg(cx)) {
|
||||
let (head, body) = msg.map_err(crate::Error::new_user_service)?;
|
||||
let (head, mut body) = msg.map_err(crate::Error::new_user_service)?;
|
||||
|
||||
// Check if the body knows its full data immediately.
|
||||
//
|
||||
// If so, we can skip a bit of bookkeeping that streaming
|
||||
// bodies need to do.
|
||||
if let Some(full) = crate::body::take_full_data(&mut body) {
|
||||
self.conn.write_full_msg(head, full);
|
||||
return Poll::Ready(Ok(()));
|
||||
}
|
||||
|
||||
let body_type = if body.is_end_stream() {
|
||||
self.body_rx.set(None);
|
||||
|
||||
Reference in New Issue
Block a user