Replace DecoderNError implementations with macro
What changed, and why it matters
This commit is a routine code cleanup. It replaces several nearly identical error-type definitions with a single Rust macro, reducing duplicated boilerplate. There is no change to how the library behaves, what data it accepts, or how it handles errors.
No security action needed. Treat as normal refactoring.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The change introduces define_decoder_n_error! and uses it to generate Decoder2Error, Decoder3Error, Decoder4Error, and Decoder6Error. The generated types retain the same enum variants, derives (Debug, Clone, PartialEq, Eq), fmt::Display implementation, and optional std::error::Error implementation. The only functional difference is a minor punctuation change in display messages: the macro version appends a period to the literal strings (e.g., “first decoder error.” vs “first decoder error”). This is cosmetic and does not affect program logic or security.
Changed components
consensus_encoding/src/decode/decoders.rsInspect captured patch +68 / −160
diff --git a/consensus_encoding/src/decode/decoders.rs b/consensus_encoding/src/decode/decoders.rs
index 06abed3d..087ada07 100644
--- a/consensus_encoding/src/decode/decoders.rs
+++ b/consensus_encoding/src/decode/decoders.rs
@@ -923,190 +923,98 @@ impl fmt::Display for UnexpectedEofError {
#[cfg(feature = "std")]
impl std::error::Error for UnexpectedEofError {}
-/// Error type for [`Decoder2`].
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub enum Decoder2Error<A, B> {
- /// Error from the first decoder.
- First(A),
- /// Error from the second decoder.
- Second(B),
-}
+/// Helper macro to define an error type for a `DecoderN`.
+macro_rules! define_decoder_n_error {
+ (
+ $(#[$attr:meta])*
+ $name:ident;
+ $(
+ $(#[$err_attr:meta])*
+ ($err_wrap:ident, $err_type:ident, $err_msg:literal),
+ )*
+ ) => {
+ $(#[$attr])*
+ #[derive(Debug, Clone, PartialEq, Eq)]
+ pub enum $name<$($err_type,)*> {
+ $(
+ $(#[$err_attr])*
+ $err_wrap($err_type),
+ )*
+ }
-impl<A, B> fmt::Display for Decoder2Error<A, B>
-where
- A: fmt::Display,
- B: fmt::Display,
-{
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- match self {
- Self::First(ref e) => write_err!(f, "first decoder error"; e),
- Self::Second(ref e) => write_err!(f, "second decoder error"; e),
+ impl<$($err_type,)*> fmt::Display for $name<$($err_type,)*>
+ where
+ $($err_type: fmt::Display,)*
+ {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match self {
+ $(Self::$err_wrap(ref e) => write_err!(f, $err_msg; e),)*
+ }
+ }
}
- }
-}
-#[cfg(feature = "std")]
-impl<A, B> std::error::Error for Decoder2Error<A, B>
-where
- A: std::error::Error + 'static,
- B: std::error::Error + 'static,
-{
- fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
- match self {
- Self::First(ref e) => Some(e),
- Self::Second(ref e) => Some(e),
+ #[cfg(feature = "std")]
+ impl<$($err_type,)*> std::error::Error for $name<$($err_type,)*>
+ where
+ $($err_type: std::error::Error + 'static,)*
+ {
+ fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
+ match self {
+ $(Self::$err_wrap(ref e) => Some(e),)*
+ }
+ }
}
- }
+ };
}
-/// Error type for [`Decoder3`].
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub enum Decoder3Error<A, B, C> {
+define_decoder_n_error! {
+ /// Error type for [`Decoder2`].
+ Decoder2Error;
/// Error from the first decoder.
- First(A),
+ (First, A, "first decoder error."),
/// Error from the second decoder.
- Second(B),
- /// Error from the third decoder.
- Third(C),
-}
-
-impl<A, B, C> fmt::Display for Decoder3Error<A, B, C>
-where
- A: fmt::Display,
- B: fmt::Display,
- C: fmt::Display,
-{
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- match self {
- Self::First(ref e) => write_err!(f, "first decoder error"; e),
- Self::Second(ref e) => write_err!(f, "second decoder error"; e),
- Self::Third(ref e) => write_err!(f, "third decoder error"; e),
- }
- }
+ (Second, B, "second decoder error."),
}
-#[cfg(feature = "std")]
-impl<A, B, C> std::error::Error for Decoder3Error<A, B, C>
-where
- A: std::error::Error + 'static,
- B: std::error::Error + 'static,
- C: std::error::Error + 'static,
-{
- fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
- match self {
- Self::First(ref e) => Some(e),
- Self::Second(ref e) => Some(e),
- Self::Third(ref e) => Some(e),
- }
- }
+define_decoder_n_error! {
+ /// Error type for [`Decoder3`].
+ Decoder3Error;
+ /// Error from the first decoder.
+ (First, A, "first decoder error."),
+ /// Error from the second decoder.
+ (Second, B, "second decoder error."),
+ /// Error from the third decoder.
+ (Third, C, "third decoder error."),
}
-/// Error type for [`Decoder4`].
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub enum Decoder4Error<A, B, C, D> {
+define_decoder_n_error! {
+ /// Error type for [`Decoder4`].
+ Decoder4Error;
/// Error from the first decoder.
- First(A),
+ (First, A, "first decoder error."),
/// Error from the second decoder.
- Second(B),
+ (Second, B, "second decoder error."),
/// Error from the third decoder.
- Third(C),
+ (Third, C, "third decoder error."),
/// Error from the fourth decoder.
- Fourth(D),
-}
-
-impl<A, B, C, D> fmt::Display for Decoder4Error<A, B, C, D>
-where
- A: fmt::Display,
- B: fmt::Display,
- C: fmt::Display,
- D: fmt::Display,
-{
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- match self {
- Self::First(ref e) => write_err!(f, "first decoder error"; e),
- Self::Second(ref e) => write_err!(f, "second decoder error"; e),
- Self::Third(ref e) => write_err!(f, "third decoder error"; e),
- Self::Fourth(ref e) => write_err!(f, "fourth decoder error"; e),
- }
- }
+ (Fourth, D, "fourth decoder error."),
}
-#[cfg(feature = "std")]
-impl<A, B, C, D> std::error::Error for Decoder4Error<A, B, C, D>
-where
- A: std::error::Error + 'static,
- B: std::error::Error + 'static,
- C: std::error::Error + 'static,
- D: std::error::Error + 'static,
-{
- fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
- match self {
- Self::First(ref e) => Some(e),
- Self::Second(ref e) => Some(e),
- Self::Third(ref e) => Some(e),
- Self::Fourth(ref e) => Some(e),
- }
- }
-}
-
-/// Error type for [`Decoder6`].
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub enum Decoder6Error<A, B, C, D, E, F> {
+define_decoder_n_error! {
+ /// Error type for [`Decoder6`].
+ Decoder6Error;
/// Error from the first decoder.
- First(A),
+ (First, A, "first decoder error."),
/// Error from the second decoder.
- Second(B),
+ (Second, B, "second decoder error."),
/// Error from the third decoder.
- Third(C),
+ (Third, C, "third decoder error."),
/// Error from the fourth decoder.
- Fourth(D),
+ (Fourth, D, "fourth decoder error."),
/// Error from the fifth decoder.
- Fifth(E),
+ (Fifth, E, "fifth decoder error."),
/// Error from the sixth decoder.
- Sixth(F),
-}
-
-impl<A, B, C, D, E, F> fmt::Display for Decoder6Error<A, B, C, D, E, F>
-where
- A: fmt::Display,
- B: fmt::Display,
- C: fmt::Display,
- D: fmt::Display,
- E: fmt::Display,
- F: fmt::Display,
-{
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- match self {
- Self::First(ref e) => write_err!(f, "first decoder error"; e),
- Self::Second(ref e) => write_err!(f, "second decoder error"; e),
- Self::Third(ref e) => write_err!(f, "third decoder error"; e),
- Self::Fourth(ref e) => write_err!(f, "fourth decoder error"; e),
- Self::Fifth(ref e) => write_err!(f, "fifth decoder error"; e),
- Self::Sixth(ref e) => write_err!(f, "sixth decoder error"; e),
- }
- }
-}
-
-#[cfg(feature = "std")]
-impl<A, B, C, D, E, F> std::error::Error for Decoder6Error<A, B, C, D, E, F>
-where
- A: std::error::Error + 'static,
- B: std::error::Error + 'static,
- C: std::error::Error + 'static,
- D: std::error::Error + 'static,
- E: std::error::Error + 'static,
- F: std::error::Error + 'static,
-{
- fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
- match self {
- Self::First(ref e) => Some(e),
- Self::Second(ref e) => Some(e),
- Self::Third(ref e) => Some(e),
- Self::Fourth(ref e) => Some(e),
- Self::Fifth(ref e) => Some(e),
- Self::Sixth(ref e) => Some(e),
- }
- }
+ (Sixth, F, "sixth decoder error."),
}
#[cfg(test)]
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.