use std::{future::Future, fmt::Debug};
use super::peekable::Peekable;
use crate::AsyncIterator;
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[derive(Debug, Clone)]
pub struct Intersperse<I: AsyncIterator>
where
I::Item: Clone,
{
separator: I::Item,
iter: Peekable<I>,
needs_sep: bool,
}
impl<I: AsyncIterator> Intersperse<I>
where
I::Item: Clone,
{
pub fn new(iter: I, separator: I::Item) -> Self {
Self {
iter: iter.peekable(),
separator,
needs_sep: false,
}
}
}
impl<I> AsyncIterator for Intersperse<I>
where
I: AsyncIterator,
I::Item: Clone,
{
type Item = I::Item;
#[inline]
async fn next(&mut self) -> Option<I::Item> {
if self.needs_sep && self.iter.peek().await.is_some() {
self.needs_sep = false;
Some(self.separator.clone())
} else {
self.needs_sep = true;
self.iter.next().await
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
intersperse_size_hint(&self.iter, self.needs_sep)
}
}
#[must_use = "iterators are lazy and do nothing unless consumed"]
pub struct IntersperseWith<I, G>
where
I: AsyncIterator,
{
separator: G,
iter: Peekable<I>,
needs_sep: bool,
}
impl<I: AsyncIterator + Debug, G> Debug for IntersperseWith<I, G>
where
I::Item: Debug
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("IntersperseWith")
.field("needs_sep", &self.needs_sep)
.field("iter", &self.iter)
.finish()
}
}
impl<I: AsyncIterator + Clone, G: Clone> std::clone::Clone for IntersperseWith<I, G>
where
I::Item: Clone,
{
fn clone(&self) -> Self {
Self {
separator: self.separator.clone(),
iter: self.iter.clone(),
needs_sep: self.needs_sep,
}
}
fn clone_from(&mut self, source: &Self) {
self.separator = source.separator.clone();
self.iter = source.iter.clone();
self.needs_sep = source.needs_sep;
}
}
impl<I, G> IntersperseWith<I, G>
where
I: AsyncIterator,
G: FnMut() -> I::Item,
{
pub fn new(iter: I, separator: G) -> Self {
Self {
iter: iter.peekable(),
separator,
needs_sep: false,
}
}
}
impl<I, G> AsyncIterator for IntersperseWith<I, G>
where
I: AsyncIterator,
G: FnMut() -> I::Item,
{
type Item = I::Item;
#[inline]
async fn next(&mut self) -> Option<I::Item> {
if self.needs_sep && self.iter.peek().await.is_some() {
self.needs_sep = false;
Some((self.separator)())
} else {
self.needs_sep = true;
self.iter.next().await
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
intersperse_size_hint(&self.iter, self.needs_sep)
}
}
#[must_use = "iterators are lazy and do nothing unless consumed"]
pub struct AsyncIntersperseWith<I, G>
where
I: AsyncIterator,
{
separator: G,
iter: Peekable<I>,
needs_sep: bool,
}
impl<I: AsyncIterator + Debug, G> Debug for AsyncIntersperseWith<I, G>
where
I::Item: Debug
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("IntersperseWith")
.field("needs_sep", &self.needs_sep)
.field("iter", &self.iter)
.finish()
}
}
impl<I: AsyncIterator + Clone, G: Clone> std::clone::Clone for AsyncIntersperseWith<I, G>
where
I::Item: Clone,
{
fn clone(&self) -> Self {
Self {
separator: self.separator.clone(),
iter: self.iter.clone(),
needs_sep: self.needs_sep,
}
}
fn clone_from(&mut self, source: &Self) {
self.separator = source.separator.clone();
self.iter = source.iter.clone();
self.needs_sep = source.needs_sep;
}
}
impl<I, G, F> AsyncIntersperseWith<I, G>
where
I: AsyncIterator,
G: FnMut() -> F,
F: Future<Output = I::Item>,
{
pub fn new(iter: I, separator: G) -> Self {
Self {
iter: iter.peekable(),
separator,
needs_sep: false,
}
}
}
impl<I, G, F> AsyncIterator for AsyncIntersperseWith<I, G>
where
I: AsyncIterator,
G: FnMut() -> F,
F: Future<Output = I::Item>,
{
type Item = I::Item;
#[inline]
async fn next(&mut self) -> Option<I::Item> {
if self.needs_sep && self.iter.peek().await.is_some() {
self.needs_sep = false;
Some((self.separator)().await)
} else {
self.needs_sep = true;
self.iter.next().await
}
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
intersperse_size_hint(&self.iter, self.needs_sep)
}
}
#[inline]
fn intersperse_size_hint<I>(iter: &I, needs_sep: bool) -> (usize, Option<usize>)
where
I: AsyncIterator,
{
let (lo, hi) = iter.size_hint();
let next_is_elem = !needs_sep;
(
lo.saturating_sub(next_is_elem as usize).saturating_add(lo),
hi.and_then(|hi| hi.saturating_sub(next_is_elem as usize).checked_add(hi)),
)
}