1use {
5 crate::AppError,
6 itertools::Itertools,
7 std::{
8 fmt,
9 ops::{ControlFlow, FromResidual, Try},
10 },
11};
12
13pub enum AllErrs<C, D = ()> {
16 Ok(C),
17 Err(Vec<AppError<D>>),
18}
19
20impl<C, D> fmt::Debug for AllErrs<C, D>
21where
22 C: fmt::Debug,
23 D: fmt::Debug + 'static,
24{
25 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
26 match self {
27 Self::Ok(value) => f.debug_tuple("Ok").field(value).finish(),
28 Self::Err(errs) => f.debug_tuple("Err").field(errs).finish(),
29 }
30 }
31}
32
33impl<C, D> Default for AllErrs<C, D>
34where
35 C: Default,
36{
37 fn default() -> Self {
38 Self::Ok(C::default())
39 }
40}
41impl<C, U, D> Extend<Result<U, AppError<D>>> for AllErrs<C, D>
42where
43 C: Extend<U>,
44{
45 fn extend<T: IntoIterator<Item = Result<U, AppError<D>>>>(&mut self, iter: T) {
46 for res in iter {
48 match (&mut *self, res) {
49 (Self::Ok(collection), Ok(item)) => collection.extend_one(item),
51 (Self::Ok(_), Err(err)) => *self = Self::Err(vec![err]),
53 (Self::Err(_), Ok(_)) => (),
55 (Self::Err(errs), Err(err)) => errs.push(err),
57 }
58 }
59 }
60}
61
62impl<C, T, D> FromIterator<Result<T, AppError<D>>> for AllErrs<C, D>
63where
64 C: Default + Extend<T>,
65{
66 fn from_iter<I>(iter: I) -> Self
67 where
68 I: IntoIterator<Item = Result<T, AppError<D>>>,
69 {
70 let (values, errs) = iter.into_iter().partition_result::<C, Vec<_>, _, _>();
72 match errs.is_empty() {
73 true => Self::Ok(values),
74 false => Self::Err(errs),
75 }
76 }
77}
78
79pub struct AllErrsResidue<D>(Vec<AppError<D>>);
80
81impl<D> fmt::Debug for AllErrsResidue<D>
82where
83 D: fmt::Debug + 'static,
84{
85 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
86 f.debug_tuple("AllErrsResidue").field(&self.0).finish()
87 }
88}
89
90impl<C, D> Try for AllErrs<C, D> {
91 type Output = C;
92 type Residual = AllErrsResidue<D>;
93
94 fn from_output(output: Self::Output) -> Self {
95 Self::Ok(output)
96 }
97
98 fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
99 match self {
100 Self::Ok(values) => ControlFlow::Continue(values),
101 Self::Err(errs) => ControlFlow::Break(AllErrsResidue(errs)),
102 }
103 }
104}
105
106impl<T, D> FromResidual<AllErrsResidue<D>> for AllErrs<T, D> {
107 fn from_residual(residual: AllErrsResidue<D>) -> Self {
108 Self::Err(residual.0)
109 }
110}
111
112impl<T, D> FromResidual<AllErrsResidue<D>> for Result<T, AppError<D>> {
113 fn from_residual(residual: AllErrsResidue<D>) -> Self {
114 let err = match <[_; 1]>::try_from(residual.0) {
115 Ok([err]) => err,
116 Err(errs) => {
117 assert!(!errs.is_empty(), "`ResultMultipleResidue` should hold at least 1 error");
118 AppError::from_multiple(errs)
119 },
120 };
121
122 Err(err)
123 }
124}