process_results/
errors.rs

1use ControlFlow::*;
2
3/// Denotes whether the iteration should continue or not.
4#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
5pub enum ControlFlow {
6    /// To stop the iteration and return the error
7    Break,
8    /// To continue the iteration
9    Continue,
10}
11
12/// Determines the manner in which the encountered error(s) are processed, stored and returned, as well as
13/// whether the iteration should continue or not.
14pub trait ErrorCollector<E> {
15    /// The type to be returned after the iteration has been stopped
16    type Collection;
17
18    /// Creates an empty `ErrorCollector`.
19    fn empty() -> Self;
20
21    /// Processes an error. Returns an [`ControlFlow`] type indicating whether the iteration shall stop
22    /// or not.
23    fn push_err(&mut self, err: E) -> ControlFlow;
24
25    /// Returns `Ok(val)` if the iteration run to completion, or an error collection of type
26    /// [`Self::Collection`][ErrorCollector::Collection] if error(s) were encountered.
27    fn with_value<T>(self, val: T) -> Result<T, Self::Collection>;
28}
29
30/// A unit type that implements [`ErrorCollector`]. Ignores all errors and runs the iterator to
31/// completion
32#[derive(Debug, Copy, Clone)]
33pub struct Ignore;
34
35impl<E> ErrorCollector<E> for Ignore {
36    type Collection = Infallible;
37
38    #[inline]
39    fn empty() -> Self {
40        Self
41    }
42
43    #[inline]
44    fn push_err(&mut self, _err: E) -> ControlFlow {
45        Continue
46    }
47
48    #[inline]
49    fn with_value<T>(self, val: T) -> Result<T, Self::Collection> {
50        Ok(val)
51    }
52}
53
54impl<E, F: From<E>> ErrorCollector<E> for Option<F> {
55    type Collection = F;
56
57    #[inline]
58    fn empty() -> Self {
59        None
60    }
61
62    #[inline]
63    fn push_err(&mut self, err: E) -> ControlFlow {
64        *self = Some(err.into());
65        Break
66    }
67
68    #[inline]
69    fn with_value<T>(self, val: T) -> Result<T, Self::Collection> {
70        if let Some(err) = self {
71            Err(err)
72        } else {
73            Ok(val)
74        }
75    }
76}
77
78impl<E, F: From<E>> ErrorCollector<E> for Vec<F> {
79    type Collection = Self;
80
81    #[inline]
82    fn empty() -> Self {
83        Self::new()
84    }
85
86    #[inline]
87    fn push_err(&mut self, err: E) -> ControlFlow {
88        self.push(err.into());
89        Continue
90    }
91
92    #[inline]
93    fn with_value<T>(self, val: T) -> Result<T, Self::Collection> {
94        if self.is_empty() {
95            Ok(val)
96        } else {
97            Err(self)
98        }
99    }
100}
101
102#[cfg(feature = "arrayvec")]
103use arrayvec::ArrayVec;
104use std::convert::Infallible;
105
106/// Store upto N errors in an `ArrayVec<E, N>`. Stop the iteration if more are encountered.
107#[cfg(feature = "arrayvec")]
108impl<E, F: From<E>, const CAP: usize> ErrorCollector<E> for ArrayVec<F, CAP> {
109    type Collection = Self;
110
111    #[inline]
112    fn empty() -> Self {
113        Self::new()
114    }
115
116    #[inline]
117    fn push_err(&mut self, err: E) -> ControlFlow {
118        match self.try_push(err.into()) {
119            Ok(_) => Continue,
120            Err(_) => Break,
121        }
122    }
123
124    #[inline]
125    fn with_value<T>(self, val: T) -> Result<T, Self::Collection> {
126        if self.is_empty() {
127            Ok(val)
128        } else {
129            Err(self)
130        }
131    }
132}