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
/// 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.
///
/// If multiple errors are applicable simultaneously the precedence
/// is as per the order in the enum definition (from high to low).
#[derive(Debug, Copy, Clone, PartialEq, Eq, thiserror::Error)]
pub enum Traversal {
/// A node does not exist at runtime.
///
/// An `enum` variant in the tree towards the node is currently absent.
/// This is for example the case if an [`Option`] using the `Tree*`
/// traits is `None` at runtime. See also [`crate::TreeKey#option`].
#[error("Variant absent (depth: {0})")]
Absent(usize),
/// The key ends early and does not reach a leaf node.
#[error("Key does not reach a leaf (depth: {0})")]
TooShort(usize),
/// The key was not found (index parse failure or too large,
/// name not found or invalid).
#[error("Key not found (depth: {0})")]
NotFound(usize),
/// The key is too long and goes beyond a leaf node.
#[error("Key goes beyond leaf (depth: {0})")]
TooLong(usize),
/// A node could not be accessed.
///
/// The `get` or `get_mut` accessor returned an error message.
#[error("Node accessor failed (depth: {0}): {1}")]
Access(usize, &'static str),
/// A deserialized leaf value was found to be invalid.
///
/// The `validate` callback returned an error message.
#[error("Invalid value (depth: {0}): {1}")]
Invalid(usize, &'static str),
}
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
#[inline]
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
#[derive(Debug, Copy, Clone, PartialEq, Eq, thiserror::Error)]
pub enum Error<E> {
/// Tree traversal error
#[error(transparent)]
Traversal(#[from] Traversal),
/// The value provided could not be serialized or deserialized
/// or the traversal callback returned an error.
#[error("(De)serialization (depth: {0}): {1}")]
Inner(usize, #[source] 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.
#[error("(De)serializer finalization: {0}")]
Finalization(#[source] E),
}
// Try to extract the Traversal from an Error
impl<E> TryFrom<Error<E>> for Traversal {
type Error = Error<E>;
#[inline]
fn try_from(value: Error<E>) -> Result<Self, Self::Error> {
match value {
Error::Traversal(e) => Ok(e),
e => Err(e),
}
}
}
impl<E> Error<E> {
/// Pass an `Error<E>` up one hierarchy depth level, incrementing its usize depth field by one.
#[inline]
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<usize, Error<E>>` up one hierarchy depth level, incrementing its usize depth field by one.
#[inline]
pub fn increment_result(result: Result<usize, Self>) -> Result<usize, Self> {
match result {
Ok(i) => Ok(i + 1),
Err(err) => Err(err.increment()),
}
}
}