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::{Chunk, Describe, 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///     "Unexpected: 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::Unexpected, "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    /// Missing values are the missing values of `T` (validated).
182    fn initial_value() -> Option<Self> {
183        T::initial_value().map(Validated::new)
184    }
185}
186
187struct ValidatedSink<'a, 'de, T, V> {
188    out: &'a mut Option<Validated<T, V>>,
189    // `None` once the value failed, the rest of it is ignored then
190    sink: Option<OwnedSink<'de, T>>,
191    error: Option<Error>,
192    // the start of the value in the input
193    start: Option<usize>,
194    // if errors are collected outside of the value while it's deserialized
195    outer: Option<bool>,
196}
197
198impl<'a, 'de, T, V> ValidatedSink<'a, 'de, T, V> {
199    /// Returns the sink of the value unless it failed.
200    fn sink(&mut self) -> Option<&mut (dyn Sink<'de> + '_)> {
201        self.sink.as_mut().map(|sink| sink.borrow_mut())
202    }
203
204    /// Returns the sink of the value at its start.
205    ///
206    /// The errors in the value are collected.
207    fn begin(&mut self, state: &mut State) -> Option<&mut (dyn Sink<'de> + '_)> {
208        if self.start.is_none() {
209            self.start = state.input_range().map(|range| range.start);
210        }
211        if self.outer.is_none() {
212            self.outer = Some(state.set_collect_errors(true));
213        }
214        self.sink()
215    }
216
217    /// Restores whether errors are collected once the value is complete or
218    /// failed.
219    fn end(&mut self, state: &mut State) {
220        if let Some(outer) = self.outer.take() {
221            state.set_collect_errors(outer);
222        }
223    }
224
225    /// Keeps the error of the value.
226    ///
227    /// The rest of the value is ignored.  While errors are discarded and
228    /// once the limit of errors is reached, the error is returned instead.
229    fn fail(&mut self, err: Error, state: &mut State) -> Result<(), Error> {
230        if state.discards_errors() || state.error_limit_reached() {
231            self.end(state);
232            return Err(err);
233        }
234        self.sink = None;
235        self.error = Some(state.attach_error_context(err));
236        Ok(())
237    }
238
239    /// Keeps the error of an operation on the value if it failed.
240    fn check(&mut self, rv: Result<(), Error>, state: &mut State) -> Result<(), Error> {
241        match rv {
242            Ok(()) => Ok(()),
243            Err(err) => self.fail(err, state),
244        }
245    }
246}
247
248impl<'a, 'de, T: Send, V: Validator<T>> Sink<'de> for ValidatedSink<'a, 'de, T, V> {
249    fn atom(&mut self, atom: Atom, state: &mut State) -> Result<(), Error> {
250        let rv = match self.begin(state) {
251            Some(sink) => sink.atom(atom, state),
252            None => Ok(()),
253        };
254        self.check(rv, state)
255    }
256
257    fn borrowed_atom(&mut self, atom: Atom<'de>, state: &mut State) -> Result<(), Error> {
258        let rv = match self.begin(state) {
259            Some(sink) => sink.borrowed_atom(atom, state),
260            None => Ok(()),
261        };
262        self.check(rv, state)
263    }
264
265    fn map(&mut self, state: &mut State) -> Result<(), Error> {
266        let rv = match self.begin(state) {
267            Some(sink) => sink.map(state),
268            None => Ok(()),
269        };
270        self.check(rv, state)
271    }
272
273    fn seq(&mut self, state: &mut State) -> Result<(), Error> {
274        let rv = match self.begin(state) {
275            Some(sink) => sink.seq(state),
276            None => Ok(()),
277        };
278        self.check(rv, state)
279    }
280
281    // The errors of the items are handled in `recover`.
282
283    fn next_key(&mut self, state: &mut State) -> Result<SinkHandle<'_, 'de>, Error> {
284        match self.sink() {
285            Some(sink) => sink.next_key(state),
286            None => Ok(SinkHandle::null()),
287        }
288    }
289
290    fn next_value(&mut self, state: &mut State) -> Result<SinkHandle<'_, 'de>, Error> {
291        match self.sink() {
292            Some(sink) => sink.next_value(state),
293            None => Ok(SinkHandle::null()),
294        }
295    }
296
297    fn __private_key_atom(&mut self, atom: Atom, state: &mut State) -> Result<(), Error> {
298        match self.sink() {
299            Some(sink) => sink.__private_key_atom(atom, state),
300            None => Ok(()),
301        }
302    }
303
304    fn __private_value_atom(&mut self, atom: Atom, state: &mut State) -> Result<(), Error> {
305        match self.sink() {
306            Some(sink) => sink.__private_value_atom(atom, state),
307            None => Ok(()),
308        }
309    }
310
311    fn __private_borrowed_key_atom(
312        &mut self,
313        atom: Atom<'de>,
314        state: &mut State,
315    ) -> Result<(), Error> {
316        match self.sink() {
317            Some(sink) => sink.__private_borrowed_key_atom(atom, state),
318            None => Ok(()),
319        }
320    }
321
322    fn __private_borrowed_value_atom(
323        &mut self,
324        atom: Atom<'de>,
325        state: &mut State,
326    ) -> Result<(), Error> {
327        match self.sink() {
328            Some(sink) => sink.__private_borrowed_value_atom(atom, state),
329            None => Ok(()),
330        }
331    }
332
333    fn value_for_key(
334        &mut self,
335        key: &str,
336        state: &mut State,
337    ) -> Result<Option<SinkHandle<'_, 'de>>, Error> {
338        match self.sink() {
339            Some(sink) => sink.value_for_key(key, state),
340            None => Ok(None),
341        }
342    }
343
344    fn recover(&mut self, err: Error, state: &mut State) -> Result<(), Error> {
345        // the value might recover itself (for instance if it collects
346        // errors), otherwise it failed
347        let rv = match self.sink() {
348            Some(sink) => sink.recover(err, state),
349            None => Ok(()),
350        };
351        self.check(rv, state)
352    }
353
354    fn finish(&mut self, state: &mut State) -> Result<(), Error> {
355        let rv = match self.sink() {
356            Some(sink) => sink.finish(state),
357            None => Ok(()),
358        };
359        self.check(rv, state)?;
360        self.end(state);
361        let value = self.sink.as_mut().and_then(|sink| sink.take());
362        if let Some(ref value) = value
363            && let Err(violation) = V::validate(value)
364        {
365            // the value is kept, it's invalid
366            let err = violation.into_error();
367            let err = match self.start {
368                Some(start) => err.with_offset(start),
369                None => err,
370            };
371            if state.discards_errors() {
372                return Err(err);
373            }
374            self.error = Some(state.attach_error_context(err));
375        }
376        if value.is_none() && self.error.is_none() {
377            return Ok(());
378        }
379        let error = self.error.take().map(|err| report_error(err, state));
380        *self.out = Some(Validated {
381            value,
382            error,
383            _validator: PhantomData,
384        });
385        Ok(())
386    }
387
388    fn expecting(&self) -> Cow<'_, str> {
389        match self.sink {
390            Some(ref sink) => sink.borrow().expecting(),
391            None => Cow::Borrowed("compatible type"),
392        }
393    }
394}
395
396/// Resolves the position of an error that is kept and reports it.
397fn report_error(err: Error, state: &mut State) -> Error {
398    let err = match Locations::source_map(state) {
399        Some(source_map) => err.resolve_position(source_map.source().as_bytes()),
400        None => err,
401    };
402    ReportHandle::report(&err, state);
403    err
404}
405
406impl<T: Serialize, V> Serialize for Validated<T, V> {
407    fn serialize(&self, state: &mut State) -> Result<Chunk<'_>, Error> {
408        match self.value {
409            Some(ref value) => value.serialize(state),
410            None => Ok(Chunk::Atom(Atom::Null)),
411        }
412    }
413
414    fn finish(&self, state: &mut State) -> Result<(), Error> {
415        match self.value {
416            Some(ref value) => value.finish(state),
417            None => Ok(()),
418        }
419    }
420
421    fn is_optional(&self) -> bool {
422        match self.value {
423            Some(ref value) => value.is_optional(),
424            None => true,
425        }
426    }
427
428    fn container_shape(&self) -> ContainerShape {
429        match self.value {
430            Some(ref value) => value.container_shape(),
431            None => ContainerShape::new(),
432        }
433    }
434
435    fn describe(&self, d: &mut dyn Describe) {
436        if let Some(ref value) = self.value {
437            value.describe(d)
438        }
439    }
440}