async_std/stream/
sum.rs

1use std::future::Future;
2use std::pin::Pin;
3
4use crate::stream::Stream;
5
6/// Trait to represent types that can be created by summing up a stream.
7///
8/// This trait is used to implement the [`sum`] method on streams. Types which
9/// implement the trait can be generated by the [`sum`] method. Like
10/// [`FromStream`] this trait should rarely be called directly and instead
11/// interacted with through [`Stream::sum`].
12///
13/// [`sum`]: trait.Sum.html#tymethod.sum
14/// [`FromStream`]: trait.FromStream.html
15/// [`Stream::sum`]: trait.Stream.html#method.sum
16#[cfg(feature = "unstable")]
17#[cfg_attr(feature = "docs", doc(cfg(unstable)))]
18pub trait Sum<A = Self>: Sized {
19    /// Method which takes a stream and generates `Self` from the elements by
20    /// "summing up" the items.
21    fn sum<'a, S>(stream: S) -> Pin<Box<dyn Future<Output = Self> + 'a>>
22    where
23        S: Stream<Item = A> + 'a;
24}
25
26use crate::stream::stream::StreamExt;
27use core::num::Wrapping;
28use core::ops::Add;
29
30macro_rules! integer_sum {
31    (@impls $zero: expr, $($a:ty)*) => ($(
32        impl Sum for $a {
33            fn sum<'a, S>(stream: S) -> Pin<Box<dyn Future<Output = Self>+ 'a>>
34            where
35                S: Stream<Item = $a> + 'a,
36            {
37                Box::pin(async move { stream.fold($zero, Add::add).await } )
38            }
39        }
40        impl<'a> Sum<&'a $a> for $a {
41            fn sum<'b, S>(stream: S) -> Pin<Box<dyn Future<Output = Self> + 'b>>
42            where
43                S: Stream<Item = &'a $a> + 'b,
44            {
45                Box::pin(async move { stream.fold($zero, Add::add).await } )
46            }
47        }
48    )*);
49    ($($a:ty)*) => (
50        integer_sum!(@impls 0, $($a)*);
51        integer_sum!(@impls Wrapping(0), $(Wrapping<$a>)*);
52    );
53}
54
55macro_rules! float_sum {
56    ($($a:ty)*) => ($(
57        impl Sum for $a {
58            fn sum<'a, S>(stream: S) -> Pin<Box<dyn Future<Output = Self> + 'a>>
59                where S: Stream<Item = $a> + 'a,
60            {
61                Box::pin(async move { stream.fold(0.0, |a, b| a + b).await } )
62            }
63        }
64        impl<'a> Sum<&'a $a> for $a {
65            fn sum<'b, S>(stream: S) -> Pin<Box<dyn Future<Output = Self> + 'b>>
66                where S: Stream<Item = &'a $a> + 'b,
67            {
68                Box::pin(async move { stream.fold(0.0, |a, b| a + b).await } )
69            }
70        }
71    )*);
72    ($($a:ty)*) => (
73        float_sum!(@impls 0.0, $($a)*);
74        float_sum!(@impls Wrapping(0.0), $(Wrapping<$a>)*);
75    );
76}
77
78integer_sum! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize }
79float_sum! { f32 f64 }