use std::fmt; use futures::{Stream, Poll, Async}; use bytes::Bytes; /// An asynchronous `Stream`. pub struct Body { inner: Inner, } enum Inner { Reusable(Bytes), Hyper(::hyper::Body), } impl Body { fn poll_inner(&mut self) -> &mut ::hyper::Body { match self.inner { Inner::Hyper(ref mut body) => body, Inner::Reusable(_) => unreachable!(), } } } impl Stream for Body { type Item = Chunk; type Error = ::Error; #[inline] fn poll(&mut self) -> Poll, Self::Error> { match try_!(self.poll_inner().poll()) { Async::Ready(opt) => Ok(Async::Ready(opt.map(|chunk| Chunk { inner: chunk, }))), Async::NotReady => Ok(Async::NotReady), } } } impl From for Body { #[inline] fn from(bytes: Bytes) -> Body { reusable(bytes) } } impl From> for Body { #[inline] fn from(vec: Vec) -> Body { reusable(vec.into()) } } impl From<&'static [u8]> for Body { #[inline] fn from(s: &'static [u8]) -> Body { reusable(Bytes::from_static(s)) } } impl From for Body { #[inline] fn from(s: String) -> Body { reusable(s.into()) } } impl From<&'static str> for Body { #[inline] fn from(s: &'static str) -> Body { s.as_bytes().into() } } /// A chunk of bytes for a `Body`. /// /// A `Chunk` can be treated like `&[u8]`. #[derive(Default)] pub struct Chunk { inner: ::hyper::Chunk, } impl AsRef<[u8]> for Chunk { #[inline] fn as_ref(&self) -> &[u8] { &*self } } impl ::std::ops::Deref for Chunk { type Target = [u8]; #[inline] fn deref(&self) -> &Self::Target { self.inner.as_ref() } } impl Extend for Chunk { fn extend(&mut self, iter: T) where T: IntoIterator { self.inner.extend(iter) } } impl IntoIterator for Chunk { type Item = u8; //XXX: exposing type from hyper! type IntoIter = <::hyper::Chunk as IntoIterator>::IntoIter; fn into_iter(self) -> Self::IntoIter { self.inner.into_iter() } } impl fmt::Debug for Body { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("Body") .finish() } } impl fmt::Debug for Chunk { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(&self.inner, f) } } // pub(crate) #[inline] pub fn wrap(body: ::hyper::Body) -> Body { Body { inner: Inner::Hyper(body), } } #[inline] pub fn take(body: &mut Body) -> Body { use std::mem; let inner = mem::replace(&mut body.inner, Inner::Hyper(::hyper::Body::empty())); Body { inner: inner, } } #[inline] pub fn empty() -> Body { Body { inner: Inner::Hyper(::hyper::Body::empty()), } } #[inline] pub fn chunk(chunk: Bytes) -> Chunk { Chunk { inner: ::hyper::Chunk::from(chunk) } } #[inline] pub fn reusable(chunk: Bytes) -> Body { Body { inner: Inner::Reusable(chunk), } } #[inline] pub fn into_hyper(body: Body) -> (Option, ::hyper::Body) { match body.inner { Inner::Reusable(chunk) => (Some(chunk.clone()), chunk.into()), Inner::Hyper(b) => (None, b), } }