From c5a123b72d0233c9ebc7739268e0f8273ccbd89a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lorenz=20Sch=C3=BCler?= Date: Wed, 17 Aug 2022 08:32:20 +0200 Subject: [PATCH 1/8] add StreamingIteratorMut::flatten and Flatten --- src/lib.rs | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 6da2195..89531a5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -40,7 +40,7 @@ #![warn(missing_docs)] #![cfg_attr(not(feature = "std"), no_std)] -use core::cmp; +use core::{cmp, marker::PhantomData}; mod sources; pub use crate::sources::{convert, Convert}; @@ -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 + where + Self: Sized, + Self::Item: StreamingIterator + Sized, + { + Flatten { + iter: self, + _inner: PhantomData, + } + } } impl<'a, I: ?Sized> StreamingIteratorMut for &'a mut I @@ -1259,6 +1272,61 @@ where } } +/// A streaming iterator that flattens nested streaming iterators. +#[derive(Debug)] +pub struct Flatten { + iter: I, + _inner: PhantomData, +} + +impl StreamingIterator for Flatten +where + I: StreamingIteratorMut, + J: StreamingIterator, +{ + type Item = J::Item; + + #[inline] + fn advance(&mut self) { + loop { + if let Some(ref mut iter) = self.iter.get_mut() { + iter.advance(); + if !iter.is_done() { + break; + } + } + self.iter.advance(); + if self.iter.is_done() { + break; + } + } + } + + #[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(|iter| iter.get()) + } +} + +impl StreamingIteratorMut for Flatten +where + I: StreamingIteratorMut, + J: StreamingIteratorMut, +{ + #[inline] + fn get_mut(&mut self) -> Option<&mut Self::Item> { + self.iter.get_mut().and_then(J::get_mut) + } +} + /// A regular, non-streaming iterator which both filters and maps elements of a streaming iterator with a closure. #[derive(Debug)] pub struct FilterMapDeref { From 3a64d5c69064aa7ddd0b1315b7e2a9f6d36d01c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lorenz=20Sch=C3=BCler?= Date: Wed, 17 Aug 2022 09:14:08 +0200 Subject: [PATCH 2/8] add test --- src/lib.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 89531a5..7435dd9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2566,6 +2566,14 @@ mod test { test(it, &[0, 1, 2, 3, 4, 5]); } + #[test] + fn flatten() { + let mut items = [convert([0, 1, 2]), convert([3, 4, 5])]; + let it = convert_mut(&mut items).flatten(); + + test(it, &[0, 1, 2, 3, 4, 5]); + } + #[test] fn nth() { let items = [0, 1]; From 58cf57c0b4f011b4755e463d2045967193487fed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lorenz=20Sch=C3=BCler?= Date: Tue, 6 Sep 2022 13:10:26 +0200 Subject: [PATCH 3/8] get rid of PhantomData --- src/lib.rs | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 7435dd9..c84511a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -40,7 +40,7 @@ #![warn(missing_docs)] #![cfg_attr(not(feature = "std"), no_std)] -use core::{cmp, marker::PhantomData}; +use core::cmp; mod sources; pub use crate::sources::{convert, Convert}; @@ -595,15 +595,12 @@ pub trait StreamingIteratorMut: StreamingIterator { /// Creates an iterator which flattens nested streaming iterators. #[inline] - fn flatten(self) -> Flatten + fn flatten(self) -> Flatten where Self: Sized, Self::Item: StreamingIterator + Sized, { - Flatten { - iter: self, - _inner: PhantomData, - } + Flatten { iter: self } } } @@ -1274,15 +1271,14 @@ where /// A streaming iterator that flattens nested streaming iterators. #[derive(Debug)] -pub struct Flatten { +pub struct Flatten { iter: I, - _inner: PhantomData, } -impl StreamingIterator for Flatten +impl StreamingIterator for Flatten where I: StreamingIteratorMut, - J: StreamingIterator, + for<'a> J: StreamingIterator + 'a, { type Item = J::Item; @@ -1316,10 +1312,10 @@ where } } -impl StreamingIteratorMut for Flatten +impl StreamingIteratorMut for Flatten where I: StreamingIteratorMut, - J: StreamingIteratorMut, + for<'a> J: StreamingIteratorMut + 'a, { #[inline] fn get_mut(&mut self) -> Option<&mut Self::Item> { From 03220e068f269da15694b3909aebbab5821a3757 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lorenz=20Sch=C3=BCler?= Date: Tue, 6 Sep 2022 15:06:17 +0200 Subject: [PATCH 4/8] fix advance --- src/lib.rs | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index c84511a..389d547 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -600,7 +600,11 @@ pub trait StreamingIteratorMut: StreamingIterator { Self: Sized, Self::Item: StreamingIterator + Sized, { - Flatten { iter: self } + Flatten { + iter: self, + first: true, + inner_first: true, + } } } @@ -1273,6 +1277,8 @@ where #[derive(Debug)] pub struct Flatten { iter: I, + first: bool, + inner_first: bool, } impl StreamingIterator for Flatten @@ -1284,17 +1290,20 @@ where #[inline] fn advance(&mut self) { - loop { - if let Some(ref mut iter) = self.iter.get_mut() { + if self.first { + self.first = false; + self.iter.advance(); + } + while let Some(iter) = self.iter.get_mut() { + if self.inner_first || !iter.is_done() { + self.inner_first = false; iter.advance(); if !iter.is_done() { break; } } - self.iter.advance(); - if self.iter.is_done() { - break; - } + self.iter.advance(); // since we got Some, self.iter is not done and can be advanced + self.inner_first = true; } } @@ -2564,10 +2573,16 @@ mod test { #[test] fn flatten() { - let mut items = [convert([0, 1, 2]), convert([3, 4, 5])]; + 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, &[0, 1, 2, 3, 4, 5]); + test(it, &[1, 2, 3]); } #[test] From 01b09b086a975f39030160417b44fc317d2fb18e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lorenz=20Sch=C3=BCler?= Date: Tue, 6 Sep 2022 15:36:24 +0200 Subject: [PATCH 5/8] add fold and fold_mut --- src/lib.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 389d547..ede2fe0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1319,6 +1319,16 @@ where fn get(&self) -> Option<&Self::Item> { self.iter.get().and_then(|iter| iter.get()) } + + #[inline] + fn 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 StreamingIteratorMut for Flatten @@ -1330,6 +1340,16 @@ where fn get_mut(&mut self) -> Option<&mut Self::Item> { self.iter.get_mut().and_then(J::get_mut) } + + #[inline] + fn fold_mut(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. From 38cbe94a0d9a9df055d3bbd0ca9136e5d103bef1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lorenz=20Sch=C3=BCler?= Date: Wed, 7 Sep 2022 09:46:18 +0200 Subject: [PATCH 6/8] remove inner_first --- src/lib.rs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index ede2fe0..ad22759 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -603,7 +603,6 @@ pub trait StreamingIteratorMut: StreamingIterator { Flatten { iter: self, first: true, - inner_first: true, } } } @@ -1278,7 +1277,6 @@ where pub struct Flatten { iter: I, first: bool, - inner_first: bool, } impl StreamingIterator for Flatten @@ -1295,15 +1293,11 @@ where self.iter.advance(); } while let Some(iter) = self.iter.get_mut() { - if self.inner_first || !iter.is_done() { - self.inner_first = false; - iter.advance(); - if !iter.is_done() { - break; - } + iter.advance(); + if !iter.is_done() { + break; } self.iter.advance(); // since we got Some, self.iter is not done and can be advanced - self.inner_first = true; } } From 321a6c8cf79bbf5e9e6ae0e02070e640959c4797 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 7 Sep 2022 16:11:43 -0700 Subject: [PATCH 7/8] Remove the lifetime requirements on Flatten impls --- src/lib.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index ad22759..8afeac0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1279,12 +1279,12 @@ pub struct Flatten { first: bool, } -impl StreamingIterator for Flatten +impl StreamingIterator for Flatten where - I: StreamingIteratorMut, - for<'a> J: StreamingIterator + 'a, + I: StreamingIteratorMut, + I::Item: StreamingIterator, { - type Item = J::Item; + type Item = ::Item; #[inline] fn advance(&mut self) { @@ -1311,7 +1311,7 @@ where #[inline] fn get(&self) -> Option<&Self::Item> { - self.iter.get().and_then(|iter| iter.get()) + self.iter.get().and_then(I::Item::get) } #[inline] @@ -1325,14 +1325,14 @@ where } } -impl StreamingIteratorMut for Flatten +impl StreamingIteratorMut for Flatten where - I: StreamingIteratorMut, - for<'a> J: StreamingIteratorMut + 'a, + I: StreamingIteratorMut, + I::Item: StreamingIteratorMut, { #[inline] fn get_mut(&mut self) -> Option<&mut Self::Item> { - self.iter.get_mut().and_then(J::get_mut) + self.iter.get_mut().and_then(I::Item::get_mut) } #[inline] From 0cd6466d8d4f35f5afd5248d40ffb7fcccd19b19 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 7 Sep 2022 16:13:27 -0700 Subject: [PATCH 8/8] Let Flatten work with unsized iterators --- src/lib.rs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 8afeac0..f12239e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -598,7 +598,7 @@ pub trait StreamingIteratorMut: StreamingIterator { fn flatten(self) -> Flatten where Self: Sized, - Self::Item: StreamingIterator + Sized, + Self::Item: StreamingIterator, { Flatten { iter: self, @@ -2599,6 +2599,20 @@ mod test { test(it, &[1, 2, 3]); } + #[test] + fn flatten_unsized() { + type DynI32 = dyn StreamingIterator; + 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];