itertools/
size_hint.rs

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