use crate::ops::{Mul, Add}; use crate::num::Wrapping; /// Trait to represent types that can be created by summing up an iterator. /// /// This trait is used to implement the [`sum`] method on iterators. Types which /// implement the trait can be generated by the [`sum`] method. Like /// [`FromIterator`] this trait should rarely be called directly and instead /// interacted with through [`Iterator::sum`]. /// /// [`sum`]: ../../std/iter/trait.Sum.html#tymethod.sum /// [`FromIterator`]: ../../std/iter/trait.FromIterator.html /// [`Iterator::sum`]: ../../std/iter/trait.Iterator.html#method.sum #[stable(feature = "iter_arith_traits", since = "1.12.0")] pub trait Sum: Sized { /// Method which takes an iterator and generates `Self` from the elements by /// "summing up" the items. #[stable(feature = "iter_arith_traits", since = "1.12.0")] fn sum>(iter: I) -> Self; } /// Trait to represent types that can be created by multiplying elements of an /// iterator. /// /// This trait is used to implement the [`product`] method on iterators. Types /// which implement the trait can be generated by the [`product`] method. Like /// [`FromIterator`] this trait should rarely be called directly and instead /// interacted with through [`Iterator::product`]. /// /// [`product`]: ../../std/iter/trait.Product.html#tymethod.product /// [`FromIterator`]: ../../std/iter/trait.FromIterator.html /// [`Iterator::product`]: ../../std/iter/trait.Iterator.html#method.product #[stable(feature = "iter_arith_traits", since = "1.12.0")] pub trait Product: Sized { /// Method which takes an iterator and generates `Self` from the elements by /// multiplying the items. #[stable(feature = "iter_arith_traits", since = "1.12.0")] fn product>(iter: I) -> Self; } // N.B., explicitly use Add and Mul here to inherit overflow checks macro_rules! integer_sum_product { (@impls $zero:expr, $one:expr, #[$attr:meta], $($a:ty)*) => ($( #[$attr] impl Sum for $a { fn sum>(iter: I) -> $a { iter.fold($zero, Add::add) } } #[$attr] impl Product for $a { fn product>(iter: I) -> $a { iter.fold($one, Mul::mul) } } #[$attr] impl<'a> Sum<&'a $a> for $a { fn sum>(iter: I) -> $a { iter.fold($zero, Add::add) } } #[$attr] impl<'a> Product<&'a $a> for $a { fn product>(iter: I) -> $a { iter.fold($one, Mul::mul) } } )*); ($($a:ty)*) => ( integer_sum_product!(@impls 0, 1, #[stable(feature = "iter_arith_traits", since = "1.12.0")], $($a)+); integer_sum_product!(@impls Wrapping(0), Wrapping(1), #[stable(feature = "wrapping_iter_arith", since = "1.14.0")], $(Wrapping<$a>)+); ); } macro_rules! float_sum_product { ($($a:ident)*) => ($( #[stable(feature = "iter_arith_traits", since = "1.12.0")] impl Sum for $a { fn sum>(iter: I) -> $a { iter.fold(0.0, |a, b| a + b) } } #[stable(feature = "iter_arith_traits", since = "1.12.0")] impl Product for $a { fn product>(iter: I) -> $a { iter.fold(1.0, |a, b| a * b) } } #[stable(feature = "iter_arith_traits", since = "1.12.0")] impl<'a> Sum<&'a $a> for $a { fn sum>(iter: I) -> $a { iter.fold(0.0, |a, b| a + *b) } } #[stable(feature = "iter_arith_traits", since = "1.12.0")] impl<'a> Product<&'a $a> for $a { fn product>(iter: I) -> $a { iter.fold(1.0, |a, b| a * *b) } } )*) } integer_sum_product! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize } float_sum_product! { f32 f64 } /// An iterator adapter that produces output as long as the underlying /// iterator produces `Result::Ok` values. /// /// If an error is encountered, the iterator stops and the error is /// stored. The error may be recovered later via `reconstruct`. struct ResultShunt { iter: I, error: Option, } impl ResultShunt where I: Iterator> { /// Process the given iterator as if it yielded a `T` instead of a /// `Result`. Any errors will stop the inner iterator and /// the overall result will be an error. pub fn process(iter: I, mut f: F) -> Result where F: FnMut(&mut Self) -> U { let mut shunt = ResultShunt::new(iter); let value = f(shunt.by_ref()); shunt.reconstruct(value) } fn new(iter: I) -> Self { ResultShunt { iter, error: None, } } /// Consume the adapter and rebuild a `Result` value. This should /// *always* be called, otherwise any potential error would be /// lost. fn reconstruct(self, val: U) -> Result { match self.error { None => Ok(val), Some(e) => Err(e), } } } impl Iterator for ResultShunt where I: Iterator> { type Item = T; fn next(&mut self) -> Option { match self.iter.next() { Some(Ok(v)) => Some(v), Some(Err(e)) => { self.error = Some(e); None } None => None, } } fn size_hint(&self) -> (usize, Option) { if self.error.is_some() { (0, Some(0)) } else { let (_, upper) = self.iter.size_hint(); (0, upper) } } } #[stable(feature = "iter_arith_traits_result", since="1.16.0")] impl Sum> for Result where T: Sum, { /// Takes each element in the `Iterator`: if it is an `Err`, no further /// elements are taken, and the `Err` is returned. Should no `Err` occur, /// the sum of all elements is returned. /// /// # Examples /// /// This sums up every integer in a vector, rejecting the sum if a negative /// element is encountered: /// /// ``` /// let v = vec![1, 2]; /// let res: Result = v.iter().map(|&x: &i32| /// if x < 0 { Err("Negative element found") } /// else { Ok(x) } /// ).sum(); /// assert_eq!(res, Ok(3)); /// ``` fn sum(iter: I) -> Result where I: Iterator>, { ResultShunt::process(iter, |i| i.sum()) } } #[stable(feature = "iter_arith_traits_result", since="1.16.0")] impl Product> for Result where T: Product, { /// Takes each element in the `Iterator`: if it is an `Err`, no further /// elements are taken, and the `Err` is returned. Should no `Err` occur, /// the product of all elements is returned. fn product(iter: I) -> Result where I: Iterator>, { ResultShunt::process(iter, |i| i.product()) } }