use super::FromBufStream; use BufStream; use futures::{Future, Poll}; /// Consumes a buf stream, collecting the data into a single byte container. /// /// `Collect` values are produced by `BufStream::collect`. #[derive(Debug)] pub struct Collect where T: BufStream, U: FromBufStream, { stream: T, builder: Option, } /// Errors returned from `Collect` future. #[derive(Debug)] pub struct CollectError { inner: Error, } #[derive(Debug)] enum Error { Stream(T), Collect(U), } impl Collect where T: BufStream, U: FromBufStream, { pub(crate) fn new(stream: T) -> Collect { let builder = U::builder(&stream.size_hint()); Collect { stream, builder: Some(builder), } } } impl Future for Collect where T: BufStream, U: FromBufStream, { type Item = U; type Error = CollectError; fn poll(&mut self) -> Poll { loop { let res = self.stream.poll_buf().map_err(|err| { let inner = Error::Stream(err); CollectError { inner } }); match try_ready!(res) { Some(mut buf) => { let builder = self.builder.as_mut().expect("cannot poll after done"); U::extend(builder, &mut buf, &self.stream.size_hint()).map_err(|err| { let inner = Error::Collect(err); CollectError { inner } })?; } None => { let builder = self.builder.take().expect("cannot poll after done"); let value = U::build(builder).map_err(|err| { let inner = Error::Collect(err); CollectError { inner } })?; return Ok(value.into()); } } } } } // ===== impl CollectError ===== impl CollectError { /// Returns `true` if the error was caused by polling the stream. pub fn is_stream_err(&self) -> bool { match self.inner { Error::Stream(_) => true, _ => false, } } /// Returns `true` if the error happened while collecting the data. pub fn is_collect_err(&self) -> bool { match self.inner { Error::Collect(_) => true, _ => false, } } }