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 {
|
impl Default for Body {
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
//! and returned by hyper as a "receive stream" (so, for server requests and
|
//! 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
|
//! client responses). It is also a decent default implementation if you don't
|
||||||
//! have very custom needs of your send streams.
|
//! have very custom needs of your send streams.
|
||||||
|
|
||||||
pub use self::body::{Body, Sender};
|
pub use self::body::{Body, Sender};
|
||||||
pub use self::chunk::Chunk;
|
pub use self::chunk::Chunk;
|
||||||
pub use self::payload::Payload;
|
pub use self::payload::Payload;
|
||||||
@@ -22,6 +23,27 @@ mod body;
|
|||||||
mod chunk;
|
mod chunk;
|
||||||
mod payload;
|
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
|
// The full_data API is not stable, so these types are to try to prevent
|
||||||
// users from being able to:
|
// users from being able to:
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -248,7 +248,16 @@ where
|
|||||||
return Poll::Ready(Ok(()));
|
return Poll::Ready(Ok(()));
|
||||||
} else if self.body_rx.is_none() && self.conn.can_write_head() && self.dispatch.should_poll() {
|
} 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)) {
|
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() {
|
let body_type = if body.is_end_stream() {
|
||||||
self.body_rx.set(None);
|
self.body_rx.set(None);
|
||||||
|
|||||||
Reference in New Issue
Block a user