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