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 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
use core::fmt::{Display, Formatter};
/// Errors that can occur when using the Tree traits.
///
/// A `usize` member indicates the key depth where the error occurred.
/// The depth here is the number of names or indices consumed.
/// It is also the number of separators in a path or the length
/// of an indices slice. The [`TreeKey<Y>` recursion depth](crate::TreeKey#recursion-depth)
/// is an upper bound to the key depth here but not equivalent.
///
/// If multiple errors are applicable simultaneously the precedence
/// is as per the order in the enum definition (from high to low).
#[non_exhaustive]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Traversal {
/// The key is valid, but does not exist at runtime.
///
/// This is the case if an [`Option`] using the `Tree*` traits
/// is `None` at runtime. See also [`crate::TreeKey#option`].
Absent(usize),
/// The key ends early and does not reach a leaf node.
TooShort(usize),
/// The key was not found (index parse failure or too large,
/// name not found or invalid).
NotFound(usize),
/// The key is too long and goes beyond a leaf node.
TooLong(usize),
/// A field could not be accessed.
///
/// The `get` or `get_mut` accessor returned an error message.
Access(usize, &'static str),
/// A deserialized leaf value was found to be invalid.
///
/// The `validate` callback returned an error message.
Invalid(usize, &'static str),
}
impl Display for Traversal {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
match self {
Traversal::Absent(depth) => {
write!(f, "Key not currently present (depth: {depth})")
}
Traversal::TooShort(depth) => {
write!(f, "Key too short (depth: {depth})")
}
Traversal::NotFound(depth) => {
write!(f, "Key not found (depth: {depth})")
}
Traversal::TooLong(depth) => {
write!(f, "Key too long (depth: {depth})")
}
Traversal::Access(depth, msg) => {
write!(f, "Access failed (depth: {depth}): {msg}")
}
Traversal::Invalid(depth, msg) => {
write!(f, "Invalid value (depth: {depth}): {msg}")
}
}
}
}
impl Traversal {
/// Pass it up one hierarchy depth level, incrementing its usize depth field by one.
pub fn increment(self) -> Self {
match self {
Self::Absent(i) => Self::Absent(i + 1),
Self::TooShort(i) => Self::TooShort(i + 1),
Self::NotFound(i) => Self::NotFound(i + 1),
Self::TooLong(i) => Self::TooLong(i + 1),
Self::Access(i, msg) => Self::Access(i + 1, msg),
Self::Invalid(i, msg) => Self::Invalid(i + 1, msg),
}
}
/// Return the traversal depth
pub fn depth(&self) -> &usize {
match self {
Self::Absent(i)
| Self::TooShort(i)
| Self::NotFound(i)
| Self::TooLong(i)
| Self::Access(i, _)
| Self::Invalid(i, _) => i,
}
}
}
/// Compound errors
#[non_exhaustive]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Error<E> {
/// Tree traversal error
Traversal(Traversal),
/// The value provided could not be serialized or deserialized
/// or the traversal callback returned an error.
Inner(usize, E),
/// There was an error during finalization.
///
/// The `Deserializer` has encountered an error only after successfully
/// deserializing a value. This is the case if there is additional unexpected data.
/// The `deserialize_by_key()` update takes place but this
/// error will be returned.
///
/// A `Serializer` may write checksums or additional framing data and fail with
/// this error during finalization after the value has been serialized.
Finalization(E),
}
impl<E: core::fmt::Display> Display for Error<E> {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
match self {
Self::Traversal(t) => t.fmt(f),
Self::Inner(depth, error) => {
write!(f, "(De)serialization error (depth: {depth}): {error}")
}
Self::Finalization(error) => {
write!(f, "(De)serializer finalization error: {error}")
}
}
}
}
// Try to extract the Traversal from an Error
impl<E> TryFrom<Error<E>> for Traversal {
type Error = Error<E>;
fn try_from(value: Error<E>) -> Result<Self, Self::Error> {
match value {
Error::Traversal(e) => Ok(e),
e => Err(e),
}
}
}
impl<E> From<Traversal> for Error<E> {
fn from(value: Traversal) -> Self {
Self::Traversal(value)
}
}
impl<E> Error<E> {
/// Pass an [`Error`] up one hierarchy depth level, incrementing its usize depth field by one.
pub fn increment(self) -> Self {
match self {
Self::Traversal(t) => Self::Traversal(t.increment()),
Self::Inner(i, e) => Self::Inner(i + 1, e),
Self::Finalization(e) => Self::Finalization(e),
}
}
}
/// Pass a [`Result`] up one hierarchy depth level, incrementing its usize depth field by one.
pub fn increment_result<E>(result: Result<usize, Error<E>>) -> Result<usize, Error<E>> {
match result {
Ok(i) => Ok(i + 1),
Err(err) => Err(err.increment()),
}
}