      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110

    use crate::ops::Try;

    /// Used to make try_fold closures more like normal loops
    #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
    #[derive(Debug, Clone, Copy, PartialEq)]
    pub enum ControlFlow<C, B> {
        /// Continue in the loop, using the given value for the next iteration
        Continue(C),
        /// Exit the loop, yielding the given value
        Break(B),
    }

    #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
    impl<C, B> Try for ControlFlow<C, B> {
        type Ok = C;
        type Error = B;
        #[inline]
        fn into_result(self) -> Result<Self::Ok, Self::Error> {
            match self {
                ControlFlow::Continue(y) => Ok(y),
                ControlFlow::Break(x) => Err(x),
            }
        }
        #[inline]
        fn from_error(v: Self::Error) -> Self {
            ControlFlow::Break(v)
        }
        #[inline]
        fn from_ok(v: Self::Ok) -> Self {
            ControlFlow::Continue(v)
        }
    }

    impl<C, B> ControlFlow<C, B> {
        /// Converts the `ControlFlow` into an `Option` which is `Some` if the
        /// `ControlFlow` was `Break` and `None` otherwise.
        #[inline]
        #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
        pub fn break_value(self) -> Option<B> {
            match self {
                ControlFlow::Continue(..) => None,
                ControlFlow::Break(x) => Some(x),
            }
        }
    }

    impl<R: Try> ControlFlow<R::Ok, R> {
        /// Create a `ControlFlow` from any type implementing `Try`.
        #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
        #[inline]
        pub fn from_try(r: R) -> Self {
            match Try::into_result(r) {
                Ok(v) => ControlFlow::Continue(v),
                Err(v) => ControlFlow::Break(Try::from_error(v)),
            }
        }

        /// Convert a `ControlFlow` into any type implementing `Try`;
        #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
        #[inline]
        pub fn into_try(self) -> R {
            match self {
                ControlFlow::Continue(v) => Try::from_ok(v),
                ControlFlow::Break(v) => v,
            }
        }
    }

    impl<B> ControlFlow<(), B> {
        /// It's frequently the case that there's no value needed with `Continue`,
        /// so this provides a way to avoid typing `(())`, if you prefer it.
        ///
        /// # Examples
        ///
        /// ```
        /// #![feature(control_flow_enum)]
        /// use std::ops::ControlFlow;
        ///
        /// let mut partial_sum = 0;
        /// let last_used = (1..10).chain(20..25).try_for_each(|x| {
        ///     partial_sum += x;
        ///     if partial_sum > 100 { ControlFlow::Break(x) }
        ///     else { ControlFlow::CONTINUE }
        /// });
        /// assert_eq!(last_used.break_value(), Some(22));
        /// ```
        #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
        pub const CONTINUE: Self = ControlFlow::Continue(());
    }

    impl<C> ControlFlow<C, ()> {
        /// APIs like `try_for_each` don't need values with `Break`,
        /// so this provides a way to avoid typing `(())`, if you prefer it.
        ///
        /// # Examples
        ///
        /// ```
        /// #![feature(control_flow_enum)]
        /// use std::ops::ControlFlow;
        ///
        /// let mut partial_sum = 0;
        /// (1..10).chain(20..25).try_for_each(|x| {
        ///     if partial_sum > 100 { ControlFlow::BREAK }
        ///     else { partial_sum += x; ControlFlow::CONTINUE }
        /// });
        /// assert_eq!(partial_sum, 108);
        /// ```
        #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
        pub const BREAK: Self = ControlFlow::Break(());
    }