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<'_> {}