itertools/
size_hint.rs

1//! Arithmetic on `Iterator.size_hint()` values.
2//!
3
4use std::cmp;
5use std::usize;
6
7/// `SizeHint` is the return type of `Iterator::size_hint()`.
8pub type SizeHint = (usize, Option<usize>);
9
10/// Add `SizeHint` correctly.
11#[inline]
12pub fn add(a: SizeHint, b: SizeHint) -> SizeHint {
13    let min = a.0.saturating_add(b.0);
14    let max = match (a.1, b.1) {
15        (Some(x), Some(y)) => x.checked_add(y),
16        _ => None,
17    };
18
19    (min, max)
20}
21
22/// Add `x` correctly to a `SizeHint`.
23#[inline]
24pub fn add_scalar(sh: SizeHint, x: usize) -> SizeHint {
25    let (mut low, mut hi) = sh;
26    low = low.saturating_add(x);
27    hi = hi.and_then(|elt| elt.checked_add(x));
28    (low, hi)
29}
30
31/// Subtract `x` correctly from a `SizeHint`.
32#[inline]
33pub fn sub_scalar(sh: SizeHint, x: usize) -> SizeHint {
34    let (mut low, mut hi) = sh;
35    low = low.saturating_sub(x);
36    hi = hi.map(|elt| elt.saturating_sub(x));
37    (low, hi)
38}
39
40/// Multiply `SizeHint` correctly
41#[inline]
42pub fn mul(a: SizeHint, b: SizeHint) -> SizeHint {
43    let low = a.0.saturating_mul(b.0);
44    let hi = match (a.1, b.1) {
45        (Some(x), Some(y)) => x.checked_mul(y),
46        (Some(0), None) | (None, Some(0)) => Some(0),
47        _ => None,
48    };
49    (low, hi)
50}
51
52/// Multiply `x` correctly with a `SizeHint`.
53#[inline]
54pub fn mul_scalar(sh: SizeHint, x: usize) -> SizeHint {
55    let (mut low, mut hi) = sh;
56    low = low.saturating_mul(x);
57    hi = hi.and_then(|elt| elt.checked_mul(x));
58    (low, hi)
59}
60
61/// Return the maximum
62#[inline]
63pub fn max(a: SizeHint, b: SizeHint) -> SizeHint {
64    let (a_lower, a_upper) = a;
65    let (b_lower, b_upper) = b;
66
67    let lower = cmp::max(a_lower, b_lower);
68
69    let upper = match (a_upper, b_upper) {
70        (Some(x), Some(y)) => Some(cmp::max(x, y)),
71        _ => None,
72    };
73
74    (lower, upper)
75}
76
77/// Return the minimum
78#[inline]
79pub fn min(a: SizeHint, b: SizeHint) -> SizeHint {
80    let (a_lower, a_upper) = a;
81    let (b_lower, b_upper) = b;
82    let lower = cmp::min(a_lower, b_lower);
83    let upper = match (a_upper, b_upper) {
84        (Some(u1), Some(u2)) => Some(cmp::min(u1, u2)),
85        _ => a_upper.or(b_upper),
86    };
87    (lower, upper)
88}
89
90#[test]
91fn mul_size_hints() {
92    assert_eq!(mul((3, Some(4)), (3, Some(4))), (9, Some(16)));
93    assert_eq!(mul((3, Some(4)), (usize::MAX, None)), (usize::MAX, None));
94    assert_eq!(mul((3, None), (0, Some(0))), (0, Some(0)));
95}