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