more_itertools/itertools/
sum.rs

1
2
3#[macro_export]
4macro_rules! sum {
5    ($arg:ty,  $iter:expr, $init:expr) => {
6        {
7            let mut overflow = false;
8            let mut upstream_error = false;
9            let mut the_upstream_error = Err(error::any_error(error::Kind::None, "none error".to_string()));
10            let mut sum0: $arg = $init;
11
12            let mut _next = $iter.next();
13            while !_next.is_none() {
14                match _next {
15                    None=>{
16                        break;
17                    }
18                    Some(v) => {
19                        if !v.is_ok() {
20                            upstream_error = true;
21                            the_upstream_error = v;
22                            break;
23                        } else {
24                            let add_result = <$arg>::overflowing_add(sum0, v.ok().unwrap());
25                        
26                            if add_result.1 {
27                                overflow = true;
28                                break;
29                            } else {
30                                sum0 = add_result.0;
31                                _next = $iter.next();
32                                continue;
33                            }
34                        }
35                    }
36                }
37            }
38
39            if upstream_error {
40                the_upstream_error
41            } else if overflow {
42                Err(error::any_error(error::Kind::OverflowError, "Add overflow.".to_string()))
43            } else {
44                Ok(sum0)
45            }
46        }
47    };
48}
49
50pub(crate) use sum;
51
52
53#[cfg(test)]
54mod tests {
55    use crate::error;
56    use crate::itertools::iter::iter_from_vec;
57    use crate::itertools::map::map2;
58    use crate::utils::generate_okok_iterator;
59
60    //use super::*;
61
62    #[test]
63    fn test1() {
64        let v = vec![Ok(1usize),Ok(2),Ok(3)];
65        let mut iter: Box<dyn Iterator<Item = Result<usize, error::Error>>> = iter_from_vec(v);
66        let ret = sum!(usize, iter, 0);
67        assert_eq!(Ok(6), ret);
68
69        let v = Vec::<Result<usize,error::Error>>::new();
70        let mut iter = iter_from_vec(v);
71        let ret = sum!(usize, iter, 0);
72        assert_eq!(Ok(0), ret);
73
74        let v = vec![Ok(usize::MAX),Ok(2),Ok(3)];
75        let mut iter = iter_from_vec(v);
76        let ret = sum!(usize, iter, 0);
77        assert_eq!(error::Kind::OverflowError, ret.err().unwrap().kind());
78
79        let v1 = generate_okok_iterator(vec![2, 3, usize::MAX]);
80        let v2 = generate_okok_iterator(vec![1, 2, 3]);
81        let mut iter = map2(v1, v2, |x, y| {
82            let ret = x.overflowing_mul(*y);
83                if ret.1 {
84                    return Err(error::any_error(error::Kind::OverflowError, "multiple overflow.".to_string()));
85                } else {
86                    return Ok(ret.0);
87                }
88        });
89        let ret = sum!(usize, iter, 0);
90        assert!(ret.is_err());
91        assert!(ret.err().unwrap().message().unwrap().contains("multiple overflow"));
92
93    }
94}