Skip to content

Commit

Permalink
feat: Add ContextualDisplay to TransactionValidationError
Browse files Browse the repository at this point in the history
  • Loading branch information
dhedey committed Nov 26, 2024
1 parent 1b5c173 commit 9c98fde
Show file tree
Hide file tree
Showing 2 changed files with 127 additions and 0 deletions.
34 changes: 34 additions & 0 deletions radix-rust/src/contextual_display.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,21 @@ pub trait ContextualDisplay<Context> {
}
}

/// Returns an object implementing [`fmt::Debug`] using the contextual display implementation.
///
/// Typically you should use [`format`] instead.
///
/// [`format`]: #method.format
fn debug_as_display<'a, 'b, TContext: Into<Context>>(
&'a self,
context: TContext,
) -> ContextDebuggableAsDisplay<'a, Self, Context> {
ContextDebuggableAsDisplay {
value: self,
context: context.into(),
}
}

fn to_string<'a, 'b, TContext: Into<Context>>(&'a self, context: TContext) -> String {
self.display(context).to_string()
}
Expand All @@ -93,3 +108,22 @@ where
.map_err(|_| fmt::Error) // We eat any errors into fmt::Error
}
}

pub struct ContextDebuggableAsDisplay<'a, TValue, TContext>
where
TValue: ContextualDisplay<TContext> + ?Sized,
{
value: &'a TValue,
context: TContext,
}

impl<'a, 'b, TValue, TContext> fmt::Debug for ContextDebuggableAsDisplay<'a, TValue, TContext>
where
TValue: ContextualDisplay<TContext> + ?Sized,
{
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
self.value
.contextual_format(f, &self.context)
.map_err(|_| fmt::Error) // We eat any errors into fmt::Error
}
}
93 changes: 93 additions & 0 deletions radix-transactions/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,41 @@ pub enum TransactionValidationError {
SignatureValidationError(TransactionValidationErrorLocation, SignatureValidationError),
}

impl<'a> ContextualDisplay<TransactionHashDisplayContext<'a>> for TransactionValidationError {
type Error = fmt::Error;

fn contextual_format(
&self,
f: &mut fmt::Formatter,
context: &TransactionHashDisplayContext<'a>,
) -> Result<(), Self::Error> {
match self {
Self::TransactionVersionNotPermitted(arg0) => f
.debug_tuple("TransactionVersionNotPermitted")
.field(arg0)
.finish(),
Self::TransactionTooLarge => write!(f, "TransactionTooLarge"),
Self::EncodeError(arg0) => f.debug_tuple("EncodeError").field(arg0).finish(),
Self::PrepareError(arg0) => f.debug_tuple("PrepareError").field(arg0).finish(),
Self::SubintentStructureError(arg0, arg1) => f
.debug_tuple("SubintentStructureError")
.field(&arg0.debug_as_display(*context))
.field(&arg1.debug_as_display(*context))
.finish(),
Self::IntentValidationError(arg0, arg1) => f
.debug_tuple("IntentValidationError")
.field(&arg0.debug_as_display(*context))
.field(arg1)
.finish(),
Self::SignatureValidationError(arg0, arg1) => f
.debug_tuple("SignatureValidationError")
.field(&arg0.debug_as_display(*context))
.field(arg1)
.finish(),
}
}
}

pub enum IntentSpecifier {
RootTransactionIntent(TransactionIntentHash),
RootSubintent(SubintentHash),
Expand All @@ -93,6 +128,37 @@ impl TransactionValidationErrorLocation {
}
}

impl<'a> ContextualDisplay<TransactionHashDisplayContext<'a>>
for TransactionValidationErrorLocation
{
type Error = fmt::Error;

fn contextual_format(
&self,
f: &mut fmt::Formatter,
context: &TransactionHashDisplayContext<'a>,
) -> Result<(), Self::Error> {
// Copied from the auto-generated `Debug` implementation, and tweaked
match self {
Self::RootTransactionIntent(arg0) => f
.debug_tuple("RootTransactionIntent")
.field(&arg0.debug_as_display(*context))
.finish(),
Self::RootSubintent(arg0) => f
.debug_tuple("RootSubintent")
.field(&arg0.debug_as_display(*context))
.finish(),
Self::NonRootSubintent(arg0, arg1) => f
.debug_tuple("NonRootSubintent")
.field(arg0)
.field(&arg1.debug_as_display(*context))
.finish(),
Self::AcrossTransaction => write!(f, "AcrossTransaction"),
Self::Unlocatable => write!(f, "Unlocatable"),
}
}
}

impl From<PrepareError> for TransactionValidationError {
fn from(value: PrepareError) -> Self {
Self::PrepareError(value)
Expand Down Expand Up @@ -176,6 +242,33 @@ pub enum SubintentStructureError {
MismatchingYieldChildAndYieldParentCountsForSubintent,
}

impl<'a> ContextualDisplay<TransactionHashDisplayContext<'a>> for SubintentStructureError {
type Error = fmt::Error;

fn contextual_format(
&self,
f: &mut fmt::Formatter,
context: &TransactionHashDisplayContext<'a>,
) -> Result<(), Self::Error> {
// Copied from the auto-generated `Debug` implementation, and tweaked
match self {
Self::DuplicateSubintent => write!(f, "DuplicateSubintent"),
Self::SubintentHasMultipleParents => write!(f, "SubintentHasMultipleParents"),
Self::ChildSubintentNotIncludedInTransaction(arg0) => f
.debug_tuple("ChildSubintentNotIncludedInTransaction")
.field(&arg0.debug_as_display(*context))
.finish(),
Self::SubintentExceedsMaxDepth => write!(f, "SubintentExceedsMaxDepth"),
Self::SubintentIsNotReachableFromTheTransactionIntent => {
write!(f, "SubintentIsNotReachableFromTheTransactionIntent")
}
Self::MismatchingYieldChildAndYieldParentCountsForSubintent => {
write!(f, "MismatchingYieldChildAndYieldParentCountsForSubintent")
}
}
}
}

impl SubintentStructureError {
pub fn for_unindexed(self) -> TransactionValidationError {
TransactionValidationError::SubintentStructureError(
Expand Down

0 comments on commit 9c98fde

Please sign in to comment.