Coverage Report

Created: 2025-09-04 06:37

/rust/registry/src/index.crates.io-6f17d22bba15001f/itertools-0.11.0/src/minmax.rs
Line
Count
Source (jump to first uncovered line)
1
2
/// `MinMaxResult` is an enum returned by `minmax`.
3
///
4
/// See [`.minmax()`](crate::Itertools::minmax) for more detail.
5
#[derive(Copy, Clone, PartialEq, Debug)]
6
pub enum MinMaxResult<T> {
7
    /// Empty iterator
8
    NoElements,
9
10
    /// Iterator with one element, so the minimum and maximum are the same
11
    OneElement(T),
12
13
    /// More than one element in the iterator, the first element is not larger
14
    /// than the second
15
    MinMax(T, T)
16
}
17
18
impl<T: Clone> MinMaxResult<T> {
19
    /// `into_option` creates an `Option` of type `(T, T)`. The returned `Option`
20
    /// has variant `None` if and only if the `MinMaxResult` has variant
21
    /// `NoElements`. Otherwise `Some((x, y))` is returned where `x <= y`.
22
    /// If the `MinMaxResult` has variant `OneElement(x)`, performing this
23
    /// operation will make one clone of `x`.
24
    ///
25
    /// # Examples
26
    ///
27
    /// ```
28
    /// use itertools::MinMaxResult::{self, NoElements, OneElement, MinMax};
29
    ///
30
    /// let r: MinMaxResult<i32> = NoElements;
31
    /// assert_eq!(r.into_option(), None);
32
    ///
33
    /// let r = OneElement(1);
34
    /// assert_eq!(r.into_option(), Some((1, 1)));
35
    ///
36
    /// let r = MinMax(1, 2);
37
    /// assert_eq!(r.into_option(), Some((1, 2)));
38
    /// ```
39
0
    pub fn into_option(self) -> Option<(T,T)> {
40
0
        match self {
41
0
            MinMaxResult::NoElements => None,
42
0
            MinMaxResult::OneElement(x) => Some((x.clone(), x)),
43
0
            MinMaxResult::MinMax(x, y) => Some((x, y))
44
        }
45
0
    }
46
}
47
48
/// Implementation guts for `minmax` and `minmax_by_key`.
49
0
pub fn minmax_impl<I, K, F, L>(mut it: I, mut key_for: F,
50
0
                               mut lt: L) -> MinMaxResult<I::Item>
51
0
    where I: Iterator,
52
0
          F: FnMut(&I::Item) -> K,
53
0
          L: FnMut(&I::Item, &I::Item, &K, &K) -> bool,
54
0
{
55
0
    let (mut min, mut max, mut min_key, mut max_key) = match it.next() {
56
0
        None => return MinMaxResult::NoElements,
57
0
        Some(x) => {
58
0
            match it.next() {
59
0
                None => return MinMaxResult::OneElement(x),
60
0
                Some(y) => {
61
0
                    let xk = key_for(&x);
62
0
                    let yk = key_for(&y);
63
0
                    if !lt(&y, &x, &yk, &xk) {(x, y, xk, yk)} else {(y, x, yk, xk)}
64
                }
65
            }
66
        }
67
    };
68
69
    loop {
70
        // `first` and `second` are the two next elements we want to look
71
        // at.  We first compare `first` and `second` (#1). The smaller one
72
        // is then compared to current minimum (#2). The larger one is
73
        // compared to current maximum (#3). This way we do 3 comparisons
74
        // for 2 elements.
75
0
        let first = match it.next() {
76
0
            None => break,
77
0
            Some(x) => x
78
        };
79
0
        let second = match it.next() {
80
            None => {
81
0
                let first_key = key_for(&first);
82
0
                if lt(&first, &min, &first_key, &min_key) {
83
0
                    min = first;
84
0
                } else if !lt(&first, &max, &first_key, &max_key) {
85
0
                    max = first;
86
0
                }
87
0
                break;
88
            }
89
0
            Some(x) => x
90
0
        };
91
0
        let first_key = key_for(&first);
92
0
        let second_key = key_for(&second);
93
0
        if !lt(&second, &first, &second_key, &first_key) {
94
0
            if lt(&first, &min, &first_key, &min_key) {
95
0
                min = first;
96
0
                min_key = first_key;
97
0
            }
98
0
            if !lt(&second, &max, &second_key, &max_key) {
99
0
                max = second;
100
0
                max_key = second_key;
101
0
            }
102
        } else {
103
0
            if lt(&second, &min, &second_key, &min_key) {
104
0
                min = second;
105
0
                min_key = second_key;
106
0
            }
107
0
            if !lt(&first, &max, &first_key, &max_key) {
108
0
                max = first;
109
0
                max_key = first_key;
110
0
            }
111
        }
112
    }
113
114
0
    MinMaxResult::MinMax(min, max)
115
0
}