use core::fmt;
use eth_valkyoth_codec::{DecodeError, DecodeErrorCategory};
#[non_exhaustive]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum MptNodeField {
Node,
CompactPath,
BranchChild,
BranchValue,
ExtensionChild,
LeafValue,
ProofNode,
}
#[non_exhaustive]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum MptNodeDecodeError {
WrongFieldCount {
found: usize,
},
FieldDecode {
field: MptNodeField,
source: DecodeError,
},
EmptyCompactPath,
InvalidCompactPathFlag {
flag: u8,
},
InvalidCompactPathPadding {
found: u8,
},
EmptyNodeReference {
field: MptNodeField,
},
InvalidNodeReferenceLength {
field: MptNodeField,
found: usize,
},
InlineNodeTooLarge {
field: MptNodeField,
found: usize,
},
LengthOverflow,
InlineNodeTooDeep,
}
impl MptNodeDecodeError {
#[must_use]
pub const fn code(self) -> &'static str {
match self {
Self::WrongFieldCount { .. } => "ETH_MPT_WRONG_FIELD_COUNT",
Self::FieldDecode { source, .. } => source.code(),
Self::EmptyCompactPath => "ETH_MPT_EMPTY_COMPACT_PATH",
Self::InvalidCompactPathFlag { .. } => "ETH_MPT_INVALID_COMPACT_PATH_FLAG",
Self::InvalidCompactPathPadding { .. } => "ETH_MPT_INVALID_COMPACT_PATH_PADDING",
Self::EmptyNodeReference { .. } => "ETH_MPT_EMPTY_NODE_REFERENCE",
Self::InvalidNodeReferenceLength { .. } => "ETH_MPT_INVALID_NODE_REFERENCE_LENGTH",
Self::InlineNodeTooLarge { .. } => "ETH_MPT_INLINE_NODE_TOO_LARGE",
Self::LengthOverflow => "ETH_MPT_LENGTH_OVERFLOW",
Self::InlineNodeTooDeep => "ETH_MPT_INLINE_NODE_TOO_DEEP",
}
}
#[must_use]
pub const fn message(self) -> &'static str {
match self {
Self::WrongFieldCount { .. } => "MPT node must have two or seventeen fields",
Self::FieldDecode { .. } => "MPT node field failed bounded decoding",
Self::EmptyCompactPath => "MPT compact path must include a flag byte",
Self::InvalidCompactPathFlag { .. } => {
"MPT compact path uses a reserved hex-prefix flag"
}
Self::InvalidCompactPathPadding { .. } => {
"MPT compact path has nonzero even-path padding"
}
Self::EmptyNodeReference { .. } => "MPT child reference must not be empty",
Self::InvalidNodeReferenceLength { .. } => {
"MPT scalar child reference must be empty or 32 bytes"
}
Self::InlineNodeTooLarge { .. } => {
"MPT inline child reference must be shorter than 32 encoded bytes"
}
Self::LengthOverflow => "MPT length arithmetic overflowed",
Self::InlineNodeTooDeep => "MPT inline child-node depth limit exceeded",
}
}
#[must_use]
pub const fn category(self) -> MptNodeDecodeErrorCategory {
match self {
Self::FieldDecode { source, .. } => match source.category() {
DecodeErrorCategory::ResourceExhaustion => {
MptNodeDecodeErrorCategory::ResourceExhaustion
}
DecodeErrorCategory::MalformedInput => MptNodeDecodeErrorCategory::MalformedInput,
_ => MptNodeDecodeErrorCategory::MalformedInput,
},
Self::WrongFieldCount { .. }
| Self::EmptyCompactPath
| Self::InvalidCompactPathFlag { .. }
| Self::InvalidCompactPathPadding { .. }
| Self::EmptyNodeReference { .. }
| Self::InvalidNodeReferenceLength { .. }
| Self::InlineNodeTooLarge { .. }
| Self::LengthOverflow => MptNodeDecodeErrorCategory::MalformedInput,
Self::InlineNodeTooDeep => MptNodeDecodeErrorCategory::ResourceExhaustion,
}
}
}
impl fmt::Display for MptNodeDecodeError {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str(self.message())
}
}
#[cfg(feature = "std")]
impl std::error::Error for MptNodeDecodeError {}
#[non_exhaustive]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum MptNodeDecodeErrorCategory {
MalformedInput,
ResourceExhaustion,
}