Skip to main content

facet_format/deserializer/
error.rs

1extern crate alloc;
2
3use alloc::string::String;
4use core::fmt;
5use facet_path::Path;
6use facet_reflect::ReflectError;
7
8/// Error produced by the format deserializer.
9#[derive(Debug)]
10pub enum DeserializeError<E> {
11    /// Error emitted by the format-specific parser.
12    Parser(E),
13    /// Reflection error from Partial operations.
14    Reflect {
15        /// The underlying reflection error.
16        error: ReflectError,
17        /// Source span where the error occurred (if available).
18        span: Option<facet_reflect::Span>,
19        /// Path through the type structure where the error occurred.
20        path: Option<Path>,
21    },
22    /// Type mismatch during deserialization.
23    TypeMismatch {
24        /// The expected type or token.
25        expected: &'static str,
26        /// The actual type or token that was encountered.
27        got: String,
28        /// Source span where the mismatch occurred (if available).
29        span: Option<facet_reflect::Span>,
30        /// Path through the type structure where the error occurred.
31        path: Option<Path>,
32    },
33    /// Unsupported type or operation.
34    Unsupported(String),
35    /// Unknown field encountered when deny_unknown_fields is set.
36    UnknownField {
37        /// The unknown field name.
38        field: String,
39        /// Source span where the unknown field was found (if available).
40        span: Option<facet_reflect::Span>,
41        /// Path through the type structure where the error occurred.
42        path: Option<Path>,
43    },
44    /// Cannot borrow string from input (e.g., escaped string into &str).
45    CannotBorrow {
46        /// Description of why borrowing failed.
47        message: String,
48    },
49    /// Required field missing from input.
50    MissingField {
51        /// The field that is missing.
52        field: &'static str,
53        /// The type that contains the field.
54        type_name: &'static str,
55        /// Source span where the struct was being parsed (if available).
56        span: Option<facet_reflect::Span>,
57        /// Path through the type structure where the error occurred.
58        path: Option<Path>,
59    },
60    /// Field validation failed.
61    #[cfg(feature = "validate")]
62    Validation {
63        /// The field that failed validation.
64        field: &'static str,
65        /// The validation error message.
66        message: String,
67        /// Source span where the invalid value was found.
68        span: Option<facet_reflect::Span>,
69        /// Path through the type structure where the error occurred.
70        path: Option<Path>,
71    },
72    /// Unexpected end of input.
73    UnexpectedEof {
74        /// What was expected before EOF.
75        expected: &'static str,
76    },
77}
78
79impl<E: fmt::Display> fmt::Display for DeserializeError<E> {
80    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
81        match self {
82            DeserializeError::Parser(err) => write!(f, "{err}"),
83            DeserializeError::Reflect { error, .. } => write!(f, "{error}"),
84            DeserializeError::TypeMismatch { expected, got, .. } => {
85                write!(f, "type mismatch: expected {expected}, got {got}")
86            }
87            DeserializeError::Unsupported(msg) => write!(f, "unsupported: {msg}"),
88            DeserializeError::UnknownField { field, .. } => write!(f, "unknown field: {field}"),
89            DeserializeError::CannotBorrow { message } => write!(f, "{message}"),
90            DeserializeError::MissingField {
91                field, type_name, ..
92            } => {
93                write!(f, "missing field `{field}` in type `{type_name}`")
94            }
95            #[cfg(feature = "validate")]
96            DeserializeError::Validation { field, message, .. } => {
97                write!(f, "validation failed for field `{field}`: {message}")
98            }
99            DeserializeError::UnexpectedEof { expected } => {
100                write!(f, "unexpected end of input, expected {expected}")
101            }
102        }
103    }
104}
105
106impl<E: fmt::Debug + fmt::Display> std::error::Error for DeserializeError<E> {}
107
108impl<E> DeserializeError<E> {
109    /// Create a Reflect error without span or path information.
110    #[inline]
111    pub const fn reflect(error: ReflectError) -> Self {
112        DeserializeError::Reflect {
113            error,
114            span: None,
115            path: None,
116        }
117    }
118
119    /// Create a Reflect error with span information.
120    #[inline]
121    pub const fn reflect_with_span(error: ReflectError, span: facet_reflect::Span) -> Self {
122        DeserializeError::Reflect {
123            error,
124            span: Some(span),
125            path: None,
126        }
127    }
128
129    /// Create a Reflect error with span and path information.
130    #[inline]
131    pub const fn reflect_with_context(
132        error: ReflectError,
133        span: Option<facet_reflect::Span>,
134        path: Path,
135    ) -> Self {
136        DeserializeError::Reflect {
137            error,
138            span,
139            path: Some(path),
140        }
141    }
142
143    /// Get the path where the error occurred, if available.
144    pub const fn path(&self) -> Option<&Path> {
145        match self {
146            DeserializeError::Reflect { path, .. } => path.as_ref(),
147            DeserializeError::TypeMismatch { path, .. } => path.as_ref(),
148            DeserializeError::UnknownField { path, .. } => path.as_ref(),
149            DeserializeError::MissingField { path, .. } => path.as_ref(),
150            _ => None,
151        }
152    }
153
154    /// Add path information to an error (consumes and returns the modified error).
155    pub fn with_path(self, new_path: Path) -> Self {
156        match self {
157            DeserializeError::Reflect { error, span, .. } => DeserializeError::Reflect {
158                error,
159                span,
160                path: Some(new_path),
161            },
162            DeserializeError::TypeMismatch {
163                expected,
164                got,
165                span,
166                ..
167            } => DeserializeError::TypeMismatch {
168                expected,
169                got,
170                span,
171                path: Some(new_path),
172            },
173            DeserializeError::UnknownField { field, span, .. } => DeserializeError::UnknownField {
174                field,
175                span,
176                path: Some(new_path),
177            },
178            DeserializeError::MissingField {
179                field,
180                type_name,
181                span,
182                ..
183            } => DeserializeError::MissingField {
184                field,
185                type_name,
186                span,
187                path: Some(new_path),
188            },
189            // Other variants don't have path fields
190            other => other,
191        }
192    }
193}