1use facet_core::{Characteristic, EnumType, FieldError, Shape, TryFromError};
2use facet_path::Path;
3
4#[derive(Debug, Clone)]
9pub struct ShapeMismatchError {
10 pub expected: &'static Shape,
12 pub actual: &'static Shape,
14}
15
16impl core::fmt::Display for ShapeMismatchError {
17 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
18 write!(
19 f,
20 "shape mismatch: expected {}, got {}",
21 self.expected, self.actual
22 )
23 }
24}
25
26impl core::error::Error for ShapeMismatchError {}
27
28#[derive(Debug, Clone)]
33pub struct AllocError {
34 pub shape: &'static Shape,
36 pub operation: &'static str,
38}
39
40impl core::fmt::Display for AllocError {
41 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
42 write!(f, "failed to allocate {}: {}", self.shape, self.operation)
43 }
44}
45
46impl core::error::Error for AllocError {}
47
48#[allow(missing_docs)]
50#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
51#[non_exhaustive]
52pub enum TrackerKind {
53 Scalar,
54 Array,
55 Struct,
56 SmartPointer,
57 SmartPointerSlice,
58 Enum,
59 List,
60 Map,
61 Set,
62 Option,
63 Result,
64 DynamicValue,
65 Inner,
66}
67
68#[derive(Clone)]
70pub struct ReflectError {
71 pub path: Path,
73
74 pub kind: ReflectErrorKind,
76}
77
78impl ReflectError {
79 #[inline]
81 pub fn new(kind: ReflectErrorKind, path: Path) -> Self {
82 Self { path, kind }
83 }
84}
85
86#[derive(Clone)]
88#[non_exhaustive]
89pub enum ReflectErrorKind {
90 NoSuchVariant {
92 enum_type: EnumType,
94 },
95
96 WrongShape {
99 expected: &'static Shape,
101 actual: &'static Shape,
103 },
104
105 WasNotA {
107 expected: &'static str,
109
110 actual: &'static Shape,
112 },
113
114 UninitializedField {
116 shape: &'static Shape,
118 field_name: &'static str,
120 },
121
122 UninitializedValue {
124 shape: &'static Shape,
126 },
127
128 ValidationFailed {
130 shape: &'static Shape,
132 field_name: &'static str,
134 message: alloc::string::String,
136 },
137
138 InvariantViolation {
140 invariant: &'static str,
142 },
143
144 MissingCharacteristic {
146 shape: &'static Shape,
148 characteristic: Characteristic,
150 },
151
152 OperationFailed {
154 shape: &'static Shape,
156 operation: &'static str,
158 },
159
160 #[cfg(feature = "alloc")]
161 OperationFailedOwned {
163 shape: &'static Shape,
165 operation: alloc::string::String,
167 },
168
169 ParseFailed {
171 shape: &'static Shape,
173 input: alloc::string::String,
175 },
176
177 FieldError {
179 shape: &'static Shape,
181 field_error: FieldError,
183 },
184
185 NotPod {
191 shape: &'static Shape,
193 },
194
195 MissingPushPointee {
198 shape: &'static Shape,
200 },
201
202 Unknown,
204
205 TryFromError {
207 src_shape: &'static Shape,
209
210 dst_shape: &'static Shape,
212
213 inner: TryFromError,
215 },
216
217 DefaultAttrButNoDefaultImpl {
219 shape: &'static Shape,
221 },
222
223 Unsized {
225 shape: &'static Shape,
227 operation: &'static str,
229 },
230
231 ArrayNotFullyInitialized {
233 shape: &'static Shape,
235 pushed_count: usize,
237 expected_size: usize,
239 },
240
241 ArrayIndexOutOfBounds {
243 shape: &'static Shape,
245 index: usize,
247 size: usize,
249 },
250
251 InvalidOperation {
253 operation: &'static str,
255 reason: &'static str,
257 },
258
259 UnexpectedTracker {
261 message: &'static str,
264
265 current_tracker: TrackerKind,
267 },
268
269 NoActiveFrame,
271
272 #[cfg(feature = "alloc")]
273 CustomDeserializationError {
275 message: alloc::string::String,
277 src_shape: &'static Shape,
279 dst_shape: &'static Shape,
281 },
282
283 #[cfg(feature = "alloc")]
284 UserInvariantFailed {
286 message: alloc::string::String,
288 shape: &'static Shape,
290 },
291
292 #[cfg(feature = "alloc")]
293 CustomSerializationError {
295 message: alloc::string::String,
297 src_shape: &'static Shape,
299 dst_shape: &'static Shape,
301 },
302}
303
304impl core::fmt::Display for ReflectError {
305 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
306 write!(f, "{} at {}", self.kind, self.path)
307 }
308}
309
310impl core::fmt::Display for ReflectErrorKind {
311 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
312 match self {
313 ReflectErrorKind::NoSuchVariant { enum_type } => {
314 write!(f, "No such variant in enum. Known variants: ")?;
315 for v in enum_type.variants {
316 write!(f, ", {}", v.name)?;
317 }
318 write!(f, ", that's it.")
319 }
320 ReflectErrorKind::WrongShape { expected, actual } => {
321 write!(f, "Wrong shape: expected {expected}, but got {actual}")
322 }
323 ReflectErrorKind::WasNotA { expected, actual } => {
324 write!(f, "Wrong shape: expected {expected}, but got {actual}")
325 }
326 ReflectErrorKind::UninitializedField { shape, field_name } => {
327 write!(
328 f,
329 "Field '{shape}::{field_name}' was not initialized. \
330 If you need to leave fields partially initialized and come back later, \
331 use deferred mode (begin_deferred/finish_deferred)"
332 )
333 }
334 ReflectErrorKind::UninitializedValue { shape } => {
335 write!(
336 f,
337 "Value '{shape}' was not initialized. \
338 If you need to leave values partially initialized and come back later, \
339 use deferred mode (begin_deferred/finish_deferred)"
340 )
341 }
342 ReflectErrorKind::ValidationFailed {
343 shape,
344 field_name,
345 message,
346 } => {
347 write!(
348 f,
349 "Validation failed for field '{shape}::{field_name}': {message}"
350 )
351 }
352 ReflectErrorKind::InvariantViolation { invariant } => {
353 write!(f, "Invariant violation: {invariant}")
354 }
355 ReflectErrorKind::MissingCharacteristic {
356 shape,
357 characteristic,
358 } => write!(
359 f,
360 "{shape} does not implement characteristic {characteristic:?}",
361 ),
362 ReflectErrorKind::OperationFailed { shape, operation } => {
363 write!(f, "Operation failed on shape {shape}: {operation}")
364 }
365 #[cfg(feature = "alloc")]
366 ReflectErrorKind::OperationFailedOwned { shape, operation } => {
367 write!(f, "Operation failed on shape {shape}: {operation}")
368 }
369 ReflectErrorKind::ParseFailed { shape, input } => {
370 write!(f, "failed to parse \"{input}\" as {shape}")
371 }
372 ReflectErrorKind::FieldError { shape, field_error } => {
373 write!(f, "Field error for shape {shape}: {field_error}")
374 }
375 ReflectErrorKind::NotPod { shape } => {
376 write!(
377 f,
378 "Cannot mutate fields of '{shape}' - it is not POD (Plain Old Data). \
379 Add #[facet(pod)] to the struct to enable field mutation. \
380 (Wholesale replacement via Poke::set() is always allowed.)"
381 )
382 }
383 ReflectErrorKind::MissingPushPointee { shape } => {
384 write!(
385 f,
386 "Tried to access a field on smart pointer '{shape}', but you need to call .begin_smart_ptr() first to work with the value it points to (and pop it with .pop() later)"
387 )
388 }
389 ReflectErrorKind::Unknown => write!(f, "Unknown error"),
390 ReflectErrorKind::TryFromError {
391 src_shape,
392 dst_shape,
393 inner,
394 } => {
395 write!(
396 f,
397 "While trying to put {src_shape} into a {dst_shape}: {inner}"
398 )
399 }
400 ReflectErrorKind::DefaultAttrButNoDefaultImpl { shape } => write!(
401 f,
402 "Shape '{shape}' has a `default` attribute but no default implementation"
403 ),
404 ReflectErrorKind::Unsized { shape, operation } => write!(
405 f,
406 "Shape '{shape}' is unsized, can't perform operation {operation}"
407 ),
408 ReflectErrorKind::ArrayNotFullyInitialized {
409 shape,
410 pushed_count,
411 expected_size,
412 } => {
413 write!(
414 f,
415 "Array '{shape}' not fully initialized: expected {expected_size} elements, but got {pushed_count}"
416 )
417 }
418 ReflectErrorKind::ArrayIndexOutOfBounds { shape, index, size } => {
419 write!(
420 f,
421 "Array index {index} out of bounds for '{shape}' (array length is {size})"
422 )
423 }
424 ReflectErrorKind::InvalidOperation { operation, reason } => {
425 write!(f, "Invalid operation '{operation}': {reason}")
426 }
427 ReflectErrorKind::UnexpectedTracker {
428 message,
429 current_tracker,
430 } => {
431 write!(f, "{message}: current tracker is {current_tracker:?}")
432 }
433 ReflectErrorKind::NoActiveFrame => {
434 write!(f, "No active frame in Partial")
435 }
436 #[cfg(feature = "alloc")]
437 ReflectErrorKind::CustomDeserializationError {
438 message,
439 src_shape,
440 dst_shape,
441 } => {
442 write!(
443 f,
444 "Custom deserialization of shape '{src_shape}' into '{dst_shape}' failed: {message}"
445 )
446 }
447 #[cfg(feature = "alloc")]
448 ReflectErrorKind::CustomSerializationError {
449 message,
450 src_shape,
451 dst_shape,
452 } => {
453 write!(
454 f,
455 "Custom serialization of shape '{src_shape}' into '{dst_shape}' failed: {message}"
456 )
457 }
458 #[cfg(feature = "alloc")]
459 ReflectErrorKind::UserInvariantFailed { message, shape } => {
460 write!(f, "Invariant check failed for '{shape}': {message}")
461 }
462 }
463 }
464}
465
466impl core::fmt::Debug for ReflectError {
467 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
468 f.debug_struct("ReflectError")
469 .field("path", &self.path)
470 .field("kind", &self.kind)
471 .finish()
472 }
473}
474
475impl core::fmt::Debug for ReflectErrorKind {
476 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
477 write!(f, "ReflectErrorKind({self})")
479 }
480}
481
482impl core::error::Error for ReflectError {}
483impl core::error::Error for ReflectErrorKind {}
484
485impl From<AllocError> for ReflectError {
486 fn from(e: AllocError) -> Self {
487 ReflectError {
488 path: Path::new(e.shape),
489 kind: ReflectErrorKind::OperationFailed {
490 shape: e.shape,
491 operation: e.operation,
492 },
493 }
494 }
495}