facet_reflect/
error.rs

1use facet_core::{Characteristic, EnumType, Field, FieldError, Shape, TryFromError};
2use owo_colors::OwoColorize;
3
4/// Errors that can occur when reflecting on types.
5#[derive(Debug, PartialEq, Clone)]
6#[non_exhaustive]
7pub enum ReflectError {
8    /// Tried to `build` or `build_in_place` a struct/enum without initializing all fields.
9    PartiallyInitialized {
10        /// The field that was not initialized.
11        field: Field,
12    },
13
14    /// Tried to set an enum to a variant that does not exist
15    NoSuchVariant {
16        /// The enum definition containing all known variants.
17        enum_type: EnumType,
18    },
19
20    /// Tried to get the wrong shape out of a value — e.g. we were manipulating
21    /// a `String`, but `.get()` was called with a `u64` or something.
22    WrongShape {
23        /// The expected shape of the value.
24        expected: &'static Shape,
25        /// The actual shape of the value.
26        actual: &'static Shape,
27    },
28
29    /// Attempted to perform an operation that expected a struct or something
30    WasNotA {
31        /// The name of the expected type.
32        expected: &'static str,
33
34        /// The type we got instead
35        actual: &'static Shape,
36    },
37
38    /// A field was not initialized during build
39    UninitializedField {
40        /// The shape containing the field
41        shape: &'static Shape,
42        /// The name of the field that wasn't initialized
43        field_name: &'static str,
44    },
45
46    /// A field in an enum variant was not initialized during build
47    UninitializedEnumField {
48        /// The enum shape
49        shape: &'static Shape,
50        /// The name of the field that wasn't initialized
51        field_name: &'static str,
52        /// The name of the variant containing the field
53        variant_name: &'static str,
54    },
55
56    /// An enum had no variant selected during build
57    NoVariantSelected {
58        /// The enum shape
59        shape: &'static Shape,
60    },
61
62    /// A scalar value was not initialized during build
63    UninitializedValue {
64        /// The scalar shape
65        shape: &'static Shape,
66    },
67
68    /// An invariant of the reflection system was violated.
69    InvariantViolation {
70        /// The invariant that was violated.
71        invariant: &'static str,
72    },
73
74    /// Attempted to set a value to its default, but the value doesn't implement `Default`.
75    MissingCharacteristic {
76        /// The shape of the value that doesn't implement `Default`.
77        shape: &'static Shape,
78        /// The characteristic that is missing.
79        characteristic: Characteristic,
80    },
81
82    /// An operation failed for a given shape
83    OperationFailed {
84        /// The shape of the value for which the operation failed.
85        shape: &'static Shape,
86        /// The name of the operation that failed.
87        operation: &'static str,
88    },
89
90    /// An error occurred when attempting to access or modify a field.
91    FieldError {
92        /// The shape of the value containing the field.
93        shape: &'static Shape,
94        /// The specific error that occurred with the field.
95        field_error: FieldError,
96    },
97
98    /// An unknown error occurred.
99    Unknown,
100
101    /// An error occured while putting
102    TryFromError {
103        /// The shape of the value being converted from.
104        src_shape: &'static Shape,
105
106        /// The shape of the value being converted to.
107        dst_shape: &'static Shape,
108
109        /// The inner error
110        inner: TryFromError,
111    },
112
113    /// A shape has a `default` attribute, but no implementation of the `Default` trait.
114    DefaultAttrButNoDefaultImpl {
115        /// The shape of the value that has a `default` attribute but no default implementation.
116        shape: &'static Shape,
117    },
118
119    /// The type is unsized
120    Unsized {
121        /// The shape for the type that is unsized
122        shape: &'static Shape,
123    },
124
125    /// Array not fully initialized during build
126    ArrayNotFullyInitialized {
127        /// The shape of the array
128        shape: &'static Shape,
129        /// The number of elements pushed
130        pushed_count: usize,
131        /// The expected array size
132        expected_size: usize,
133    },
134
135    /// Array index out of bounds
136    ArrayIndexOutOfBounds {
137        /// The shape of the array
138        shape: &'static Shape,
139        /// The index that was out of bounds
140        index: usize,
141        /// The array size
142        size: usize,
143    },
144}
145
146impl core::fmt::Display for ReflectError {
147    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
148        match self {
149            ReflectError::PartiallyInitialized { field } => {
150                write!(
151                    f,
152                    "Value partially initialized: field {} was not set",
153                    field.name.yellow()
154                )
155            }
156            ReflectError::NoSuchVariant { enum_type } => {
157                write!(f, "No such variant in enum. Known variants: ")?;
158                for v in enum_type.variants {
159                    write!(f, ", {}", v.name.cyan())?;
160                }
161                write!(f, ", that's it.")
162            }
163            ReflectError::WrongShape { expected, actual } => {
164                write!(
165                    f,
166                    "Wrong shape: expected {}, but got {}",
167                    expected.green(),
168                    actual.red()
169                )
170            }
171            ReflectError::WasNotA { expected, actual } => {
172                write!(
173                    f,
174                    "Wrong shape: expected {}, but got {}",
175                    expected.green(),
176                    actual.red()
177                )
178            }
179            ReflectError::UninitializedField { shape, field_name } => {
180                write!(f, "Field '{}::{}' was not initialized", shape, field_name)
181            }
182            ReflectError::UninitializedEnumField {
183                shape,
184                field_name,
185                variant_name,
186            } => {
187                write!(
188                    f,
189                    "Field '{}::{}' in variant '{}' was not initialized",
190                    shape.blue(),
191                    field_name.yellow(),
192                    variant_name.red()
193                )
194            }
195            ReflectError::NoVariantSelected { shape } => {
196                write!(f, "Enum '{}' had no variant selected", shape.blue())
197            }
198            ReflectError::UninitializedValue { shape } => {
199                write!(f, "Value '{}' was not initialized", shape.blue())
200            }
201            ReflectError::InvariantViolation { invariant } => {
202                write!(f, "Invariant violation: {}", invariant.red())
203            }
204            ReflectError::MissingCharacteristic {
205                shape,
206                characteristic,
207            } => write!(
208                f,
209                "{shape} does not implement characteristic {characteristic:?}",
210            ),
211            ReflectError::OperationFailed { shape, operation } => {
212                write!(
213                    f,
214                    "Operation failed on shape {}: {}",
215                    shape.blue(),
216                    operation
217                )
218            }
219            ReflectError::FieldError { shape, field_error } => {
220                write!(f, "Field error for shape {}: {}", shape.red(), field_error)
221            }
222            ReflectError::Unknown => write!(f, "Unknown error"),
223            ReflectError::TryFromError {
224                src_shape,
225                dst_shape,
226                inner,
227            } => {
228                write!(
229                    f,
230                    "While trying to put {} into a {}: {}",
231                    src_shape.green(),
232                    dst_shape.blue(),
233                    inner.red()
234                )
235            }
236            ReflectError::DefaultAttrButNoDefaultImpl { shape } => write!(
237                f,
238                "Shape '{}' has a `default` attribute but no default implementation",
239                shape.red()
240            ),
241            ReflectError::Unsized { shape } => write!(f, "Shape '{}' is unsized", shape.red()),
242            ReflectError::ArrayNotFullyInitialized {
243                shape,
244                pushed_count,
245                expected_size,
246            } => {
247                write!(
248                    f,
249                    "Array '{}' not fully initialized: expected {} elements, but got {}",
250                    shape.blue(),
251                    expected_size,
252                    pushed_count
253                )
254            }
255            ReflectError::ArrayIndexOutOfBounds { shape, index, size } => {
256                write!(
257                    f,
258                    "Array index {} out of bounds for '{}' (array length is {})",
259                    index,
260                    shape.blue(),
261                    size
262                )
263            }
264        }
265    }
266}
267
268impl core::error::Error for ReflectError {}