dpp/validation/
validation_result.rs

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    // -- new() --
298
299    #[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    // -- new_with_data() --
312
313    #[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    // -- new_with_error() --
321
322    #[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    // -- new_with_errors() --
332
333    #[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    // -- map() --
351
352    #[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    // -- map_result() --
379
380    #[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    // -- is_valid() / is_err() --
410
411    #[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    // -- first_error() --
440
441    #[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    // -- into_data() --
455
456    #[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    // -- into_data_with_error() --
469
470    #[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    // -- into_data_and_errors() --
492
493    #[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    // -- From impls --
518
519    #[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    // -- flatten() --
543
544    #[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    // -- merge_many() --
566
567    #[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    // -- merge_many_errors() --
587
588    #[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    // -- Default --
611
612    #[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    // -- add_error / add_errors / merge --
620
621    #[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    // -- get_error / has_data / is_valid_with_data / set_data --
648
649    #[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}