stream_reduce/
lib.rs

1//! This crate gives Streams a `reduce` function that is similar to
2//! [`fold`](https://docs.rs/futures/0.3.4/futures/stream/trait.StreamExt.html#method.fold)
3//! but without an initial value. The function returns a [`Future`](core::future::Future)
4//! containing `None` if the stream is empty and `Some(value)` otherwise.
5//!
6//! Based on David Tolnay's [`reduce`](https://docs.rs/reduce/0.1.2/reduce/) crate for iterators.
7//! 
8//! # Examples
9//! ```
10//! use stream_reduce::Reduce;
11//! use futures::stream;
12//!
13//! # futures::executor::block_on(
14//! async {
15//!     // Reduce a non-empty stream into Some(value)
16//!     let v = vec![1usize, 2, 3, 4, 5];
17//!     let sum = stream::iter(v).reduce(|a, b| async move { a + b }).await;
18//!     assert_eq!(Some(15), sum);
19//!
20//!     // Reduce an empty stream into None
21//!     let v = Vec::<usize>::new();
22//!     let product = stream::iter(v).reduce(|a, b| async move { a * b }).await;
23//!     assert_eq!(None, product);
24//! }
25//! # )
26//! ```
27
28#![no_std]
29
30use core::future::Future;
31use futures::Stream;
32
33mod reducer;
34pub use reducer::Reducer;
35
36pub trait Reduce<T>: Stream {
37    fn reduce<F, Fut>(self, f: F) -> Reducer<Self, T, F, Fut>
38    where
39        Self: Sized,
40        F: FnMut(T, Self::Item) -> Fut,
41        Fut: Future<Output = T>,
42    {
43        Reducer::new(self, f)
44    }
45}
46
47impl<S, T> Reduce<T> for S where S: Stream<Item = T> {}