kutil_std/error/
errors.rs

1use super::recipient::*;
2
3use std::{error::*, fmt, iter::*, slice, vec};
4
5//
6// Errors
7//
8
9/// An [Error] that contains zero or more errors.
10///
11/// Implements [ErrorRecipient] by accumulating errors.
12#[derive(Debug, Clone)]
13pub struct Errors<ErrorT> {
14    /// The errors.
15    pub errors: Vec<ErrorT>,
16}
17
18impl<ErrorT> Errors<ErrorT> {
19    /// Constructor.
20    pub fn new() -> Self {
21        Self { errors: Vec::new() }
22    }
23
24    /// True if there are no errors.
25    pub fn is_empty(&self) -> bool {
26        self.errors.is_empty()
27    }
28
29    /// Fails with self if there are errors.
30    pub fn check(&self) -> Result<(), &Self> {
31        if self.is_empty() {
32            Ok(())
33        } else {
34            Err(self)
35        }
36    }
37}
38
39impl<ErrorT> ErrorRecipient<ErrorT> for Errors<ErrorT> {
40    fn give(&mut self, error: impl Into<ErrorT>) -> Result<(), ErrorT> {
41        self.errors.push(error.into());
42        Ok(())
43    }
44}
45
46impl<ErrorT> Error for Errors<ErrorT> where ErrorT: Error {}
47
48impl<ErrorT> fmt::Display for Errors<ErrorT>
49where
50    ErrorT: fmt::Display,
51{
52    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
53        let mut i = self.errors.iter().peekable();
54        while let Some(error) = i.next() {
55            fmt::Display::fmt(error, formatter)?;
56            if i.peek().is_some() {
57                writeln!(formatter)?;
58            }
59        }
60        Ok(())
61    }
62}
63
64// Delegated
65
66impl<ErrorT> IntoIterator for Errors<ErrorT> {
67    type Item = ErrorT;
68    type IntoIter = vec::IntoIter<Self::Item>;
69
70    fn into_iter(self) -> Self::IntoIter {
71        self.errors.into_iter()
72    }
73}
74
75impl<'own, ErrorT> IntoIterator for &'own Errors<ErrorT> {
76    type Item = &'own ErrorT;
77    type IntoIter = slice::Iter<'own, ErrorT>;
78
79    fn into_iter(self) -> Self::IntoIter {
80        self.errors.iter()
81    }
82}
83
84impl<'own, ErrorT> IntoIterator for &'own mut Errors<ErrorT> {
85    type Item = &'own mut ErrorT;
86    type IntoIter = slice::IterMut<'own, ErrorT>;
87
88    fn into_iter(self) -> Self::IntoIter {
89        self.errors.iter_mut()
90    }
91}
92
93// Conversions
94
95impl<ErrorT> From<ErrorT> for Errors<ErrorT> {
96    fn from(value: ErrorT) -> Self {
97        let mut errors = Errors::new();
98        errors.errors.push(value);
99        errors
100    }
101}
102
103impl<ErrorT> Into<Vec<ErrorT>> for Errors<ErrorT> {
104    fn into(self) -> Vec<ErrorT> {
105        self.errors
106    }
107}
108
109//
110// AsErrorsResult
111//
112
113/// Converts to a [Result] with [Errors].
114pub trait AsErrorsResult<ReturnT, ErrorT> {
115    /// Converts to a [Result] with [Errors].
116    fn as_errors(self) -> Result<ReturnT, Errors<ErrorT>>;
117}
118
119impl<ReturnT, ErrorT> AsErrorsResult<ReturnT, ErrorT> for Result<ReturnT, ErrorT> {
120    fn as_errors(self) -> Result<ReturnT, Errors<ErrorT>> {
121        Ok(self?)
122    }
123}