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> {}