itertools/
size_hint.rs

1//! Arithmetic on **Iterator** *.size_hint()* values.
2//!
3
4use std::usize;
5use std::cmp;
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.checked_add(b.0).unwrap_or(usize::MAX);
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/// Sbb **x** correctly to a **SizeHint**.
32#[inline]
33#[allow(dead_code)]
34pub fn sub_scalar(sh: SizeHint, x: usize) -> SizeHint {
35    let (mut low, mut hi) = sh;
36    low = low.saturating_sub(x);
37    hi = hi.map(|elt| elt.saturating_sub(x));
38    (low, hi)
39}
40
41
42/// Multiply **SizeHint** correctly
43///
44/// ```ignore
45/// use std::usize;
46/// use itertools::size_hint;
47///
48/// assert_eq!(size_hint::mul((3, Some(4)), (3, Some(4))),
49///            (9, Some(16)));
50///
51/// assert_eq!(size_hint::mul((3, Some(4)), (usize::MAX, None)),
52///            (usize::MAX, None));
53///
54/// assert_eq!(size_hint::mul((3, None), (0, Some(0))),
55///            (0, Some(0)));
56/// ```
57#[inline]
58pub fn mul(a: SizeHint, b: SizeHint) -> SizeHint {
59    let low = a.0.checked_mul(b.0).unwrap_or(usize::MAX);
60    let hi = match (a.1, b.1) {
61        (Some(x), Some(y)) => x.checked_mul(y),
62        (Some(0), None) | (None, Some(0)) => Some(0),
63        _ => None,
64    };
65    (low, hi)
66}
67
68/// Multiply **x** correctly with a **SizeHint**.
69#[inline]
70pub fn mul_scalar(sh: SizeHint, x: usize) -> SizeHint {
71    let (mut low, mut hi) = sh;
72    low = low.saturating_mul(x);
73    hi = hi.and_then(|elt| elt.checked_mul(x));
74    (low, hi)
75}
76
77/// Return the maximum
78#[inline]
79pub fn max(a: SizeHint, b: SizeHint) -> SizeHint {
80    let (a_lower, a_upper) = a;
81    let (b_lower, b_upper) = b;
82
83    let lower = cmp::max(a_lower, b_lower);
84
85    let upper = match (a_upper, b_upper) {
86        (Some(x), Some(y)) => Some(cmp::max(x, y)),
87        _ => None,
88    };
89
90    (lower, upper)
91}
92
93/// Return the minimum
94#[inline]
95pub fn min(a: SizeHint, b: SizeHint) -> SizeHint {
96    let (a_lower, a_upper) = a;
97    let (b_lower, b_upper) = b;
98    let lower = cmp::min(a_lower, b_lower);
99    let upper = match (a_upper, b_upper) {
100        (Some(u1), Some(u2)) => Some(cmp::min(u1, u2)),
101        _ => a_upper.or(b_upper),
102    };
103    (lower, upper)
104}