use std::mem;
use {Future, IntoFuture, Task, Poll};
use util::Collapsed;
pub struct Collect<I>
where I: IntoIterator + Send + 'static,
I::Item: IntoFuture,
I::IntoIter: Send + 'static,
{
cur: Option<Collapsed<<I::Item as IntoFuture>::Future>>,
remaining: I::IntoIter,
result: Vec<<I::Item as IntoFuture>::Item>,
}
pub fn collect<I>(i: I) -> Collect<I>
where I: IntoIterator + Send + 'static,
I::Item: IntoFuture,
I::IntoIter: Send + 'static,
{
let mut i = i.into_iter();
Collect {
cur: i.next().map(IntoFuture::into_future).map(Collapsed::Start),
remaining: i,
result: Vec::new(),
}
}
impl<I> Future for Collect<I>
where I: IntoIterator + Send + 'static,
I::IntoIter: Send + 'static,
I::Item: IntoFuture,
{
type Item = Vec<<I::Item as IntoFuture>::Item>;
type Error = <I::Item as IntoFuture>::Error;
fn poll(&mut self, task: &mut Task) -> Poll<Self::Item, Self::Error> {
let mut task = task.scoped();
loop {
match self.cur {
Some(ref mut cur) => {
match try_poll!(cur.poll(&mut task)) {
Ok(e) => self.result.push(e),
Err(e) => {
for f in self.remaining.by_ref() {
drop(f);
}
for f in self.result.drain(..) {
drop(f);
}
return Poll::Err(e)
}
}
}
None => {
return Poll::Ok(mem::replace(&mut self.result, Vec::new()))
}
}
task.ready();
self.cur = self.remaining.next()
.map(IntoFuture::into_future)
.map(Collapsed::Start);
}
}
fn schedule(&mut self, task: &mut Task) {
if let Some(ref mut cur) = self.cur {
cur.schedule(task);
}
}
fn tailcall(&mut self)
-> Option<Box<Future<Item=Self::Item, Error=Self::Error>>> {
if let Some(ref mut cur) = self.cur {
cur.collapse();
}
None
}
}