1use crate::{BoxedError, Error};
4use std::{error::Error as StdError, fmt, sync::Arc};
5
6const MAX_REPORTED_ERRORS: usize = 1024;
7
8#[derive(Clone, Debug, Default)]
25pub struct ErrorReport {
26 errors: Vec<Arc<Error>>,
27}
28
29impl ErrorReport {
30 pub fn record(&mut self, error: Error) {
32 let room = MAX_REPORTED_ERRORS.saturating_sub(self.errors.len());
33 match error {
34 Error::Other(cause) => match cause.downcast::<ErrorReport>() {
35 Ok(report) => self.errors.extend(report.errors.into_iter().take(room)),
36 Err(cause) if room > 0 => self.errors.push(Arc::new(Error::Other(cause))),
37 Err(_) => {}
38 },
39 error if room > 0 => self.errors.push(Arc::new(error)),
40 _ => {}
41 }
42 }
43
44 pub fn record_shared(&mut self, error: Arc<Error>) {
46 if self.errors.len() < MAX_REPORTED_ERRORS {
47 self.errors.push(error);
48 }
49 }
50
51 pub fn errors(&self) -> &[Arc<Error>] {
53 &self.errors
54 }
55
56 pub fn first(&self) -> Option<&Arc<Error>> {
58 self.errors.first()
59 }
60
61 pub fn len(&self) -> usize {
63 self.errors.len()
64 }
65
66 pub fn is_empty(&self) -> bool {
68 self.errors.is_empty()
69 }
70
71 pub fn into_vec(self) -> Vec<Arc<Error>> {
73 self.errors
74 }
75
76 pub fn map(self, map: impl FnMut(Arc<Error>) -> Arc<Error>) -> Self {
78 Self {
79 errors: self.errors.into_iter().map(map).collect(),
80 }
81 }
82}
83
84impl From<Error> for ErrorReport {
85 fn from(error: Error) -> Self {
86 let mut report = Self::default();
87 report.record(error);
88 report
89 }
90}
91
92impl From<crate::ValidationError> for ErrorReport {
93 fn from(error: crate::ValidationError) -> Self {
94 Error::from(error).into()
95 }
96}
97
98impl From<std::io::Error> for ErrorReport {
99 fn from(error: std::io::Error) -> Self {
100 Error::from(error).into()
101 }
102}
103
104impl From<BoxedError> for ErrorReport {
105 fn from(error: BoxedError) -> Self {
106 Error::from(error).into()
107 }
108}
109
110impl From<ErrorReport> for Error {
111 fn from(report: ErrorReport) -> Self {
112 let mut errors = report.errors;
113 if errors.len() == 1 {
114 match Arc::try_unwrap(errors.remove(0)) {
115 Ok(error) => return error,
116 Err(shared) => errors.push(shared),
117 }
118 }
119 Self::Other(Box::new(ErrorReport { errors }))
120 }
121}
122
123impl fmt::Display for ErrorReport {
124 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
125 write!(formatter, "{} authoring error(s)", self.errors.len())?;
126 for error in &self.errors {
127 write!(formatter, "\n {error}")?;
128 }
129 Ok(())
130 }
131}
132
133impl StdError for ErrorReport {
134 fn source(&self) -> Option<&(dyn StdError + 'static)> {
135 self.errors
136 .first()
137 .map(|error| error.as_ref() as &(dyn StdError + 'static))
138 }
139}
140
141impl IntoIterator for ErrorReport {
142 type Item = Arc<Error>;
143
144 type IntoIter = std::vec::IntoIter<Arc<Error>>;
145
146 fn into_iter(self) -> Self::IntoIter {
147 self.errors.into_iter()
148 }
149}
150
151impl<'a> IntoIterator for &'a ErrorReport {
152 type Item = &'a Arc<Error>;
153
154 type IntoIter = std::slice::Iter<'a, Arc<Error>>;
155
156 fn into_iter(self) -> Self::IntoIter {
157 self.errors.iter()
158 }
159}