use std::{fmt::Debug, future::Future};
use crate::{AsyncIterator, IntoAsyncIterator};
use super::{
fuse::Fuse,
map::{AsyncMap, Map},
};
#[must_use = "iterators are lazy and do nothing unless consumed"]
pub struct Flatten<I: AsyncIterator<Item = A>, A: IntoAsyncIterator> {
inner: FlattenCompat<I, <I::Item as IntoAsyncIterator>::AsyncIter>,
}
impl<I, U> Debug for Flatten<I, U>
where
I: AsyncIterator<Item = U> + Debug,
U: IntoAsyncIterator + Debug,
U::AsyncIter: Debug,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Flatten")
.field("inner", &self.inner)
.finish()
}
}
impl<I, U> std::clone::Clone for Flatten<I, U>
where
I: AsyncIterator<Item = U> + Clone,
U: IntoAsyncIterator + Clone,
U::AsyncIter: Clone,
{
fn clone(&self) -> Self {
Self {
inner: self.inner.clone(),
}
}
fn clone_from(&mut self, source: &Self) {
self.inner = source.inner.clone();
}
}
impl<I: AsyncIterator<Item = A>, A: IntoAsyncIterator> Flatten<I, A> {
pub fn new(iter: I) -> Flatten<I, A> {
Flatten {
inner: FlattenCompat::new(iter),
}
}
}
impl<I: AsyncIterator<Item = A>, A: IntoAsyncIterator> AsyncIterator for Flatten<I, A> {
type Item = A::Item;
#[inline]
fn next(&mut self) -> impl Future<Output = Option<A::Item>> {
self.inner.next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}
#[must_use = "iterators are lazy and do nothing unless consumed"]
pub struct FlatMap<I, U: IntoAsyncIterator, F> {
inner: FlattenCompat<Map<I, F>, <U as IntoAsyncIterator>::AsyncIter>,
}
impl<I, U, F> Debug for FlatMap<I, U, F>
where
F: (FnMut(I::Item) -> U) + Debug,
I: AsyncIterator<Item = U> + Debug,
U: IntoAsyncIterator + Debug,
U::AsyncIter: Debug,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("FlatMap")
.field("inner", &self.inner)
.finish()
}
}
impl<I, U, F> std::clone::Clone for FlatMap<I, U, F>
where
F: (FnMut(I::Item) -> U) + Clone,
I: AsyncIterator + Clone,
U: IntoAsyncIterator + Clone,
U::AsyncIter: Clone,
{
fn clone(&self) -> Self {
Self {
inner: self.inner.clone(),
}
}
fn clone_from(&mut self, source: &Self) {
self.inner = source.inner.clone();
}
}
impl<I: AsyncIterator, U: IntoAsyncIterator, F: FnMut(I::Item) -> U> FlatMap<I, U, F> {
pub fn new(iter: I, f: F) -> FlatMap<I, U, F> {
FlatMap {
inner: FlattenCompat::new(iter.map(f)),
}
}
}
impl<I, U, F> AsyncIterator for FlatMap<I, U, F>
where
I: AsyncIterator,
U: IntoAsyncIterator,
F: FnMut(I::Item) -> U,
{
type Item = U::Item;
#[inline]
fn next(&mut self) -> impl Future<Output = Option<U::Item>> {
self.inner.next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}
#[must_use = "iterators are lazy and do nothing unless consumed"]
pub struct AsyncFlatMap<I: AsyncIterator, U: IntoAsyncIterator, F, O>
where
F: FnMut(I::Item) -> O,
O: Future<Output = U>,
{
inner: FlattenCompat<AsyncMap<I, F>, <U as IntoAsyncIterator>::AsyncIter>,
}
impl<I, U, F, O> Debug for AsyncFlatMap<I, U, F, O>
where
F: (FnMut(I::Item) -> O) + Debug,
I: AsyncIterator + Debug,
U: IntoAsyncIterator + Debug,
U::AsyncIter: Debug,
O: Future<Output = U> + Clone,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("AsyncFlatMap")
.field("inner", &self.inner)
.finish()
}
}
impl<I, U, F, O> std::clone::Clone for AsyncFlatMap<I, U, F, O>
where
F: (FnMut(I::Item) -> O) + Clone,
I: AsyncIterator + Clone,
U: IntoAsyncIterator + Clone,
U::AsyncIter: Clone,
O: Future<Output = U> + Clone,
{
fn clone(&self) -> Self {
Self {
inner: self.inner.clone(),
}
}
fn clone_from(&mut self, source: &Self) {
self.inner = source.inner.clone();
}
}
impl<I, U, F, B> AsyncFlatMap<I, U, F, B>
where
I: AsyncIterator,
U: IntoAsyncIterator,
F: FnMut(I::Item) -> B,
B: Future<Output = U>,
{
pub fn new(iter: I, f: F) -> AsyncFlatMap<I, U, F, B> {
AsyncFlatMap {
inner: FlattenCompat::new(iter.amap(f)),
}
}
}
impl<I, U, F, B> AsyncIterator for AsyncFlatMap<I, U, F, B>
where
I: AsyncIterator,
U: IntoAsyncIterator,
F: FnMut(I::Item) -> B,
B: Future<Output = U>,
{
type Item = U::Item;
#[inline]
fn next(&mut self) -> impl Future<Output = Option<U::Item>> {
self.inner.next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[derive(Debug)]
struct FlattenCompat<I, U> {
iter: Fuse<I>,
frontiter: Option<U>,
backiter: Option<U>,
}
impl<I: AsyncIterator + Clone, U: AsyncIterator + Clone> std::clone::Clone for FlattenCompat<I, U> {
fn clone(&self) -> Self {
Self {
iter: self.iter.clone(),
frontiter: self.frontiter.clone(),
backiter: self.backiter.clone(),
}
}
fn clone_from(&mut self, source: &Self) {
self.iter = source.iter.clone();
self.frontiter = source.frontiter.clone();
self.backiter = source.backiter.clone();
}
}
impl<I, U> FlattenCompat<I, U>
where
I: AsyncIterator,
{
fn new(iter: I) -> FlattenCompat<I, U> {
FlattenCompat {
iter: iter.fuse(),
frontiter: None,
backiter: None,
}
}
}
impl<I, U, B> AsyncIterator for FlattenCompat<I, U>
where
I: AsyncIterator<Item = B>,
B: IntoAsyncIterator<Item = U::Item, AsyncIter = U>,
U: AsyncIterator,
{
type Item = U::Item;
async fn next(&mut self) -> Option<U::Item> {
loop {
if let elt @ Some(_) = match self.frontiter.as_mut() {
Some(it) => {
let x: Option<B::Item> = it.next().await;
if x.is_none() {
self.frontiter = None;
}
x
}
None => None,
} {
break elt;
}
match self.iter.next().await {
None => {
if let Some(it) = self.backiter.as_mut() {
let x: Option<B::Item> = it.next().await;
if x.is_none() {
self.backiter = None;
}
break x;
} else {
break None;
}
}
Some(inner) => self.frontiter = Some(inner.into_aiter()),
}
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let (flo, fhi) = self.frontiter.as_ref().map_or((0, Some(0)), U::size_hint);
let (blo, bhi) = self.backiter.as_ref().map_or((0, Some(0)), U::size_hint);
let lo = flo.saturating_add(blo);
match (self.iter.size_hint(), fhi, bhi) {
((0, Some(0)), Some(a), Some(b)) => (lo, a.checked_add(b)),
_ => (lo, None),
}
}
}