|  | /// `MinMaxResult` is an enum returned by `minmax`. | 
|  | /// | 
|  | /// See [`.minmax()`](crate::Itertools::minmax) for more detail. | 
|  | #[derive(Copy, Clone, PartialEq, Eq, Debug)] | 
|  | pub enum MinMaxResult<T> { | 
|  | /// Empty iterator | 
|  | NoElements, | 
|  |  | 
|  | /// Iterator with one element, so the minimum and maximum are the same | 
|  | OneElement(T), | 
|  |  | 
|  | /// More than one element in the iterator, the first element is not larger | 
|  | /// than the second | 
|  | MinMax(T, T), | 
|  | } | 
|  |  | 
|  | impl<T: Clone> MinMaxResult<T> { | 
|  | /// `into_option` creates an `Option` of type `(T, T)`. The returned `Option` | 
|  | /// has variant `None` if and only if the `MinMaxResult` has variant | 
|  | /// `NoElements`. Otherwise `Some((x, y))` is returned where `x <= y`. | 
|  | /// If the `MinMaxResult` has variant `OneElement(x)`, performing this | 
|  | /// operation will make one clone of `x`. | 
|  | /// | 
|  | /// # Examples | 
|  | /// | 
|  | /// ``` | 
|  | /// use itertools::MinMaxResult::{self, NoElements, OneElement, MinMax}; | 
|  | /// | 
|  | /// let r: MinMaxResult<i32> = NoElements; | 
|  | /// assert_eq!(r.into_option(), None); | 
|  | /// | 
|  | /// let r = OneElement(1); | 
|  | /// assert_eq!(r.into_option(), Some((1, 1))); | 
|  | /// | 
|  | /// let r = MinMax(1, 2); | 
|  | /// assert_eq!(r.into_option(), Some((1, 2))); | 
|  | /// ``` | 
|  | pub fn into_option(self) -> Option<(T, T)> { | 
|  | match self { | 
|  | Self::NoElements => None, | 
|  | Self::OneElement(x) => Some((x.clone(), x)), | 
|  | Self::MinMax(x, y) => Some((x, y)), | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Implementation guts for `minmax` and `minmax_by_key`. | 
|  | pub fn minmax_impl<I, K, F, L>(mut it: I, mut key_for: F, mut lt: L) -> MinMaxResult<I::Item> | 
|  | where | 
|  | I: Iterator, | 
|  | F: FnMut(&I::Item) -> K, | 
|  | L: FnMut(&I::Item, &I::Item, &K, &K) -> bool, | 
|  | { | 
|  | let (mut min, mut max, mut min_key, mut max_key) = match it.next() { | 
|  | None => return MinMaxResult::NoElements, | 
|  | Some(x) => match it.next() { | 
|  | None => return MinMaxResult::OneElement(x), | 
|  | Some(y) => { | 
|  | let xk = key_for(&x); | 
|  | let yk = key_for(&y); | 
|  | if !lt(&y, &x, &yk, &xk) { | 
|  | (x, y, xk, yk) | 
|  | } else { | 
|  | (y, x, yk, xk) | 
|  | } | 
|  | } | 
|  | }, | 
|  | }; | 
|  |  | 
|  | loop { | 
|  | // `first` and `second` are the two next elements we want to look | 
|  | // at.  We first compare `first` and `second` (#1). The smaller one | 
|  | // is then compared to current minimum (#2). The larger one is | 
|  | // compared to current maximum (#3). This way we do 3 comparisons | 
|  | // for 2 elements. | 
|  | let first = match it.next() { | 
|  | None => break, | 
|  | Some(x) => x, | 
|  | }; | 
|  | let second = match it.next() { | 
|  | None => { | 
|  | let first_key = key_for(&first); | 
|  | if lt(&first, &min, &first_key, &min_key) { | 
|  | min = first; | 
|  | } else if !lt(&first, &max, &first_key, &max_key) { | 
|  | max = first; | 
|  | } | 
|  | break; | 
|  | } | 
|  | Some(x) => x, | 
|  | }; | 
|  | let first_key = key_for(&first); | 
|  | let second_key = key_for(&second); | 
|  | if !lt(&second, &first, &second_key, &first_key) { | 
|  | if lt(&first, &min, &first_key, &min_key) { | 
|  | min = first; | 
|  | min_key = first_key; | 
|  | } | 
|  | if !lt(&second, &max, &second_key, &max_key) { | 
|  | max = second; | 
|  | max_key = second_key; | 
|  | } | 
|  | } else { | 
|  | if lt(&second, &min, &second_key, &min_key) { | 
|  | min = second; | 
|  | min_key = second_key; | 
|  | } | 
|  | if !lt(&first, &max, &first_key, &max_key) { | 
|  | max = first; | 
|  | max_key = first_key; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | MinMaxResult::MinMax(min, max) | 
|  | } |