Files
tokio/tokio-buf/src/util/collect.rs
T

102 lines
2.5 KiB
Rust
Raw Normal View History

use super::FromBufStream;
2019-02-21 11:56:15 -08:00
use BufStream;
2018-10-29 13:43:48 -07:00
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<T, U>
where
T: BufStream,
U: FromBufStream<T::Item>,
{
stream: T,
builder: Option<U::Builder>,
}
/// Errors returned from `Collect` future.
#[derive(Debug)]
pub struct CollectError<T, U> {
inner: Error<T, U>,
}
#[derive(Debug)]
enum Error<T, U> {
Stream(T),
Collect(U),
}
impl<T, U> Collect<T, U>
where
T: BufStream,
U: FromBufStream<T::Item>,
{
pub(crate) fn new(stream: T) -> Collect<T, U> {
let builder = U::builder(&stream.size_hint());
Collect {
stream,
builder: Some(builder),
}
}
}
impl<T, U> Future for Collect<T, U>
where
T: BufStream,
U: FromBufStream<T::Item>,
{
type Item = U;
type Error = CollectError<T::Error, U::Error>;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
loop {
2019-02-21 11:56:15 -08:00
let res = self.stream.poll_buf().map_err(|err| {
let inner = Error::Stream(err);
CollectError { inner }
});
2018-10-29 13:43:48 -07:00
match try_ready!(res) {
Some(mut buf) => {
let builder = self.builder.as_mut().expect("cannot poll after done");
2019-02-21 11:56:15 -08:00
U::extend(builder, &mut buf, &self.stream.size_hint()).map_err(|err| {
let inner = Error::Collect(err);
CollectError { inner }
})?;
2018-10-29 13:43:48 -07:00
}
None => {
let builder = self.builder.take().expect("cannot poll after done");
2019-02-21 11:56:15 -08:00
let value = U::build(builder).map_err(|err| {
let inner = Error::Collect(err);
CollectError { inner }
})?;
2018-10-29 13:43:48 -07:00
return Ok(value.into());
}
}
}
}
}
// ===== impl CollectError =====
impl<T, U> CollectError<T, U> {
/// 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,
}
}
}