use alloc::boxed::Box;
use alloc::vec::Vec;
use core::future::Future;
use core::pin::Pin;
use core::task::{Context, Poll};
use futures_core::Stream;
#[cfg(feature = "fusion")]
use super::flumen_fusus::{FlumenFusus, Gradus, GradusStep};
pub type BoxStream<T> = Pin<Box<dyn Stream<Item = T> + Send + 'static>>;
pub struct Flumen<T> {
inner: BoxStream<T>,
}
impl<T: Send + 'static> Flumen<T> {
#[inline]
pub fn new<S>(stream: S) -> Self
where
S: Stream<Item = T> + Send + 'static,
{
Flumen {
inner: Box::pin(stream),
}
}
#[inline]
pub fn from_iterator<I>(iter: I) -> Self
where
I: IntoIterator<Item = T>,
I::IntoIter: Send + Unpin + 'static,
{
Flumen::new(IterStream::new(iter.into_iter()))
}
#[inline]
pub fn once(value: T) -> Self
where
T: Unpin,
{
Flumen::from_iterator(core::iter::once(value))
}
#[inline]
pub fn empty() -> Self
where
T: Unpin,
{
Flumen::from_iterator(core::iter::empty())
}
#[inline]
pub fn purus(value: T) -> Self
where
T: Unpin,
{
Self::once(value)
}
#[inline(always)]
pub fn fmap<B, F>(self, f: F) -> Flumen<B>
where
F: Fn(T) -> B + Send + Sync + Unpin + 'static,
B: Send + 'static,
{
Flumen::new(MapStream::new(self.inner, f))
}
#[inline(always)]
pub fn filter<F>(self, predicate: F) -> Flumen<T>
where
F: Fn(&T) -> bool + Send + Sync + Unpin + 'static,
{
Flumen::new(FilterStream::new(self.inner, predicate))
}
#[inline(always)]
pub fn filter_map<B, F>(self, f: F) -> Flumen<B>
where
F: Fn(T) -> Option<B> + Send + Sync + Unpin + 'static,
B: Send + 'static,
{
Flumen::new(FilterMapStream::new(self.inner, f))
}
#[inline(always)]
pub fn take(self, n: usize) -> Flumen<T> {
Flumen::new(TakeStream::new(self.inner, n))
}
#[inline(always)]
pub fn skip(self, n: usize) -> Flumen<T> {
Flumen::new(SkipStream::new(self.inner, n))
}
#[inline(always)]
pub fn take_while<F>(self, predicate: F) -> Flumen<T>
where
F: Fn(&T) -> bool + Send + Sync + Unpin + 'static,
{
Flumen::new(TakeWhileStream::new(self.inner, predicate))
}
#[inline(always)]
pub fn skip_while<F>(self, predicate: F) -> Flumen<T>
where
F: Fn(&T) -> bool + Send + Sync + Unpin + 'static,
{
Flumen::new(SkipWhileStream::new(self.inner, predicate))
}
#[inline(always)]
pub fn chain(self, other: Flumen<T>) -> Flumen<T> {
Flumen::new(ChainStream::new(self.inner, other.inner))
}
#[inline(always)]
pub fn zip<U: Send + 'static>(self, other: Flumen<U>) -> Flumen<(T, U)> {
Flumen::new(ZipStream::new(self.inner, other.inner))
}
#[inline(always)]
pub fn enumerate(self) -> Flumen<(usize, T)> {
Flumen::new(EnumerateStream::new(self.inner))
}
#[inline(always)]
pub fn scan<B, F>(self, init: B, f: F) -> Flumen<B>
where
B: Clone + Send + Unpin + 'static,
F: Fn(B, T) -> B + Send + Sync + Unpin + 'static,
{
Flumen::new(ScanStream::new(self.inner, init, f))
}
#[inline(always)]
pub fn scan_with<S, B, F>(self, init: S, f: F) -> Flumen<B>
where
S: Send + Unpin + 'static,
B: Send + 'static,
F: FnMut(&mut S, T) -> Option<B> + Send + Sync + Unpin + 'static,
{
Flumen::new(ScanWithStream::new(self.inner, init, f))
}
#[inline(always)]
pub fn chunks(self, size: usize) -> Flumen<Vec<T>>
where
T: Unpin,
{
assert!(size > 0, "chunk size must be greater than 0");
Flumen::new(ChunksStream::new(self.inner, size))
}
#[inline(always)]
pub fn inspect<F>(self, f: F) -> Flumen<T>
where
F: Fn(&T) + Send + Sync + Unpin + 'static,
{
self.fmap(move |x| {
f(&x);
x
})
}
#[inline]
pub async fn fold<B, F>(mut self, init: B, mut f: F) -> B
where
F: FnMut(B, T) -> B + Send,
B: Send,
{
let mut acc = init;
while let Some(item) = self.next().await {
acc = f(acc, item);
}
acc
}
#[inline]
pub async fn reduce<F>(mut self, f: F) -> Option<T>
where
F: Fn(T, T) -> T + Send,
{
let first = self.next().await?;
Some(self.fold(first, f).await)
}
#[inline]
pub async fn collect_vec(self) -> Vec<T> {
let (lower, _) = self.inner.size_hint();
self.fold(Vec::with_capacity(lower), |mut acc, item| {
acc.push(item);
acc
})
.await
}
#[cfg(feature = "fusion")]
#[inline(always)]
pub fn fuse(self) -> FlumenFusus<BoxStream<T>, impl GradusStep<BoxStream<T>, T>, T> {
FlumenFusus::new(
self.inner,
|s: &mut BoxStream<T>, cx: &mut Context<'_>| match s.as_mut().poll_next(cx) {
Poll::Pending => Poll::Pending,
Poll::Ready(Some(item)) => Poll::Ready(Gradus::Yield(item)),
Poll::Ready(None) => Poll::Ready(Gradus::Done),
},
)
}
#[inline]
pub async fn first(mut self) -> Option<T> {
self.next().await
}
#[inline]
pub async fn last(self) -> Option<T> {
self.fold(None, |_, item| Some(item)).await
}
#[inline]
pub async fn count(self) -> usize {
self.fold(0, |acc, _| acc + 1).await
}
#[inline]
pub async fn any<F>(mut self, f: F) -> bool
where
F: Fn(&T) -> bool + Send,
{
while let Some(item) = self.next().await {
if f(&item) {
return true;
}
}
false
}
#[inline]
pub async fn all<F>(mut self, f: F) -> bool
where
F: Fn(&T) -> bool + Send,
{
while let Some(item) = self.next().await {
if !f(&item) {
return false;
}
}
true
}
#[inline]
pub async fn find<F>(mut self, f: F) -> Option<T>
where
F: Fn(&T) -> bool + Send,
{
while let Some(item) = self.next().await {
if f(&item) {
return Some(item);
}
}
None
}
#[inline]
async fn next(&mut self) -> Option<T> {
use core::future::poll_fn;
poll_fn(|cx| Pin::new(&mut self.inner).poll_next(cx)).await
}
#[inline]
pub async fn for_each<F, Fut>(mut self, f: F)
where
F: Fn(T) -> Fut + Send,
Fut: Future<Output = ()> + Send,
{
while let Some(item) = self.next().await {
f(item).await;
}
}
#[inline(always)]
pub fn flat_map<B, F>(self, f: F) -> Flumen<B>
where
F: Fn(T) -> Flumen<B> + Send + Sync + Unpin + 'static,
B: Send + 'static,
{
Flumen::new(FlatMapStream::new(self.inner, f))
}
#[inline(always)]
pub fn flatten(self) -> Flumen<T::Item>
where
T: Stream + Send + 'static,
T::Item: Send + 'static,
{
Flumen::new(FlattenStream::new(self.inner))
}
}
impl<T> Stream for Flumen<T> {
type Item = T;
#[inline]
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
self.inner.as_mut().poll_next(cx)
}
}
impl<T> core::fmt::Debug for Flumen<T> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("Flumen")
.field("inner", &"<stream>")
.finish()
}
}
struct IterStream<I> {
iter: I,
}
impl<I> IterStream<I> {
#[inline(always)]
fn new(iter: I) -> Self {
IterStream { iter }
}
}
impl<I: Iterator + Unpin> Stream for IterStream<I> {
type Item = I::Item;
#[inline(always)]
fn poll_next(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
Poll::Ready(self.iter.next())
}
}
struct MapStream<S, F> {
stream: S,
f: F,
}
impl<S, F> MapStream<S, F> {
#[inline(always)]
fn new(stream: S, f: F) -> Self {
MapStream { stream, f }
}
}
impl<S, F, B> Stream for MapStream<S, F>
where
S: Stream + Unpin,
F: Fn(S::Item) -> B + Unpin,
{
type Item = B;
#[inline(always)]
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
match Pin::new(&mut self.stream).poll_next(cx) {
Poll::Ready(Some(item)) => Poll::Ready(Some((self.f)(item))),
Poll::Ready(None) => Poll::Ready(None),
Poll::Pending => Poll::Pending,
}
}
}
struct FilterStream<S, F> {
stream: S,
predicate: F,
}
impl<S, F> FilterStream<S, F> {
#[inline(always)]
fn new(stream: S, predicate: F) -> Self {
FilterStream { stream, predicate }
}
}
impl<S, F> Stream for FilterStream<S, F>
where
S: Stream + Unpin,
F: Fn(&S::Item) -> bool + Unpin,
{
type Item = S::Item;
#[inline(always)]
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
loop {
match Pin::new(&mut self.stream).poll_next(cx) {
Poll::Ready(Some(item)) => {
if (self.predicate)(&item) {
return Poll::Ready(Some(item));
}
}
Poll::Ready(None) => return Poll::Ready(None),
Poll::Pending => return Poll::Pending,
}
}
}
}
struct FilterMapStream<S, F> {
stream: S,
f: F,
}
impl<S, F> FilterMapStream<S, F> {
#[inline(always)]
fn new(stream: S, f: F) -> Self {
FilterMapStream { stream, f }
}
}
impl<S, F, B> Stream for FilterMapStream<S, F>
where
S: Stream + Unpin,
F: Fn(S::Item) -> Option<B> + Unpin,
{
type Item = B;
#[inline(always)]
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
loop {
match Pin::new(&mut self.stream).poll_next(cx) {
Poll::Ready(Some(item)) => {
if let Some(mapped) = (self.f)(item) {
return Poll::Ready(Some(mapped));
}
}
Poll::Ready(None) => return Poll::Ready(None),
Poll::Pending => return Poll::Pending,
}
}
}
}
struct TakeStream<S> {
stream: S,
remaining: usize,
}
impl<S> TakeStream<S> {
#[inline(always)]
fn new(stream: S, n: usize) -> Self {
TakeStream {
stream,
remaining: n,
}
}
}
impl<S: Stream + Unpin> Stream for TakeStream<S> {
type Item = S::Item;
#[inline(always)]
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
if self.remaining == 0 {
return Poll::Ready(None);
}
match Pin::new(&mut self.stream).poll_next(cx) {
Poll::Ready(Some(item)) => {
self.remaining -= 1;
Poll::Ready(Some(item))
}
other => other,
}
}
}
struct SkipStream<S> {
stream: S,
remaining: usize,
}
impl<S> SkipStream<S> {
#[inline(always)]
fn new(stream: S, n: usize) -> Self {
SkipStream {
stream,
remaining: n,
}
}
}
impl<S: Stream + Unpin> Stream for SkipStream<S> {
type Item = S::Item;
#[inline(always)]
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
while self.remaining > 0 {
match Pin::new(&mut self.stream).poll_next(cx) {
Poll::Ready(Some(_)) => {
self.remaining -= 1;
}
Poll::Ready(None) => return Poll::Ready(None),
Poll::Pending => return Poll::Pending,
}
}
Pin::new(&mut self.stream).poll_next(cx)
}
}
struct TakeWhileStream<S, F> {
stream: S,
predicate: F,
done: bool,
}
impl<S, F> TakeWhileStream<S, F> {
#[inline(always)]
fn new(stream: S, predicate: F) -> Self {
TakeWhileStream {
stream,
predicate,
done: false,
}
}
}
impl<S, F> Stream for TakeWhileStream<S, F>
where
S: Stream + Unpin,
F: Fn(&S::Item) -> bool + Unpin,
{
type Item = S::Item;
#[inline(always)]
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
if self.done {
return Poll::Ready(None);
}
match Pin::new(&mut self.stream).poll_next(cx) {
Poll::Ready(Some(item)) => {
if (self.predicate)(&item) {
Poll::Ready(Some(item))
} else {
self.done = true;
Poll::Ready(None)
}
}
other => other,
}
}
}
struct SkipWhileStream<S, F> {
stream: S,
predicate: Option<F>,
}
impl<S, F> SkipWhileStream<S, F> {
#[inline(always)]
fn new(stream: S, predicate: F) -> Self {
SkipWhileStream {
stream,
predicate: Some(predicate),
}
}
}
impl<S, F> Stream for SkipWhileStream<S, F>
where
S: Stream + Unpin,
F: Fn(&S::Item) -> bool + Unpin,
{
type Item = S::Item;
#[inline(always)]
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
loop {
match Pin::new(&mut self.stream).poll_next(cx) {
Poll::Ready(Some(item)) => {
if let Some(ref predicate) = self.predicate {
if predicate(&item) {
continue;
}
self.predicate = None;
}
return Poll::Ready(Some(item));
}
other => return other,
}
}
}
}
struct ChainStream<S1, S2> {
first: Option<S1>,
second: S2,
}
impl<S1, S2> ChainStream<S1, S2> {
#[inline(always)]
fn new(first: S1, second: S2) -> Self {
ChainStream {
first: Some(first),
second,
}
}
}
impl<S1, S2> Stream for ChainStream<S1, S2>
where
S1: Stream + Unpin,
S2: Stream<Item = S1::Item> + Unpin,
{
type Item = S1::Item;
#[inline(always)]
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
if let Some(ref mut first) = self.first {
match Pin::new(first).poll_next(cx) {
Poll::Ready(Some(item)) => return Poll::Ready(Some(item)),
Poll::Ready(None) => {
self.first = None;
}
Poll::Pending => return Poll::Pending,
}
}
Pin::new(&mut self.second).poll_next(cx)
}
}
struct ZipStream<S1: Stream, S2> {
stream1: S1,
stream2: S2,
stash: Option<S1::Item>,
}
impl<S1: Stream, S2> ZipStream<S1, S2> {
#[inline(always)]
fn new(stream1: S1, stream2: S2) -> Self {
ZipStream {
stream1,
stream2,
stash: None,
}
}
}
impl<S1: Stream + Unpin, S2: Unpin> Unpin for ZipStream<S1, S2> {}
impl<S1, S2> Stream for ZipStream<S1, S2>
where
S1: Stream + Unpin,
S2: Stream + Unpin,
{
type Item = (S1::Item, S2::Item);
#[inline(always)]
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
let item1 = match self.stash.take() {
Some(item) => item,
None => match Pin::new(&mut self.stream1).poll_next(cx) {
Poll::Ready(Some(item)) => item,
Poll::Ready(None) => return Poll::Ready(None),
Poll::Pending => return Poll::Pending,
},
};
let item2 = match Pin::new(&mut self.stream2).poll_next(cx) {
Poll::Ready(Some(item)) => item,
Poll::Ready(None) => return Poll::Ready(None),
Poll::Pending => {
self.stash = Some(item1);
return Poll::Pending;
}
};
Poll::Ready(Some((item1, item2)))
}
}
struct EnumerateStream<S> {
stream: S,
index: usize,
}
impl<S> EnumerateStream<S> {
#[inline(always)]
fn new(stream: S) -> Self {
EnumerateStream { stream, index: 0 }
}
}
impl<S: Stream + Unpin> Stream for EnumerateStream<S> {
type Item = (usize, S::Item);
#[inline(always)]
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
match Pin::new(&mut self.stream).poll_next(cx) {
Poll::Ready(Some(item)) => {
let idx = self.index;
self.index += 1;
Poll::Ready(Some((idx, item)))
}
Poll::Ready(None) => Poll::Ready(None),
Poll::Pending => Poll::Pending,
}
}
}
struct FlatMapStream<S, F, B>
where
S: Stream,
F: Fn(S::Item) -> Flumen<B>,
{
stream: S,
f: F,
current: Option<BoxStream<B>>,
}
impl<S, F, B> FlatMapStream<S, F, B>
where
S: Stream,
F: Fn(S::Item) -> Flumen<B>,
{
#[inline(always)]
fn new(stream: S, f: F) -> Self {
FlatMapStream {
stream,
f,
current: None,
}
}
}
impl<S, F, B> Stream for FlatMapStream<S, F, B>
where
S: Stream + Unpin,
F: Fn(S::Item) -> Flumen<B> + Unpin,
B: Send + 'static,
{
type Item = B;
#[inline(always)]
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
loop {
if let Some(ref mut inner) = self.current {
match inner.as_mut().poll_next(cx) {
Poll::Ready(Some(item)) => return Poll::Ready(Some(item)),
Poll::Ready(None) => {
self.current = None;
}
Poll::Pending => return Poll::Pending,
}
}
match Pin::new(&mut self.stream).poll_next(cx) {
Poll::Ready(Some(item)) => {
let flumen = (self.f)(item);
self.current = Some(flumen.inner);
}
Poll::Ready(None) => return Poll::Ready(None),
Poll::Pending => return Poll::Pending,
}
}
}
}
struct ScanStream<S, B, F> {
stream: S,
acc: Option<B>,
f: F,
}
impl<S, B, F> ScanStream<S, B, F> {
#[inline]
fn new(stream: S, init: B, f: F) -> Self {
ScanStream {
stream,
acc: Some(init),
f,
}
}
}
impl<S, B, F> Stream for ScanStream<S, B, F>
where
S: Stream + Unpin,
B: Clone + Unpin,
F: Fn(B, S::Item) -> B + Unpin,
{
type Item = B;
#[inline]
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
match Pin::new(&mut self.stream).poll_next(cx) {
Poll::Ready(Some(item)) => {
let prev = self
.acc
.take()
.expect("ScanStream::acc is Some between polls");
let new_acc = (self.f)(prev, item);
self.acc = Some(new_acc.clone());
Poll::Ready(Some(new_acc))
}
Poll::Ready(None) => Poll::Ready(None),
Poll::Pending => Poll::Pending,
}
}
}
struct ScanWithStream<S, St, F> {
stream: S,
state: St,
f: F,
done: bool,
}
impl<S, St, F> ScanWithStream<S, St, F> {
#[inline(always)]
fn new(stream: S, init: St, f: F) -> Self {
ScanWithStream {
stream,
state: init,
f,
done: false,
}
}
}
impl<S, St, B, F> Stream for ScanWithStream<S, St, F>
where
S: Stream + Unpin,
St: Unpin,
F: FnMut(&mut St, S::Item) -> Option<B> + Unpin,
{
type Item = B;
#[inline(always)]
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
if self.done {
return Poll::Ready(None);
}
match Pin::new(&mut self.stream).poll_next(cx) {
Poll::Ready(Some(item)) => {
let this = self.get_mut();
if let Some(output) = (this.f)(&mut this.state, item) {
Poll::Ready(Some(output))
} else {
this.done = true;
Poll::Ready(None)
}
}
Poll::Ready(None) => Poll::Ready(None),
Poll::Pending => Poll::Pending,
}
}
}
struct ChunksStream<S: Stream> {
stream: S,
size: usize,
buffer: Vec<S::Item>,
done: bool,
}
impl<S: Stream> ChunksStream<S> {
#[inline(always)]
fn new(stream: S, size: usize) -> Self {
ChunksStream {
stream,
size,
buffer: Vec::with_capacity(size),
done: false,
}
}
}
impl<S> Stream for ChunksStream<S>
where
S: Stream + Unpin,
S::Item: Unpin,
{
type Item = Vec<S::Item>;
#[inline(always)]
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
let this = self.get_mut();
if this.done {
return Poll::Ready(None);
}
loop {
match Pin::new(&mut this.stream).poll_next(cx) {
Poll::Ready(Some(item)) => {
this.buffer.push(item);
if this.buffer.len() >= this.size {
let chunk =
core::mem::replace(&mut this.buffer, Vec::with_capacity(this.size));
return Poll::Ready(Some(chunk));
}
}
Poll::Ready(None) => {
this.done = true;
if this.buffer.is_empty() {
return Poll::Ready(None);
}
let final_chunk = core::mem::take(&mut this.buffer);
return Poll::Ready(Some(final_chunk));
}
Poll::Pending => return Poll::Pending,
}
}
}
}
struct FlattenStream<S>
where
S: Stream,
S::Item: Stream,
{
stream: S,
current: Option<Pin<Box<S::Item>>>,
}
impl<S> FlattenStream<S>
where
S: Stream,
S::Item: Stream,
{
#[inline(always)]
fn new(stream: S) -> Self {
FlattenStream {
stream,
current: None,
}
}
}
impl<S> Stream for FlattenStream<S>
where
S: Stream + Unpin,
S::Item: Stream + Send + 'static,
{
type Item = <S::Item as Stream>::Item;
#[inline(always)]
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
loop {
if let Some(ref mut inner) = self.current {
match inner.as_mut().poll_next(cx) {
Poll::Ready(Some(item)) => return Poll::Ready(Some(item)),
Poll::Ready(None) => {
self.current = None;
}
Poll::Pending => return Poll::Pending,
}
}
match Pin::new(&mut self.stream).poll_next(cx) {
Poll::Ready(Some(inner_stream)) => {
self.current = Some(Box::pin(inner_stream));
}
Poll::Ready(None) => return Poll::Ready(None),
Poll::Pending => return Poll::Pending,
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use alloc::vec;
#[test]
fn test_flumen_creation() {
let _stream: Flumen<i32> = Flumen::from_iterator(vec![1, 2, 3]);
}
#[test]
fn test_flumen_once() {
let _stream: Flumen<i32> = Flumen::once(42);
}
#[test]
fn test_flumen_empty() {
let _stream: Flumen<i32> = Flumen::empty();
}
#[test]
fn test_flumen_debug() {
let stream: Flumen<i32> = Flumen::from_iterator(vec![1, 2, 3]);
let debug = alloc::format!("{stream:?}");
assert!(debug.contains("Flumen"));
}
struct PendingOnce<S> {
inner: S,
pended: bool,
}
impl<S: Stream + Unpin> Stream for PendingOnce<S> {
type Item = S::Item;
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
if !self.pended {
self.pended = true;
cx.waker().wake_by_ref();
return Poll::Pending;
}
self.pended = false;
Pin::new(&mut self.inner).poll_next(cx)
}
}
fn drive<F: Future>(fut: F) -> F::Output {
let mut fut = core::pin::pin!(fut);
let mut cx = Context::from_waker(core::task::Waker::noop());
loop {
if let Poll::Ready(out) = fut.as_mut().poll(&mut cx) {
return out;
}
}
}
#[test]
fn test_zip_keeps_items_when_second_stream_pending() {
let fast = Flumen::from_iterator(vec![1, 2, 3]);
let slow = Flumen::new(PendingOnce {
inner: IterStream::new(vec![10, 20, 30].into_iter()),
pended: false,
});
let pairs = drive(fast.zip(slow).collect_vec());
assert_eq!(pairs, vec![(1, 10), (2, 20), (3, 30)]);
}
}