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}
77
78impl fmt::Display for AccessError<'_> {
79    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
80        let AccessError {
81            kind,
82            access,
83            offset,
84        } = self;
85
86        write!(f, "Error accessing element with `{access}` access")?;
87        if let Some(offset) = offset {
88            write!(f, "(offset {offset})")?;
89        }
90        write!(f, ": ")?;
91
92        match kind {
93            AccessErrorKind::MissingField(type_accessed) => {
94                match access {
95                    Access::Field(field) => write!(
96                        f,
97                        "The {type_accessed} accessed doesn't have {} `{}` field",
98                        if let Some("a" | "e" | "i" | "o" | "u") = field.get(0..1) {
99                            "an"
100                        } else {
101                            "a"
102                        },
103                        access.display_value()
104                    ),
105                    Access::FieldIndex(_) => write!(
106                        f,
107                        "The {type_accessed} accessed doesn't have field index `{}`",
108                        access.display_value(),
109                    ),
110                    Access::TupleIndex(_) | Access::ListIndex(_) => write!(
111                        f,
112                        "The {type_accessed} accessed doesn't have index `{}`",
113                        access.display_value()
114                    )
115                }
116            }
117            AccessErrorKind::IncompatibleTypes { expected, actual } => write!(
118                f,
119                "Expected {} access to access a {expected}, found a {actual} instead.",
120                access.kind()
121            ),
122            AccessErrorKind::IncompatibleEnumVariantTypes { expected, actual } => write!(
123                f,
124                "Expected variant {} access to access a {expected:?} variant, found a {actual:?} variant instead.",
125                access.kind()
126            ),
127        }
128    }
129}
130
131impl core::error::Error for AccessError<'_> {}