use bytes::Bytes; use futures::{Poll, Stream}; use futures::sync::mpsc; use tokio_proto; use std::borrow::Cow; use super::Chunk; pub type TokioBody = tokio_proto::streaming::Body; /// A `Stream` for `Chunk`s used in requests and responses. #[must_use = "streams do nothing unless polled"] #[derive(Debug)] pub struct Body(TokioBody); impl Body { /// Return an empty body stream #[inline] pub fn empty() -> Body { Body(TokioBody::empty()) } /// Return a body stream with an associated sender half #[inline] pub fn pair() -> (mpsc::Sender>, Body) { let (tx, rx) = TokioBody::pair(); let rx = Body(rx); (tx, rx) } } impl Default for Body { #[inline] fn default() -> Body { Body::empty() } } impl Stream for Body { type Item = Chunk; type Error = ::Error; #[inline] fn poll(&mut self) -> Poll, ::Error> { self.0.poll() } } impl From for tokio_proto::streaming::Body { #[inline] fn from(b: Body) -> tokio_proto::streaming::Body { b.0 } } impl From> for Body { #[inline] fn from(tokio_body: tokio_proto::streaming::Body) -> Body { Body(tokio_body) } } impl From>> for Body { #[inline] fn from(src: mpsc::Receiver>) -> Body { Body(src.into()) } } impl From for Body { #[inline] fn from (chunk: Chunk) -> Body { Body(TokioBody::from(chunk)) } } impl From for Body { #[inline] fn from (bytes: Bytes) -> Body { Body(TokioBody::from(Chunk::from(bytes))) } } impl From> for Body { #[inline] fn from (vec: Vec) -> Body { Body(TokioBody::from(Chunk::from(vec))) } } impl From<&'static [u8]> for Body { #[inline] fn from (slice: &'static [u8]) -> Body { Body(TokioBody::from(Chunk::from(slice))) } } impl From> for Body { #[inline] fn from (cow: Cow<'static, [u8]>) -> Body { if let Cow::Borrowed(value) = cow { Body::from(value) } else { Body::from(cow.to_owned()) } } } impl From for Body { #[inline] fn from (s: String) -> Body { Body(TokioBody::from(Chunk::from(s.into_bytes()))) } } impl From<&'static str> for Body { #[inline] fn from(slice: &'static str) -> Body { Body(TokioBody::from(Chunk::from(slice.as_bytes()))) } } impl From> for Body { #[inline] fn from(cow: Cow<'static, str>) -> Body { if let Cow::Borrowed(value) = cow { Body::from(value) } else { Body::from(cow.to_owned()) } } } impl From> for Body { #[inline] fn from (body: Option) -> Body { body.unwrap_or_default() } } fn _assert_send_sync() { fn _assert_send() {} fn _assert_sync() {} _assert_send::(); _assert_send::(); _assert_sync::(); } #[test] fn test_body_stream_concat() { use futures::{Sink, Stream, Future}; let (tx, body) = Body::pair(); ::std::thread::spawn(move || { let tx = tx.send(Ok("hello ".into())).wait().unwrap(); tx.send(Ok("world".into())).wait().unwrap(); }); let total = body.concat2().wait().unwrap(); assert_eq!(total.as_ref(), b"hello world"); }