use core::pin::Pin; use core::future::Future; use crate::stream::Stream; /// Trait to represent types that can be created by multiplying the elements of a stream. /// /// This trait is used to implement the [`product`] method on streams. Types which /// implement the trait can be generated by the [`product`] method. Like /// [`FromStream`] this trait should rarely be called directly and instead /// interacted with through [`Stream::product`]. /// /// [`product`]: trait.Product.html#tymethod.product /// [`FromStream`]: trait.FromStream.html /// [`Stream::product`]: trait.Stream.html#method.product #[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] pub trait Product: Sized { /// Method which takes a stream and generates `Self` from the elements by /// multiplying the items. fn product<'a, S>(stream: S) -> Pin + 'a>> where S: Stream + 'a; } use core::ops::Mul; use core::num::Wrapping; use crate::stream::stream::StreamExt; macro_rules! num_product { ($one:expr, $($a:ty)*) => ($( impl Product for $a { fn product<'a, S>(stream: S) -> Pin+ 'a>> where S: Stream + 'a, { Box::pin(async move { stream.fold($one, Mul::mul).await } ) } } impl<'a> Product<&'a $a> for $a { fn product<'b, S>(stream: S) -> Pin + 'b>> where S: Stream + 'b, { Box::pin(async move { stream.fold($one, Mul::mul).await } ) } } )*); } macro_rules! integer_product { ($($a:ty)*) => ( num_product!(1, $($a)*); num_product!(Wrapping(1), $(Wrapping<$a>)*); ); } macro_rules! float_product { ($($a:ty)*) => ( num_product!(1.0, $($a)*); ); } integer_product!{ i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize } float_product!{ f32 f64 }