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}