Skip to main content

itertools/
size_hint.rs

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