bevy_reflect/path/error.rs
1use core::fmt;
2
3use super::Access;
4use crate::{ReflectKind, VariantType};
5
6/// The kind of [`AccessError`], along with some kind-specific information.
7#[derive(Debug, PartialEq, Eq, Clone)]
8pub enum AccessErrorKind {
9 /// An error that occurs when a certain type doesn't
10 /// contain the value referenced by the [`Access`].
11 MissingField(ReflectKind),
12
13 /// An error that occurs when using an [`Access`] on the wrong type.
14 /// (i.e. a [`ListIndex`](Access::ListIndex) on a struct, or a [`TupleIndex`](Access::TupleIndex) on a list)
15 IncompatibleTypes {
16 /// The [`ReflectKind`] that was expected based on the [`Access`].
17 expected: ReflectKind,
18 /// The actual [`ReflectKind`] that was found.
19 actual: ReflectKind,
20 },
21
22 /// An error that occurs when using an [`Access`] on the wrong enum variant.
23 /// (i.e. a [`ListIndex`](Access::ListIndex) on a struct variant, or a [`TupleIndex`](Access::TupleIndex) on a unit variant)
24 IncompatibleEnumVariantTypes {
25 /// The [`VariantType`] that was expected based on the [`Access`].
26 expected: VariantType,
27 /// The actual [`VariantType`] that was found.
28 actual: VariantType,
29 },
30}
31
32impl AccessErrorKind {
33 pub(super) fn with_access(self, access: Access, offset: Option<usize>) -> AccessError {
34 AccessError {
35 kind: self,
36 access,
37 offset,
38 }
39 }
40}
41
42/// An error originating from an [`Access`] of an element within a type.
43///
44/// Use the `Display` impl of this type to get information on the error.
45///
46/// Some sample messages:
47///
48/// ```text
49/// Error accessing element with `.alpha` access (offset 14): The struct accessed doesn't have an "alpha" field
50/// Error accessing element with '[0]' access: Expected index access to access a list, found a struct instead.
51/// Error accessing element with '.4' access: Expected variant index access to access a Tuple variant, found a Unit variant instead.
52/// ```
53#[derive(Debug, Clone, PartialEq, Eq)]
54pub struct AccessError<'a> {
55 pub(super) kind: AccessErrorKind,
56 pub(super) access: Access<'a>,
57 pub(super) offset: Option<usize>,
58}
59
60impl<'a> AccessError<'a> {
61 /// Returns the kind of [`AccessError`].
62 pub const fn kind(&self) -> &AccessErrorKind {
63 &self.kind
64 }
65
66 /// The returns the [`Access`] that this [`AccessError`] occurred in.
67 pub const fn access(&self) -> &Access {
68 &self.access
69 }
70
71 /// If the [`Access`] was created with a parser or an offset was manually provided,
72 /// returns the offset of the [`Access`] in its path string.
73 pub const fn offset(&self) -> Option<&usize> {
74 self.offset.as_ref()
75 }
76}
77impl fmt::Display for AccessError<'_> {
78 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
79 let AccessError {
80 kind,
81 access,
82 offset,
83 } = self;
84
85 write!(f, "Error accessing element with `{access}` access")?;
86 if let Some(offset) = offset {
87 write!(f, "(offset {offset})")?;
88 }
89 write!(f, ": ")?;
90
91 match kind {
92 AccessErrorKind::MissingField(type_accessed) => {
93 match access {
94 Access::Field(field) => write!(
95 f,
96 "The {type_accessed} accessed doesn't have {} `{}` field",
97 if let Some("a" | "e" | "i" | "o" | "u") = field.get(0..1) {
98 "an"
99 } else {
100 "a"
101 },
102 access.display_value()
103 ),
104 Access::FieldIndex(_) => write!(
105 f,
106 "The {type_accessed} accessed doesn't have field index `{}`",
107 access.display_value(),
108 ),
109 Access::TupleIndex(_) | Access::ListIndex(_) => write!(
110 f,
111 "The {type_accessed} accessed doesn't have index `{}`",
112 access.display_value()
113 )
114 }
115 }
116 AccessErrorKind::IncompatibleTypes { expected, actual } => write!(
117 f,
118 "Expected {} access to access a {expected}, found a {actual} instead.",
119 access.kind()
120 ),
121 AccessErrorKind::IncompatibleEnumVariantTypes { expected, actual } => write!(
122 f,
123 "Expected variant {} access to access a {expected:?} variant, found a {actual:?} variant instead.",
124 access.kind()
125 ),
126 }
127 }
128}
129impl core::error::Error for AccessError<'_> {}