codama_errors/
combine_errors.rs1use crate::CodamaError;
2
3pub trait CombineErrors {
4 fn combine(&mut self, other: Self);
5}
6
7impl CombineErrors for CodamaError {
8 fn combine(&mut self, other: Self) {
9 if let (CodamaError::Compilation(this), CodamaError::Compilation(that)) = (self, other) {
10 this.combine(that)
11 }
12 }
13}
14
15impl CombineErrors for syn::Error {
16 fn combine(&mut self, other: Self) {
17 syn::Error::combine(self, other)
18 }
19}
20
21pub trait IteratorCombineErrors<T, E>: Iterator<Item = Result<T, E>>
22where
23 E: std::error::Error + CombineErrors,
24{
25 fn collect_and_combine_errors(self) -> Result<Vec<T>, E>
26 where
27 Self: Sized,
28 {
29 #[allow(clippy::manual_try_fold)]
30 self.fold(Ok(Vec::new()), |acc, result| match (acc, result) {
32 (Ok(mut acc_vec), Ok(parsed)) => {
33 acc_vec.push(parsed);
34 Ok(acc_vec)
35 }
36 (Err(mut acc_err), Err(err)) => {
37 acc_err.combine(err);
38 Err(acc_err)
39 }
40 (Err(acc_err), _) => Err(acc_err),
41 (_, Err(err)) => Err(err),
42 })
43 }
44}
45
46impl<I, T, E> IteratorCombineErrors<T, E> for I
47where
48 I: Iterator<Item = Result<T, E>>,
49 E: std::error::Error + CombineErrors,
50{
51}
52
53#[macro_export]
57macro_rules! combine_errors {
58 ($result:expr) => {
60 $result
61 };
62
63 ($first:expr, $second:expr $(,)?) => {{
65 match ($first, $second) {
66 (Ok(value1), Ok(value2)) => Ok((value1, value2)),
67 (Err(err1), Err(err2)) => {
68 let mut combined = err1;
69 codama_errors::CombineErrors::combine(&mut combined, err2);
70 Err(combined)
71 }
72 (Err(err), _) => Err(err),
73 (_, Err(err)) => Err(err),
74 }
75 }};
76
77 ($first:expr, $second:expr, $third:expr $(,)?) => {{
79 match ($first, combine_errors!($second, $third)) {
80 (Ok(value1), Ok((value2, value3))) => Ok((value1, value2, value3)),
81 (Err(err1), Err(err2)) => {
82 let mut combined = err1;
83 codama_errors::CombineErrors::combine(&mut combined, err2);
84 Err(combined)
85 }
86 (Err(err), _) => Err(err),
87 (_, Err(err)) => Err(err),
88 }
89 }};
90}