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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
use ControlFlow::*;

/// Denotes whether the iteration should continue or not.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum ControlFlow {
    /// To stop the iteration and return the error
    Break,
    /// To continue the iteration
    Continue,
}

/// Determines the manner in which the encountered error(s) are processed, stored and returned, as well as
/// whether the iteration should continue or not.
pub trait ErrorCollector<E> {
    /// The type to be returned after the iteration has been stopped
    type Collection;

    /// Creates an empty `ErrorCollector`.
    fn empty() -> Self;

    /// Processes an error. Returns an [`ControlFlow`] type indicating whether the iteration shall stop
    /// or not.
    fn push_err(&mut self, err: E) -> ControlFlow;

    /// Returns `Ok(val)` if the iteration run to completion, or an error collection of type
    /// [`Self::Collection`][ErrorCollector::Collection] if error(s) were encountered.
    fn with_value<T>(self, val: T) -> Result<T, Self::Collection>;
}

/// A unit type that implements [`ErrorCollector`]. Ignores all errors and runs the iterator to
/// completion
#[derive(Debug, Copy, Clone)]
pub struct Ignore;

impl<E> ErrorCollector<E> for Ignore {
    type Collection = Infallible;

    #[inline]
    fn empty() -> Self {
        Self
    }

    #[inline]
    fn push_err(&mut self, _err: E) -> ControlFlow {
        Continue
    }

    #[inline]
    fn with_value<T>(self, val: T) -> Result<T, Self::Collection> {
        Ok(val)
    }
}

impl<E, F: From<E>> ErrorCollector<E> for Option<F> {
    type Collection = F;

    #[inline]
    fn empty() -> Self {
        None
    }

    #[inline]
    fn push_err(&mut self, err: E) -> ControlFlow {
        *self = Some(err.into());
        Break
    }

    #[inline]
    fn with_value<T>(self, val: T) -> Result<T, Self::Collection> {
        if let Some(err) = self {
            Err(err)
        } else {
            Ok(val)
        }
    }
}

impl<E, F: From<E>> ErrorCollector<E> for Vec<F> {
    type Collection = Self;

    #[inline]
    fn empty() -> Self {
        Self::new()
    }

    #[inline]
    fn push_err(&mut self, err: E) -> ControlFlow {
        self.push(err.into());
        Continue
    }

    #[inline]
    fn with_value<T>(self, val: T) -> Result<T, Self::Collection> {
        if self.is_empty() {
            Ok(val)
        } else {
            Err(self)
        }
    }
}

#[cfg(feature = "arrayvec")]
use arrayvec::ArrayVec;
use std::convert::Infallible;

/// Store upto N errors in an `ArrayVec<E, N>`. Stop the iteration if more are encountered.
#[cfg(feature = "arrayvec")]
impl<E, F: From<E>, const CAP: usize> ErrorCollector<E> for ArrayVec<F, CAP> {
    type Collection = Self;

    #[inline]
    fn empty() -> Self {
        Self::new()
    }

    #[inline]
    fn push_err(&mut self, err: E) -> ControlFlow {
        match self.try_push(err.into()) {
            Ok(_) => Continue,
            Err(_) => Break,
        }
    }

    #[inline]
    fn with_value<T>(self, val: T) -> Result<T, Self::Collection> {
        if self.is_empty() {
            Ok(val)
        } else {
            Err(self)
        }
    }
}