eserde/
errors.rs

1use crate::path::Path;
2
3/// A collection of errors encountered while trying to deserialize a type.
4///
5/// Use [`.iter()`](Self::iter) to iterator over the underlying [`DeserializationError`].
6#[derive(Debug)]
7pub struct DeserializationErrors(Vec<DeserializationError>);
8
9impl From<Vec<DeserializationError>> for DeserializationErrors {
10    fn from(errors: Vec<DeserializationError>) -> Self {
11        DeserializationErrors(errors)
12    }
13}
14
15impl DeserializationErrors {
16    /// Iterate over references to the underlying [`DeserializationError`]s.
17    ///
18    /// Use [`.into_iter()`](Self::into_iter) if you need owned [`DeserializationError`]s
19    /// from the iterator.
20    pub fn iter(&self) -> impl ExactSizeIterator<Item = &DeserializationError> {
21        self.0.iter()
22    }
23
24    /// The number of errors in the collection.
25    pub fn len(&self) -> usize {
26        self.0.len()
27    }
28
29    /// Returns `true` if the collection contains no errors.
30    pub fn is_empty(&self) -> bool {
31        self.0.is_empty()
32    }
33}
34
35impl IntoIterator for DeserializationErrors {
36    type Item = DeserializationError;
37    type IntoIter = std::vec::IntoIter<Self::Item>;
38
39    fn into_iter(self) -> Self::IntoIter {
40        self.0.into_iter()
41    }
42}
43
44impl std::fmt::Display for DeserializationErrors {
45    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
46        writeln!(f, "Something went wrong during deserialization:")?;
47        for error in self.iter() {
48            writeln!(f, "- {error}")?;
49        }
50        Ok(())
51    }
52}
53
54// Due to the design of `std`'s `Error` trait, we really don't have a good
55// story for combining multiple errors into a single error.
56// In particular, it's unclear/ill-defined what should be returned from
57// `source`.
58// We leave it to `None`, but that really sucks...
59impl std::error::Error for DeserializationErrors {}
60
61#[derive(Debug)]
62/// An error that occurred during deserialization.
63pub struct DeserializationError {
64    pub(crate) path: Option<Path>,
65    pub(crate) details: String,
66}
67
68impl DeserializationError {
69    /// An explanation of what went wrong during deserialization.
70    pub fn message(&self) -> &str {
71        self.details.as_ref()
72    }
73
74    /// The input path at which the error occurred, when available.
75    ///
76    /// E.g. if the error occurred while deserializing the sub-field `foo` of the top-level
77    /// field `bar`, the path would be `bar.foo`.
78    pub fn path(&self) -> Option<&Path> {
79        self.path.as_ref()
80    }
81}
82
83impl std::fmt::Display for DeserializationError {
84    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
85        if let Some(path) = &self.path {
86            if !path.is_empty() {
87                write!(f, "{}: ", path)?;
88            }
89        }
90        write!(f, "{}", self.details)
91    }
92}