1use std::cmp;
4
5pub type SizeHint = (usize, Option<usize>);
7
8#[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#[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#[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#[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#[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#[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#[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]
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}