1use crate::errors::consensus::ConsensusError;
2use crate::ProtocolError;
3use std::fmt::Debug;
4
5#[macro_export]
6macro_rules! check_validation_result_with_data {
7 ($result:expr) => {
8 match $result {
9 Ok(result) => result,
10 Err(e) => return Ok(ValidationResult::new_with_errors(vec![e.into()])),
11 }
12 };
13}
14
15pub type SimpleValidationResult<E> = ValidationResult<(), E>;
16
17pub type ConsensusValidationResult<TData> = ValidationResult<TData, ConsensusError>;
18
19pub type SimpleConsensusValidationResult = ConsensusValidationResult<()>;
20
21#[derive(Debug, Clone)]
22pub struct ValidationResult<TData: Clone, E: Debug> {
23 pub errors: Vec<E>,
24 pub data: Option<TData>,
25}
26
27impl<T: Clone, E: Debug> Default for ValidationResult<T, E> {
28 fn default() -> Self {
29 ValidationResult {
30 errors: Vec::new(),
31 data: None,
32 }
33 }
34}
35
36impl<TData: Clone, E: Debug> ValidationResult<Vec<TData>, E> {
37 pub fn flatten<I: IntoIterator<Item = ValidationResult<Vec<TData>, E>>>(
38 items: I,
39 ) -> ValidationResult<Vec<TData>, E> {
40 let mut aggregate_errors = vec![];
41 let mut aggregate_data = vec![];
42 items.into_iter().for_each(|single_validation_result| {
43 let ValidationResult { mut errors, data } = single_validation_result;
44 aggregate_errors.append(&mut errors);
45 if let Some(mut data) = data {
46 aggregate_data.append(&mut data);
47 }
48 });
49 ValidationResult::new_with_data_and_errors(aggregate_data, aggregate_errors)
50 }
51}
52
53impl<TData: Clone, E: Debug> ValidationResult<TData, E> {
54 pub fn merge_many<I: IntoIterator<Item = ValidationResult<TData, E>>>(
55 items: I,
56 ) -> ValidationResult<Vec<TData>, E> {
57 let mut aggregate_errors = vec![];
58 let mut aggregate_data = vec![];
59 items.into_iter().for_each(|single_validation_result| {
60 let ValidationResult { mut errors, data } = single_validation_result;
61 aggregate_errors.append(&mut errors);
62 if let Some(data) = data {
63 aggregate_data.push(data);
64 }
65 });
66 ValidationResult::new_with_data_and_errors(aggregate_data, aggregate_errors)
67 }
68}
69
70impl<E: Debug> SimpleValidationResult<E> {
71 pub fn merge_many_errors<I: IntoIterator<Item = SimpleValidationResult<E>>>(
72 items: I,
73 ) -> SimpleValidationResult<E> {
74 let errors = items
75 .into_iter()
76 .flat_map(|single_validation_result| single_validation_result.errors)
77 .collect();
78 SimpleValidationResult::new_with_errors(errors)
79 }
80}
81
82impl<TData: Clone, E: Debug> ValidationResult<TData, E> {
83 pub fn new() -> Self {
84 Self {
85 errors: vec![],
86 data: None::<TData>,
87 }
88 }
89
90 pub fn new_with_data(data: TData) -> Self {
91 Self {
92 errors: vec![],
93 data: Some(data),
94 }
95 }
96
97 pub fn new_with_data_and_errors(data: TData, errors: Vec<E>) -> Self {
98 Self {
99 errors,
100 data: Some(data),
101 }
102 }
103
104 pub fn new_with_error(error: E) -> Self {
105 Self {
106 errors: vec![error],
107 data: None,
108 }
109 }
110
111 pub fn new_with_errors(errors: Vec<E>) -> Self {
112 Self { errors, data: None }
113 }
114
115 pub fn map<F, U: Clone>(self, f: F) -> ValidationResult<U, E>
116 where
117 F: FnOnce(TData) -> U,
118 {
119 ValidationResult {
120 errors: self.errors,
121 data: self.data.map(f),
122 }
123 }
124
125 pub fn map_result<F, U: Clone, G>(self, f: F) -> Result<ValidationResult<U, E>, G>
126 where
127 F: FnOnce(TData) -> Result<U, G>,
128 {
129 Ok(ValidationResult {
130 errors: self.errors,
131 data: self.data.map(f).transpose()?,
132 })
133 }
134
135 pub fn and_then_simple_validation<F>(
136 self,
137 f: F,
138 ) -> Result<ValidationResult<TData, E>, ProtocolError>
139 where
140 F: FnOnce(&TData) -> Result<SimpleValidationResult<E>, ProtocolError>,
141 {
142 let new_errors = self.data.as_ref().map(f).transpose()?;
143 let mut result = ValidationResult {
144 errors: self.errors,
145 data: self.data,
146 };
147 if let Some(new_errors) = new_errors {
148 result.add_errors(new_errors.errors)
149 }
150 Ok(result)
151 }
152
153 pub fn and_then_validation<F, U: Clone, G>(self, f: F) -> Result<ValidationResult<U, E>, G>
154 where
155 F: FnOnce(TData) -> Result<ValidationResult<U, E>, G>,
156 {
157 if let Some(data) = self.data {
158 let mut new_validation_result = f(data)?;
159 new_validation_result.add_errors(self.errors);
160 Ok(new_validation_result)
161 } else {
162 Ok(ValidationResult::<U, E>::new_with_errors(self.errors))
163 }
164 }
165
166 pub fn and_then_borrowed_validation<F, U: Clone, G>(
167 self,
168 f: F,
169 ) -> Result<ValidationResult<U, E>, G>
170 where
171 F: FnOnce(&TData) -> Result<ValidationResult<U, E>, G>,
172 {
173 if let Some(data) = self.data.as_ref() {
174 let mut new_validation_result = f(data)?;
175 new_validation_result.add_errors(self.errors);
176 Ok(new_validation_result)
177 } else {
178 Ok(ValidationResult::<U, E>::new_with_errors(self.errors))
179 }
180 }
181
182 pub fn add_error<T>(&mut self, error: T)
183 where
184 T: Into<E>,
185 {
186 self.errors.push(error.into())
187 }
188
189 pub fn add_errors(&mut self, mut errors: Vec<E>) {
190 self.errors.append(&mut errors)
191 }
192
193 pub fn add_errors_into<EI: Into<E>>(&mut self, errors: Vec<EI>) {
194 errors.into_iter().for_each(|e| self.add_error(e.into()))
195 }
196
197 pub fn merge<TOtherData: Clone>(&mut self, mut other: ValidationResult<TOtherData, E>) {
198 self.errors.append(&mut other.errors);
199 }
200
201 pub fn is_valid(&self) -> bool {
202 self.errors.is_empty()
203 }
204
205 pub fn is_err(&self) -> bool {
206 !self.errors.is_empty()
207 }
208
209 pub fn first_error(&self) -> Option<&E> {
210 self.errors.first()
211 }
212
213 pub fn get_error(&self, pos: usize) -> Option<&E> {
214 self.errors.get(pos)
215 }
216
217 pub fn into_result_without_data(self) -> ValidationResult<(), E> {
218 ValidationResult {
219 errors: self.errors,
220 data: None,
221 }
222 }
223
224 pub fn is_valid_with_data(&self) -> bool {
225 self.is_valid() && self.data.is_some()
226 }
227
228 pub fn has_data(&self) -> bool {
229 self.data.is_some()
230 }
231
232 pub fn set_data(&mut self, data: TData) {
233 self.data = Some(data)
234 }
235
236 pub fn into_data(self) -> Result<TData, ProtocolError> {
237 self.data
238 .ok_or(ProtocolError::CorruptedCodeExecution(format!(
239 "trying to push validation result into data (errors are {:?})",
240 self.errors
241 )))
242 }
243
244 pub fn into_data_with_error(mut self) -> Result<Result<TData, E>, ProtocolError> {
245 if let Some(error) = self.errors.pop() {
246 Ok(Err(error))
247 } else {
248 self.data
249 .map(Ok)
250 .ok_or(ProtocolError::CorruptedCodeExecution(format!(
251 "trying to push validation result into data (errors are {:?})",
252 self.errors
253 )))
254 }
255 }
256
257 pub fn into_data_and_errors(self) -> Result<(TData, Vec<E>), ProtocolError> {
258 Ok((
259 self.data
260 .ok_or(ProtocolError::CorruptedCodeExecution(format!(
261 "trying to push validation result into data (errors are {:?})",
262 self.errors
263 )))?,
264 self.errors,
265 ))
266 }
267
268 pub fn data_as_borrowed(&self) -> Result<&TData, ProtocolError> {
269 self.data
270 .as_ref()
271 .ok_or(ProtocolError::CorruptedCodeExecution(format!(
272 "trying to get validation result as data (errors are {:?})",
273 self.errors
274 )))
275 }
276}
277
278impl<TData: Clone, E: Debug> From<TData> for ValidationResult<TData, E> {
279 fn from(value: TData) -> Self {
280 ValidationResult::new_with_data(value)
281 }
282}
283
284impl<TData: Clone, E: Debug, F: Into<E>> From<Result<TData, F>> for ValidationResult<TData, E> {
285 fn from(value: Result<TData, F>) -> Self {
286 match value {
287 Ok(data) => ValidationResult::new_with_data(data),
288 Err(e) => ValidationResult::new_with_errors(vec![e.into()]),
289 }
290 }
291}