use std::{fmt::Debug, future::Future};
use crate::AsyncIterator;
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[derive(Clone)]
pub struct TakeWhile<I, P> {
iter: I,
flag: bool,
predicate: P,
}
impl<I, P> TakeWhile<I, P> {
pub fn new(iter: I, predicate: P) -> TakeWhile<I, P> {
TakeWhile {
iter,
flag: false,
predicate,
}
}
}
impl<I: Debug, P> Debug for TakeWhile<I, P> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("TakeWhile")
.field("flag", &self.flag)
.field("iter", &self.iter)
.finish()
}
}
impl<I: AsyncIterator, P> AsyncIterator for TakeWhile<I, P>
where
P: FnMut(&I::Item) -> bool,
{
type Item = I::Item;
#[inline]
async fn next(&mut self) -> Option<I::Item> {
if self.flag {
None
} else {
let x = self.iter.next().await?;
if (self.predicate)(&x) {
Some(x)
} else {
self.flag = true;
None
}
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
if self.flag {
(0, Some(0))
} else {
let (_, upper) = self.iter.size_hint();
(0, upper) }
}
}
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[derive(Clone)]
pub struct AsyncTakeWhile<I, P> {
iter: I,
flag: bool,
predicate: P,
}
impl<I, P> AsyncTakeWhile<I, P> {
pub fn new(iter: I, predicate: P) -> AsyncTakeWhile<I, P> {
AsyncTakeWhile {
iter,
flag: false,
predicate,
}
}
}
impl<I: Debug, P> Debug for AsyncTakeWhile<I, P> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("AsyncTakeWhile")
.field("flag", &self.flag)
.field("iter", &self.iter)
.finish()
}
}
impl<I: AsyncIterator, P, F> AsyncIterator for AsyncTakeWhile<I, P>
where
P: FnMut(&I::Item) -> F,
F: Future<Output = bool>,
{
type Item = I::Item;
#[inline]
async fn next(&mut self) -> Option<I::Item> {
if self.flag {
None
} else {
let x = self.iter.next().await?;
if (self.predicate)(&x).await {
Some(x)
} else {
self.flag = true;
None
}
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
if self.flag {
(0, Some(0))
} else {
let (_, upper) = self.iter.size_hint();
(0, upper) }
}
}