2
0
Fork 1
mirror of https://github.com/async-rs/async-std.git synced 2025-01-31 01:35:33 +00:00
async-std/src/stream/sum.rs
Kyle Tomsic e26eb7a719 Add Stream::sum() and Stream::product() implementations
These are the stream equivalents to `std::iter::Iterator::sum()` and
`std::iter::Iterator::product()`.

Note that this changeset tweaks the `Stream::Sum` and `Stream::Product`
traits a little: rather than returning a generic future `F`, they return
a pinned, boxed, `Future` trait object now. This is in line with other
traits that return a future, e.g. `FromStream`.
2019-10-22 20:30:27 -04:00

79 lines
2.6 KiB
Rust

use std::pin::Pin;
use crate::future::Future;
use crate::stream::Stream;
/// Trait to represent types that can be created by summing up a stream.
///
/// This trait is used to implement the [`sum`] method on streams. Types which
/// implement the trait can be generated by the [`sum`] method. Like
/// [`FromStream`] this trait should rarely be called directly and instead
/// interacted with through [`Stream::sum`].
///
/// [`sum`]: trait.Sum.html#tymethod.sum
/// [`FromStream`]: trait.FromStream.html
/// [`Stream::sum`]: trait.Stream.html#method.sum
#[cfg(feature = "unstable")]
#[cfg_attr(feature = "docs", doc(cfg(unstable)))]
pub trait Sum<A = Self>: Sized {
/// Method which takes a stream and generates `Self` from the elements by
/// "summing up" the items.
fn sum<'a, S>(stream: S) -> Pin<Box<dyn Future<Output = Self> + 'a>>
where
S: Stream<Item = A> + 'a;
}
use core::ops::Add;
use core::num::Wrapping;
use crate::stream::stream::StreamExt;
macro_rules! integer_sum {
(@impls $zero: expr, $($a:ty)*) => ($(
impl Sum for $a {
fn sum<'a, S>(stream: S) -> Pin<Box<dyn Future<Output = Self>+ 'a>>
where
S: Stream<Item = $a> + 'a,
{
Box::pin(async move { stream.fold($zero, Add::add).await } )
}
}
impl<'a> Sum<&'a $a> for $a {
fn sum<'b, S>(stream: S) -> Pin<Box<dyn Future<Output = Self> + 'b>>
where
S: Stream<Item = &'a $a> + 'b,
{
Box::pin(async move { stream.fold($zero, Add::add).await } )
}
}
)*);
($($a:ty)*) => (
integer_sum!(@impls 0, $($a)*);
integer_sum!(@impls Wrapping(0), $(Wrapping<$a>)*);
);
}
macro_rules! float_sum {
($($a:ty)*) => ($(
impl Sum for $a {
fn sum<'a, S>(stream: S) -> Pin<Box<dyn Future<Output = Self> + 'a>>
where S: Stream<Item = $a> + 'a,
{
Box::pin(async move { stream.fold(0.0, |a, b| a + b).await } )
}
}
impl<'a> Sum<&'a $a> for $a {
fn sum<'b, S>(stream: S) -> Pin<Box<dyn Future<Output = Self> + 'b>>
where S: Stream<Item = &'a $a> + 'b,
{
Box::pin(async move { stream.fold(0.0, |a, b| a + b).await } )
}
}
)*);
($($a:ty)*) => (
float_sum!(@impls 0.0, $($a)*);
float_sum!(@impls Wrapping(0.0), $(Wrapping<$a>)*);
);
}
integer_sum!{ i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize }
float_sum!{ f32 f64 }