1use facet_core::{Characteristic, EnumType, FieldError, Shape, TryFromError};
2
3#[allow(missing_docs)]
5#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
6#[non_exhaustive]
7pub enum TrackerKind {
8 Scalar,
9 Array,
10 Struct,
11 SmartPointer,
12 SmartPointerSlice,
13 Enum,
14 List,
15 Map,
16 Set,
17 Option,
18 Result,
19 DynamicValue,
20}
21
22#[derive(Clone)]
24pub enum ReflectError {
25 NoSuchVariant {
27 enum_type: EnumType,
29 },
30
31 WrongShape {
34 expected: &'static Shape,
36 actual: &'static Shape,
38 },
39
40 WasNotA {
42 expected: &'static str,
44
45 actual: &'static Shape,
47 },
48
49 UninitializedField {
51 shape: &'static Shape,
53 field_name: &'static str,
55 },
56
57 UninitializedEnumField {
59 shape: &'static Shape,
61 field_name: &'static str,
63 variant_name: &'static str,
65 },
66
67 UninitializedValue {
69 shape: &'static Shape,
71 },
72
73 InvariantViolation {
75 invariant: &'static str,
77 },
78
79 MissingCharacteristic {
81 shape: &'static Shape,
83 characteristic: Characteristic,
85 },
86
87 OperationFailed {
89 shape: &'static Shape,
91 operation: &'static str,
93 },
94
95 ParseFailed {
97 shape: &'static Shape,
99 input: alloc::string::String,
101 },
102
103 FieldError {
105 shape: &'static Shape,
107 field_error: FieldError,
109 },
110
111 NotPod {
117 shape: &'static Shape,
119 },
120
121 MissingPushPointee {
124 shape: &'static Shape,
126 },
127
128 Unknown,
130
131 TryFromError {
133 src_shape: &'static Shape,
135
136 dst_shape: &'static Shape,
138
139 inner: TryFromError,
141 },
142
143 DefaultAttrButNoDefaultImpl {
145 shape: &'static Shape,
147 },
148
149 Unsized {
151 shape: &'static Shape,
153 operation: &'static str,
155 },
156
157 ArrayNotFullyInitialized {
159 shape: &'static Shape,
161 pushed_count: usize,
163 expected_size: usize,
165 },
166
167 ArrayIndexOutOfBounds {
169 shape: &'static Shape,
171 index: usize,
173 size: usize,
175 },
176
177 InvalidOperation {
179 operation: &'static str,
181 reason: &'static str,
183 },
184
185 UnexpectedTracker {
187 message: &'static str,
190
191 current_tracker: TrackerKind,
193 },
194
195 NoActiveFrame,
197
198 #[cfg(feature = "alloc")]
199 CustomDeserializationError {
201 message: alloc::string::String,
203 src_shape: &'static Shape,
205 dst_shape: &'static Shape,
207 },
208
209 #[cfg(feature = "alloc")]
210 UserInvariantFailed {
212 message: alloc::string::String,
214 shape: &'static Shape,
216 },
217
218 #[cfg(feature = "alloc")]
219 CustomSerializationError {
221 message: alloc::string::String,
223 src_shape: &'static Shape,
225 dst_shape: &'static Shape,
227 },
228}
229
230impl core::fmt::Display for ReflectError {
231 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
232 match self {
233 ReflectError::NoSuchVariant { enum_type } => {
234 write!(f, "No such variant in enum. Known variants: ")?;
235 for v in enum_type.variants {
236 write!(f, ", {}", v.name)?;
237 }
238 write!(f, ", that's it.")
239 }
240 ReflectError::WrongShape { expected, actual } => {
241 write!(f, "Wrong shape: expected {expected}, but got {actual}")
242 }
243 ReflectError::WasNotA { expected, actual } => {
244 write!(f, "Wrong shape: expected {expected}, but got {actual}")
245 }
246 ReflectError::UninitializedField { shape, field_name } => {
247 write!(
248 f,
249 "Field '{shape}::{field_name}' was not initialized. \
250 If you need to leave fields partially initialized and come back later, \
251 use deferred mode (begin_deferred/finish_deferred)"
252 )
253 }
254 ReflectError::UninitializedEnumField {
255 shape,
256 field_name,
257 variant_name,
258 } => {
259 write!(
260 f,
261 "Field '{shape}::{field_name}' in variant '{variant_name}' was not initialized. \
262 If you need to leave fields partially initialized and come back later, \
263 use deferred mode (begin_deferred/finish_deferred)"
264 )
265 }
266 ReflectError::UninitializedValue { shape } => {
267 write!(
268 f,
269 "Value '{shape}' was not initialized. \
270 If you need to leave values partially initialized and come back later, \
271 use deferred mode (begin_deferred/finish_deferred)"
272 )
273 }
274 ReflectError::InvariantViolation { invariant } => {
275 write!(f, "Invariant violation: {invariant}")
276 }
277 ReflectError::MissingCharacteristic {
278 shape,
279 characteristic,
280 } => write!(
281 f,
282 "{shape} does not implement characteristic {characteristic:?}",
283 ),
284 ReflectError::OperationFailed { shape, operation } => {
285 write!(f, "Operation failed on shape {shape}: {operation}")
286 }
287 ReflectError::ParseFailed { shape, input } => {
288 write!(f, "failed to parse \"{input}\" as {shape}")
289 }
290 ReflectError::FieldError { shape, field_error } => {
291 write!(f, "Field error for shape {shape}: {field_error}")
292 }
293 ReflectError::NotPod { shape } => {
294 write!(
295 f,
296 "Cannot mutate fields of '{shape}' - it is not POD (Plain Old Data). \
297 Add #[facet(pod)] to the struct to enable field mutation. \
298 (Wholesale replacement via Poke::set() is always allowed.)"
299 )
300 }
301 ReflectError::MissingPushPointee { shape } => {
302 write!(
303 f,
304 "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)"
305 )
306 }
307 ReflectError::Unknown => write!(f, "Unknown error"),
308 ReflectError::TryFromError {
309 src_shape,
310 dst_shape,
311 inner,
312 } => {
313 write!(
314 f,
315 "While trying to put {src_shape} into a {dst_shape}: {inner}"
316 )
317 }
318 ReflectError::DefaultAttrButNoDefaultImpl { shape } => write!(
319 f,
320 "Shape '{shape}' has a `default` attribute but no default implementation"
321 ),
322 ReflectError::Unsized { shape, operation } => write!(
323 f,
324 "Shape '{shape}' is unsized, can't perform operation {operation}"
325 ),
326 ReflectError::ArrayNotFullyInitialized {
327 shape,
328 pushed_count,
329 expected_size,
330 } => {
331 write!(
332 f,
333 "Array '{shape}' not fully initialized: expected {expected_size} elements, but got {pushed_count}"
334 )
335 }
336 ReflectError::ArrayIndexOutOfBounds { shape, index, size } => {
337 write!(
338 f,
339 "Array index {index} out of bounds for '{shape}' (array length is {size})"
340 )
341 }
342 ReflectError::InvalidOperation { operation, reason } => {
343 write!(f, "Invalid operation '{operation}': {reason}")
344 }
345 ReflectError::UnexpectedTracker {
346 message,
347 current_tracker,
348 } => {
349 write!(f, "{message}: current tracker is {current_tracker:?}")
350 }
351 ReflectError::NoActiveFrame => {
352 write!(f, "No active frame in Partial")
353 }
354 #[cfg(feature = "alloc")]
355 ReflectError::CustomDeserializationError {
356 message,
357 src_shape,
358 dst_shape,
359 } => {
360 write!(
361 f,
362 "Custom deserialization of shape '{src_shape}' into '{dst_shape}' failed: {message}"
363 )
364 }
365 #[cfg(feature = "alloc")]
366 ReflectError::CustomSerializationError {
367 message,
368 src_shape,
369 dst_shape,
370 } => {
371 write!(
372 f,
373 "Custom serialization of shape '{src_shape}' into '{dst_shape}' failed: {message}"
374 )
375 }
376 #[cfg(feature = "alloc")]
377 ReflectError::UserInvariantFailed { message, shape } => {
378 write!(f, "Invariant check failed for '{shape}': {message}")
379 }
380 }
381 }
382}
383
384impl core::fmt::Debug for ReflectError {
385 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
386 write!(f, "ReflectError({self})")
388 }
389}
390
391impl core::error::Error for ReflectError {}