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

#![no_std]

use core::future::Future;
use futures::Stream;

mod reducer;
pub use reducer::Reducer;

pub trait Reduce<T>: Stream {
    fn reduce<F, Fut>(self, f: F) -> Reducer<Self, T, F, Fut>
    where
        Self: Sized,
        F: FnMut(T, Self::Item) -> Fut,
        Fut: Future<Output = T>,
    {
        Reducer::new(self, f)
    }
}

impl<S, T> Reduce<T> for S where S: Stream<Item = T> {}