Skip to content

Commit

Permalink
Merge pull request #27 from LorenzSchueler/master
Browse files Browse the repository at this point in the history
add StreamingIteratorMut::flatten
  • Loading branch information
cuviper authored Sep 8, 2022
2 parents a0f4ee0 + 0cd6466 commit 8f433f6
Showing 1 changed file with 115 additions and 0 deletions.
115 changes: 115 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -592,6 +592,19 @@ pub trait StreamingIteratorMut: StreamingIterator {
{
MapDerefMut { it: self, f }
}

/// Creates an iterator which flattens nested streaming iterators.
#[inline]
fn flatten(self) -> Flatten<Self>
where
Self: Sized,
Self::Item: StreamingIterator,
{
Flatten {
iter: self,
first: true,
}
}
}

impl<'a, I: ?Sized> StreamingIteratorMut for &'a mut I
Expand Down Expand Up @@ -1268,6 +1281,80 @@ where
}
}

/// A streaming iterator that flattens nested streaming iterators.
#[derive(Debug)]
pub struct Flatten<I> {
iter: I,
first: bool,
}

impl<I> StreamingIterator for Flatten<I>
where
I: StreamingIteratorMut,
I::Item: StreamingIterator,
{
type Item = <I::Item as StreamingIterator>::Item;

#[inline]
fn advance(&mut self) {
if self.first {
self.first = false;
self.iter.advance();
}
while let Some(iter) = self.iter.get_mut() {
iter.advance();
if !iter.is_done() {
break;
}
self.iter.advance(); // since we got Some, self.iter is not done and can be advanced
}
}

#[inline]
fn is_done(&self) -> bool {
match self.iter.get() {
Some(iter) => iter.is_done(),
None => true,
}
}

#[inline]
fn get(&self) -> Option<&Self::Item> {
self.iter.get().and_then(I::Item::get)
}

#[inline]
fn fold<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc
where
Self: Sized,
Fold: FnMut(Acc, &Self::Item) -> Acc,
{
self.iter
.fold_mut(init, |acc, item| item.fold(acc, &mut fold))
}
}

impl<I> StreamingIteratorMut for Flatten<I>
where
I: StreamingIteratorMut,
I::Item: StreamingIteratorMut,
{
#[inline]
fn get_mut(&mut self) -> Option<&mut Self::Item> {
self.iter.get_mut().and_then(I::Item::get_mut)
}

#[inline]
fn fold_mut<Acc, Fold>(self, init: Acc, mut fold: Fold) -> Acc
where
Self: Sized,
Fold: FnMut(Acc, &mut Self::Item) -> Acc,
{
self.iter
.fold_mut(init, |acc, item| item.fold_mut(acc, &mut fold))
}
}

/// A regular, non-streaming iterator which both filters and maps elements of a streaming iterator with a closure.
#[derive(Debug)]
pub struct FilterMapDeref<I, F> {
Expand Down Expand Up @@ -2549,6 +2636,34 @@ mod test {
test(it, &[0, 1, 2, 3, 4, 5]);
}

#[test]
fn flatten() {
let mut items = [
convert_ref([].as_ref()),
convert_ref([1].as_ref()),
convert_ref([].as_ref()),
convert_ref([2, 3].as_ref()),
convert_ref([].as_ref()),
];
let it = convert_mut(&mut items).flatten();

test(it, &[1, 2, 3]);
}

#[test]
fn flatten_unsized() {
type DynI32 = dyn StreamingIterator<Item = i32>;
let mut items = [
&mut once(1) as &mut DynI32,
&mut empty(),
&mut convert(2..=3),
];
let iters = items.iter_mut().map(|iter| &mut **iter);
let it = convert_mut(iters).flatten();

test(it, &[1, 2, 3]);
}

#[test]
fn nth() {
let items = [0, 1];
Expand Down

0 comments on commit 8f433f6

Please sign in to comment.