Skip to main content

deser_validate/
validated.rs

1//! A value together with the errors it had.
2use std::borrow::Cow;
3use std::fmt;
4use std::marker::PhantomData;
5
6use deser_core::de::{Deserialize, OwnedSink, Sink, SinkHandle};
7use deser_core::ser::{Describe, Emit, Serialize};
8use deser_core::{Atom, ContainerShape, Error, ErrorKind, State};
9use deser_location::Locations;
10
11use crate::Validator;
12use crate::report::ReportHandle;
13
14/// A value that might be invalid, together with its errors.
15///
16/// Deserializing a `Validated` never fails: the errors of the value are
17/// kept in it instead of failing the deserialization of the value it's in.
18/// That covers the errors of the value itself (for instance a string where
19/// a number is expected), of the values nested in it and the violation of
20/// the validator `V` (none by default).  Within the value, all errors are
21/// collected (see [`State::set_collect_errors`]): the error holds all
22/// problems of the value, not just the first one.  Only the errors of the
23/// data format and of layers (for instance
24/// [`Limits`](deser_core::de::Limits)) still fail the deserialization, and
25/// the error that exceeds the limit of errors (see
26/// [`State::set_max_errors`]).
27///
28/// ```
29/// use deser::Deserialize;
30/// use deser_validate::{Email, Validated};
31///
32/// #[derive(Deserialize)]
33/// struct Signup {
34///     email: Validated<String, Email>,
35///     age: Validated<u8>,
36/// }
37///
38/// let signup: Signup =
39///     deser_json::from_str(r#"{"email": "nope", "age": "x"}"#).unwrap();
40/// assert!(!signup.email.is_valid());
41/// assert_eq!(signup.email.unchecked_value().unwrap(), "nope");
42/// assert_eq!(
43///     signup.email.error().unwrap().to_string(),
44///     "InvalidValue: invalid value: must be an email address at offset 10"
45/// );
46/// assert_eq!(signup.age.value(), None);
47/// ```
48///
49/// The errors have the context of the value attached, like errors that
50/// are returned (for instance the path with a
51/// [`PathLayer`](deser_path::PathLayer)).  If the format provides the
52/// source (see [`deser_location`]), their lines and columns are resolved.
53/// If a [`Validation`](crate::Validation) runs, they are reported to it
54/// too.
55///
56/// While an untagged enum tries its variants, errors are not kept: a
57/// variant with an invalid `Validated` value does not match.
58///
59/// ```
60/// use deser::Deserialize;
61/// use deser_validate::Validated;
62///
63/// #[derive(Deserialize)]
64/// struct Address {
65///     street: String,
66///     zip: u32,
67/// }
68///
69/// #[derive(Deserialize)]
70/// struct Order {
71///     shipping: Validated<Address>,
72/// }
73///
74/// let order: Order =
75///     deser_json::from_str(r#"{"shipping": {"zip": "x"}}"#).unwrap();
76/// let err = order.shipping.error().unwrap();
77/// let errors: Vec<_> = err.errors().map(|err| err.message()).collect();
78/// assert_eq!(
79///     errors,
80///     ["unexpected string, expected u32", "missing field `street`"]
81/// );
82/// ```
83///
84/// When serialized, the value is serialized (also if it's invalid), a
85/// value that could not be deserialized is serialized as null.
86pub struct Validated<T, V = ()> {
87    value: Option<T>,
88    error: Option<Error>,
89    _validator: PhantomData<fn() -> V>,
90}
91
92impl<T, V: Validator<T>> Validated<T, V> {
93    /// Validates a value.
94    pub fn new(value: T) -> Validated<T, V> {
95        let error = V::validate(&value).err().map(|x| x.into_error());
96        Validated {
97            value: Some(value),
98            error,
99            _validator: PhantomData,
100        }
101    }
102}
103
104impl<T, V> Validated<T, V> {
105    /// Creates an invalid value from an error.
106    pub fn from_error(error: Error) -> Validated<T, V> {
107        Validated {
108            value: None,
109            error: Some(error),
110            _validator: PhantomData,
111        }
112    }
113
114    /// Returns `true` if the value is valid.
115    pub fn is_valid(&self) -> bool {
116        self.error.is_none()
117    }
118
119    /// Returns the value if it's valid.
120    pub fn value(&self) -> Option<&T> {
121        match self.error {
122            None => self.value.as_ref(),
123            Some(_) => None,
124        }
125    }
126
127    /// Returns the value, also if the validator rejected it.
128    ///
129    /// Returns `None` if the value could not be deserialized.
130    pub fn unchecked_value(&self) -> Option<&T> {
131        self.value.as_ref()
132    }
133
134    /// Returns the error if the value is invalid.
135    ///
136    /// The error holds all errors of the value (see [`Error::errors`]).
137    pub fn error(&self) -> Option<&Error> {
138        self.error.as_ref()
139    }
140
141    /// Returns the value if it's valid and the error otherwise.
142    pub fn into_result(self) -> Result<T, Error> {
143        match (self.value, self.error) {
144            (Some(value), None) => Ok(value),
145            (_, Some(err)) => Err(err),
146            (None, None) => Err(Error::new(ErrorKind::InvalidState, "missing value")),
147        }
148    }
149}
150
151impl<T: fmt::Debug, V> fmt::Debug for Validated<T, V> {
152    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
153        match self.error {
154            None => fmt::Debug::fmt(&self.value, f),
155            Some(ref err) => f
156                .debug_struct("Invalid")
157                .field("value", &self.value)
158                .field("error", &format_args!("{:#}", err))
159                .finish(),
160        }
161    }
162}
163
164impl<'de, T: Deserialize<'de>, V: Validator<T>> Deserialize<'de> for Validated<T, V> {
165    fn deserialize_into<'out>(
166        out: &'out mut Option<Self>,
167        state: &mut State,
168    ) -> SinkHandle<'out, 'de> {
169        SinkHandle::arena(
170            ValidatedSink {
171                out,
172                sink: Some(OwnedSink::deserialize(state)),
173                error: None,
174                start: None,
175                outer: None,
176            },
177            state,
178        )
179    }
180
181    fn expecting() -> Cow<'static, str> {
182        T::expecting()
183    }
184
185    fn describe_type(d: &mut dyn Describe) {
186        T::describe_type(d)
187    }
188
189    /// Missing values are the missing values of `T` (validated).
190    fn initial_value() -> Option<Self> {
191        T::initial_value().map(Validated::new)
192    }
193}
194
195struct ValidatedSink<'a, 'de, T, V> {
196    out: &'a mut Option<Validated<T, V>>,
197    // `None` once the value failed, the rest of it is ignored then
198    sink: Option<OwnedSink<'de, T>>,
199    error: Option<Error>,
200    // the start of the value in the input
201    start: Option<usize>,
202    // if errors are collected outside of the value while it's deserialized
203    outer: Option<bool>,
204}
205
206impl<'a, 'de, T, V> ValidatedSink<'a, 'de, T, V> {
207    /// Returns the sink of the value unless it failed.
208    fn sink(&mut self) -> Option<&mut (dyn Sink<'de> + '_)> {
209        self.sink.as_mut().map(|sink| sink.get_mut())
210    }
211
212    /// Returns the sink of the value at its start.
213    ///
214    /// The errors in the value are collected.
215    fn begin(&mut self, state: &mut State) -> Option<&mut (dyn Sink<'de> + '_)> {
216        if self.start.is_none() {
217            self.start = state.input_range().map(|range| range.start);
218        }
219        if self.outer.is_none() {
220            self.outer = Some(state.collect_errors());
221            state.set_collect_errors(true);
222        }
223        self.sink()
224    }
225
226    /// Restores whether errors are collected once the value is complete or
227    /// failed.
228    fn end(&mut self, state: &mut State) {
229        if let Some(outer) = self.outer.take() {
230            state.set_collect_errors(outer);
231        }
232    }
233
234    /// Keeps the error of the value.
235    ///
236    /// The rest of the value is ignored.  While errors are discarded and
237    /// once the limit of errors is reached, the error is returned instead.
238    fn fail(&mut self, mut err: Error, state: &mut State) -> Result<(), Error> {
239        if state.discards_errors() || state.error_limit_reached() {
240            self.end(state);
241            return Err(err);
242        }
243        self.sink = None;
244        state.attach_error_context(&mut err);
245        self.error = Some(err);
246        Ok(())
247    }
248
249    /// Keeps the error of an operation on the value if it failed.
250    fn check(&mut self, rv: Result<(), Error>, state: &mut State) -> Result<(), Error> {
251        match rv {
252            Ok(()) => Ok(()),
253            Err(err) => self.fail(err, state),
254        }
255    }
256}
257
258impl<'a, 'de, T: Send, V: Validator<T>> Sink<'de> for ValidatedSink<'a, 'de, T, V> {
259    fn atom(&mut self, atom: Atom, state: &mut State) -> Result<(), Error> {
260        let rv = match self.begin(state) {
261            Some(sink) => sink.atom(atom, state),
262            None => Ok(()),
263        };
264        self.check(rv, state)
265    }
266
267    fn borrowed_atom(&mut self, atom: Atom<'de>, state: &mut State) -> Result<(), Error> {
268        let rv = match self.begin(state) {
269            Some(sink) => sink.borrowed_atom(atom, state),
270            None => Ok(()),
271        };
272        self.check(rv, state)
273    }
274
275    fn map(&mut self, state: &mut State) -> Result<(), Error> {
276        let rv = match self.begin(state) {
277            Some(sink) => sink.map(state),
278            None => Ok(()),
279        };
280        self.check(rv, state)
281    }
282
283    fn seq(&mut self, state: &mut State) -> Result<(), Error> {
284        let rv = match self.begin(state) {
285            Some(sink) => sink.seq(state),
286            None => Ok(()),
287        };
288        self.check(rv, state)
289    }
290
291    // The errors of the items are handled in `recover`.
292
293    fn next_key(&mut self, state: &mut State) -> Result<SinkHandle<'_, 'de>, Error> {
294        match self.sink() {
295            Some(sink) => sink.next_key(state),
296            None => Ok(SinkHandle::null()),
297        }
298    }
299
300    fn next_value(&mut self, state: &mut State) -> Result<SinkHandle<'_, 'de>, Error> {
301        match self.sink() {
302            Some(sink) => sink.next_value(state),
303            None => Ok(SinkHandle::null()),
304        }
305    }
306
307    fn __private_key_atom(&mut self, atom: Atom, state: &mut State) -> Result<(), Error> {
308        match self.sink() {
309            Some(sink) => sink.__private_key_atom(atom, state),
310            None => Ok(()),
311        }
312    }
313
314    fn __private_value_atom(&mut self, atom: Atom, state: &mut State) -> Result<(), Error> {
315        match self.sink() {
316            Some(sink) => sink.__private_value_atom(atom, state),
317            None => Ok(()),
318        }
319    }
320
321    fn __private_borrowed_key_atom(
322        &mut self,
323        atom: Atom<'de>,
324        state: &mut State,
325    ) -> Result<(), Error> {
326        match self.sink() {
327            Some(sink) => sink.__private_borrowed_key_atom(atom, state),
328            None => Ok(()),
329        }
330    }
331
332    fn __private_borrowed_value_atom(
333        &mut self,
334        atom: Atom<'de>,
335        state: &mut State,
336    ) -> Result<(), Error> {
337        match self.sink() {
338            Some(sink) => sink.__private_borrowed_value_atom(atom, state),
339            None => Ok(()),
340        }
341    }
342
343    fn value_for_key(
344        &mut self,
345        key: &str,
346        state: &mut State,
347    ) -> Result<Option<SinkHandle<'_, 'de>>, Error> {
348        match self.sink() {
349            Some(sink) => sink.value_for_key(key, state),
350            None => Ok(None),
351        }
352    }
353
354    fn recover(&mut self, err: Error, state: &mut State) -> Result<(), Error> {
355        // the value might recover itself (for instance if it collects
356        // errors), otherwise it failed
357        let rv = match self.sink() {
358            Some(sink) => sink.recover(err, state),
359            None => Ok(()),
360        };
361        self.check(rv, state)
362    }
363
364    fn finish(&mut self, state: &mut State) -> Result<(), Error> {
365        let rv = match self.sink() {
366            Some(sink) => sink.finish(state),
367            None => Ok(()),
368        };
369        self.check(rv, state)?;
370        self.end(state);
371        let value = self.sink.as_mut().and_then(|sink| sink.take());
372        if let Some(ref value) = value
373            && let Err(violation) = V::validate(value)
374        {
375            // the value is kept, it's invalid
376            let mut err = violation.into_error();
377            if let Some(start) = self.start {
378                err.set_offset(start);
379            }
380            if state.discards_errors() {
381                return Err(err);
382            }
383            state.attach_error_context(&mut err);
384            self.error = Some(err);
385        }
386        if value.is_none() && self.error.is_none() {
387            return Ok(());
388        }
389        let error = self.error.take().map(|err| report_error(err, state));
390        *self.out = Some(Validated {
391            value,
392            error,
393            _validator: PhantomData,
394        });
395        Ok(())
396    }
397
398    fn expecting(&self) -> Cow<'_, str> {
399        match self.sink {
400            Some(ref sink) => sink.get().expecting(),
401            None => Cow::Borrowed("compatible type"),
402        }
403    }
404}
405
406/// Resolves the position of an error that is kept and reports it.
407fn report_error(mut err: Error, state: &mut State) -> Error {
408    if let Some(source_map) = Locations::source_map(state) {
409        err.resolve_position(source_map.source().as_bytes());
410    }
411    ReportHandle::report(&err, state);
412    err
413}
414
415impl<T: Serialize, V> Serialize for Validated<T, V> {
416    fn serialize<'a>(this: &'a Self, state: &mut State) -> Result<Emit<'a>, Error> {
417        match this.value {
418            Some(ref value) => T::serialize(value, state),
419            None => Ok(Emit::Atom(Atom::Null)),
420        }
421    }
422
423    fn finish(this: &Self, state: &mut State) -> Result<(), Error> {
424        match this.value {
425            Some(ref value) => T::finish(value, state),
426            None => Ok(()),
427        }
428    }
429
430    fn is_optional(this: &Self) -> bool {
431        match this.value {
432            Some(ref value) => T::is_optional(value),
433            None => true,
434        }
435    }
436
437    fn container_shape(this: &Self) -> ContainerShape {
438        match this.value {
439            Some(ref value) => T::container_shape(value),
440            None => ContainerShape::new(),
441        }
442    }
443
444    fn describe(this: &Self, d: &mut dyn Describe) {
445        if let Some(ref value) = this.value {
446            T::describe(value, d)
447        }
448    }
449}