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}
292
293#[cfg(test)]
294mod tests {
295 use super::*;
296
297 #[test]
300 fn test_new_has_no_errors() {
301 let result: ValidationResult<i32, String> = ValidationResult::new();
302 assert!(result.errors.is_empty());
303 }
304
305 #[test]
306 fn test_new_has_no_data() {
307 let result: ValidationResult<i32, String> = ValidationResult::new();
308 assert!(result.data.is_none());
309 }
310
311 #[test]
314 fn test_new_with_data_stores_data() {
315 let result: ValidationResult<i32, String> = ValidationResult::new_with_data(42);
316 assert_eq!(result.data, Some(42));
317 assert!(result.errors.is_empty());
318 }
319
320 #[test]
323 fn test_new_with_error_stores_single_error() {
324 let result: ValidationResult<i32, String> =
325 ValidationResult::new_with_error("bad".to_string());
326 assert_eq!(result.errors.len(), 1);
327 assert_eq!(result.errors[0], "bad");
328 assert!(result.data.is_none());
329 }
330
331 #[test]
334 fn test_new_with_errors_stores_multiple_errors() {
335 let result: ValidationResult<i32, String> =
336 ValidationResult::new_with_errors(vec!["a".to_string(), "b".to_string()]);
337 assert_eq!(result.errors.len(), 2);
338 assert_eq!(result.errors[0], "a");
339 assert_eq!(result.errors[1], "b");
340 assert!(result.data.is_none());
341 }
342
343 #[test]
344 fn test_new_with_errors_empty_vec() {
345 let result: ValidationResult<i32, String> = ValidationResult::new_with_errors(vec![]);
346 assert!(result.errors.is_empty());
347 assert!(result.data.is_none());
348 }
349
350 #[test]
353 fn test_map_transforms_data() {
354 let result: ValidationResult<i32, String> = ValidationResult::new_with_data(10);
355 let mapped = result.map(|x| x * 2);
356 assert_eq!(mapped.data, Some(20));
357 assert!(mapped.errors.is_empty());
358 }
359
360 #[test]
361 fn test_map_preserves_errors() {
362 let result: ValidationResult<i32, String> =
363 ValidationResult::new_with_data_and_errors(5, vec!["err".to_string()]);
364 let mapped = result.map(|x| x + 1);
365 assert_eq!(mapped.data, Some(6));
366 assert_eq!(mapped.errors, vec!["err".to_string()]);
367 }
368
369 #[test]
370 fn test_map_with_no_data() {
371 let result: ValidationResult<i32, String> =
372 ValidationResult::new_with_error("err".to_string());
373 let mapped = result.map(|x| x + 1);
374 assert!(mapped.data.is_none());
375 assert_eq!(mapped.errors.len(), 1);
376 }
377
378 #[test]
381 fn test_map_result_with_ok_closure() {
382 let result: ValidationResult<i32, String> = ValidationResult::new_with_data(10);
383 let mapped: Result<ValidationResult<String, String>, String> =
384 result.map_result(|x| Ok(format!("val={}", x)));
385 let mapped = mapped.unwrap();
386 assert_eq!(mapped.data, Some("val=10".to_string()));
387 }
388
389 #[test]
390 fn test_map_result_with_err_closure() {
391 let result: ValidationResult<i32, String> = ValidationResult::new_with_data(10);
392 let mapped: Result<ValidationResult<i32, String>, String> =
393 result.map_result(|_| Err("fail".to_string()));
394 assert!(mapped.is_err());
395 assert_eq!(mapped.unwrap_err(), "fail");
396 }
397
398 #[test]
399 fn test_map_result_with_no_data() {
400 let result: ValidationResult<i32, String> =
401 ValidationResult::new_with_error("err".to_string());
402 let mapped: Result<ValidationResult<i32, String>, String> =
403 result.map_result(|x| Ok(x + 1));
404 let mapped = mapped.unwrap();
405 assert!(mapped.data.is_none());
406 assert_eq!(mapped.errors, vec!["err".to_string()]);
407 }
408
409 #[test]
412 fn test_is_valid_true_when_no_errors() {
413 let result: ValidationResult<i32, String> = ValidationResult::new();
414 assert!(result.is_valid());
415 assert!(!result.is_err());
416 }
417
418 #[test]
419 fn test_is_valid_false_when_errors_present() {
420 let result: ValidationResult<i32, String> =
421 ValidationResult::new_with_error("e".to_string());
422 assert!(!result.is_valid());
423 assert!(result.is_err());
424 }
425
426 #[test]
427 fn test_is_valid_with_data_and_no_errors() {
428 let result: ValidationResult<i32, String> = ValidationResult::new_with_data(1);
429 assert!(result.is_valid());
430 }
431
432 #[test]
433 fn test_is_err_with_data_and_errors() {
434 let result: ValidationResult<i32, String> =
435 ValidationResult::new_with_data_and_errors(1, vec!["e".to_string()]);
436 assert!(result.is_err());
437 }
438
439 #[test]
442 fn test_first_error_returns_first() {
443 let result: ValidationResult<i32, String> =
444 ValidationResult::new_with_errors(vec!["first".to_string(), "second".to_string()]);
445 assert_eq!(result.first_error(), Some(&"first".to_string()));
446 }
447
448 #[test]
449 fn test_first_error_returns_none_when_no_errors() {
450 let result: ValidationResult<i32, String> = ValidationResult::new();
451 assert_eq!(result.first_error(), None);
452 }
453
454 #[test]
457 fn test_into_data_returns_data_when_present() {
458 let result: ValidationResult<i32, String> = ValidationResult::new_with_data(42);
459 assert_eq!(result.into_data().unwrap(), 42);
460 }
461
462 #[test]
463 fn test_into_data_returns_error_when_no_data() {
464 let result: ValidationResult<i32, String> = ValidationResult::new();
465 assert!(result.into_data().is_err());
466 }
467
468 #[test]
471 fn test_into_data_with_error_returns_data_when_valid() {
472 let result: ValidationResult<i32, String> = ValidationResult::new_with_data(42);
473 let inner = result.into_data_with_error().unwrap();
474 assert_eq!(inner.unwrap(), 42);
475 }
476
477 #[test]
478 fn test_into_data_with_error_returns_last_error_when_errors_present() {
479 let result: ValidationResult<i32, String> =
480 ValidationResult::new_with_errors(vec!["first".to_string(), "last".to_string()]);
481 let inner = result.into_data_with_error().unwrap();
482 assert_eq!(inner.unwrap_err(), "last");
483 }
484
485 #[test]
486 fn test_into_data_with_error_returns_protocol_error_when_no_data_and_no_errors() {
487 let result: ValidationResult<i32, String> = ValidationResult::new();
488 assert!(result.into_data_with_error().is_err());
489 }
490
491 #[test]
494 fn test_into_data_and_errors_returns_both() {
495 let result: ValidationResult<i32, String> =
496 ValidationResult::new_with_data_and_errors(10, vec!["e".to_string()]);
497 let (data, errors) = result.into_data_and_errors().unwrap();
498 assert_eq!(data, 10);
499 assert_eq!(errors, vec!["e".to_string()]);
500 }
501
502 #[test]
503 fn test_into_data_and_errors_returns_empty_errors_when_valid() {
504 let result: ValidationResult<i32, String> = ValidationResult::new_with_data(10);
505 let (data, errors) = result.into_data_and_errors().unwrap();
506 assert_eq!(data, 10);
507 assert!(errors.is_empty());
508 }
509
510 #[test]
511 fn test_into_data_and_errors_fails_without_data() {
512 let result: ValidationResult<i32, String> =
513 ValidationResult::new_with_error("e".to_string());
514 assert!(result.into_data_and_errors().is_err());
515 }
516
517 #[test]
520 fn test_from_data_creates_valid_result() {
521 let result: ValidationResult<i32, String> = 42.into();
522 assert_eq!(result.data, Some(42));
523 assert!(result.errors.is_empty());
524 }
525
526 #[test]
527 fn test_from_ok_result_creates_valid_result() {
528 let ok_result: Result<i32, String> = Ok(42);
529 let result: ValidationResult<i32, String> = ok_result.into();
530 assert_eq!(result.data, Some(42));
531 assert!(result.errors.is_empty());
532 }
533
534 #[test]
535 fn test_from_err_result_creates_error_result() {
536 let err_result: Result<i32, String> = Err("bad".to_string());
537 let result: ValidationResult<i32, String> = err_result.into();
538 assert!(result.data.is_none());
539 assert_eq!(result.errors, vec!["bad".to_string()]);
540 }
541
542 #[test]
545 fn test_flatten_merges_data_and_errors() {
546 let r1: ValidationResult<Vec<i32>, String> = ValidationResult::new_with_data(vec![1, 2]);
547 let r2: ValidationResult<Vec<i32>, String> =
548 ValidationResult::new_with_data_and_errors(vec![3], vec!["e".to_string()]);
549 let r3: ValidationResult<Vec<i32>, String> =
550 ValidationResult::new_with_error("e2".to_string());
551
552 let flat = ValidationResult::flatten(vec![r1, r2, r3]);
553 assert_eq!(flat.data, Some(vec![1, 2, 3]));
554 assert_eq!(flat.errors, vec!["e".to_string(), "e2".to_string()]);
555 }
556
557 #[test]
558 fn test_flatten_empty_input() {
559 let flat: ValidationResult<Vec<i32>, String> =
560 ValidationResult::flatten(std::iter::empty());
561 assert_eq!(flat.data, Some(vec![]));
562 assert!(flat.errors.is_empty());
563 }
564
565 #[test]
568 fn test_merge_many_collects_data_into_vec() {
569 let r1: ValidationResult<i32, String> = ValidationResult::new_with_data(1);
570 let r2: ValidationResult<i32, String> = ValidationResult::new_with_data(2);
571 let r3: ValidationResult<i32, String> = ValidationResult::new_with_error("e".to_string());
572
573 let merged = ValidationResult::merge_many(vec![r1, r2, r3]);
574 assert_eq!(merged.data, Some(vec![1, 2]));
575 assert_eq!(merged.errors, vec!["e".to_string()]);
576 }
577
578 #[test]
579 fn test_merge_many_empty_input() {
580 let merged: ValidationResult<Vec<i32>, String> =
581 ValidationResult::merge_many(std::iter::empty::<ValidationResult<i32, String>>());
582 assert_eq!(merged.data, Some(vec![]));
583 assert!(merged.errors.is_empty());
584 }
585
586 #[test]
589 fn test_merge_many_errors_collects_all_errors() {
590 let r1: SimpleValidationResult<String> =
591 SimpleValidationResult::new_with_errors(vec!["a".to_string()]);
592 let r2: SimpleValidationResult<String> =
593 SimpleValidationResult::new_with_errors(vec!["b".to_string(), "c".to_string()]);
594 let r3: SimpleValidationResult<String> = SimpleValidationResult::new();
595
596 let merged = SimpleValidationResult::merge_many_errors(vec![r1, r2, r3]);
597 assert_eq!(
598 merged.errors,
599 vec!["a".to_string(), "b".to_string(), "c".to_string()]
600 );
601 }
602
603 #[test]
604 fn test_merge_many_errors_empty_input() {
605 let merged: SimpleValidationResult<String> =
606 SimpleValidationResult::merge_many_errors(std::iter::empty());
607 assert!(merged.errors.is_empty());
608 }
609
610 #[test]
613 fn test_default_is_empty() {
614 let result: ValidationResult<i32, String> = ValidationResult::default();
615 assert!(result.errors.is_empty());
616 assert!(result.data.is_none());
617 }
618
619 #[test]
622 fn test_add_error() {
623 let mut result: ValidationResult<i32, String> = ValidationResult::new();
624 result.add_error("e1".to_string());
625 result.add_error("e2".to_string());
626 assert_eq!(result.errors, vec!["e1".to_string(), "e2".to_string()]);
627 }
628
629 #[test]
630 fn test_add_errors() {
631 let mut result: ValidationResult<i32, String> =
632 ValidationResult::new_with_error("e1".to_string());
633 result.add_errors(vec!["e2".to_string(), "e3".to_string()]);
634 assert_eq!(result.errors.len(), 3);
635 }
636
637 #[test]
638 fn test_merge_appends_errors_from_other() {
639 let mut r1: ValidationResult<i32, String> =
640 ValidationResult::new_with_error("a".to_string());
641 let r2: ValidationResult<String, String> =
642 ValidationResult::new_with_error("b".to_string());
643 r1.merge(r2);
644 assert_eq!(r1.errors, vec!["a".to_string(), "b".to_string()]);
645 }
646
647 #[test]
650 fn test_get_error() {
651 let result: ValidationResult<i32, String> =
652 ValidationResult::new_with_errors(vec!["a".to_string(), "b".to_string()]);
653 assert_eq!(result.get_error(0), Some(&"a".to_string()));
654 assert_eq!(result.get_error(1), Some(&"b".to_string()));
655 assert_eq!(result.get_error(2), None);
656 }
657
658 #[test]
659 fn test_has_data() {
660 let with: ValidationResult<i32, String> = ValidationResult::new_with_data(1);
661 let without: ValidationResult<i32, String> = ValidationResult::new();
662 assert!(with.has_data());
663 assert!(!without.has_data());
664 }
665
666 #[test]
667 fn test_is_valid_with_data() {
668 let valid_with_data: ValidationResult<i32, String> = ValidationResult::new_with_data(1);
669 let valid_no_data: ValidationResult<i32, String> = ValidationResult::new();
670 let invalid_with_data: ValidationResult<i32, String> =
671 ValidationResult::new_with_data_and_errors(1, vec!["e".to_string()]);
672 assert!(valid_with_data.is_valid_with_data());
673 assert!(!valid_no_data.is_valid_with_data());
674 assert!(!invalid_with_data.is_valid_with_data());
675 }
676
677 #[test]
678 fn test_set_data() {
679 let mut result: ValidationResult<i32, String> = ValidationResult::new();
680 assert!(result.data.is_none());
681 result.set_data(99);
682 assert_eq!(result.data, Some(99));
683 }
684
685 #[test]
686 fn test_into_result_without_data() {
687 let result: ValidationResult<i32, String> =
688 ValidationResult::new_with_data_and_errors(42, vec!["e".to_string()]);
689 let without_data = result.into_result_without_data();
690 assert!(without_data.data.is_none());
691 assert_eq!(without_data.errors, vec!["e".to_string()]);
692 }
693
694 #[test]
695 fn test_data_as_borrowed() {
696 let result: ValidationResult<i32, String> = ValidationResult::new_with_data(42);
697 assert_eq!(result.data_as_borrowed().unwrap(), &42);
698 }
699
700 #[test]
701 fn test_data_as_borrowed_no_data() {
702 let result: ValidationResult<i32, String> = ValidationResult::new();
703 assert!(result.data_as_borrowed().is_err());
704 }
705}