ContextHandler

Trait ContextHandler 

Source
pub trait ContextHandler<C>: 'static {
    // Required methods
    fn source(value: &C) -> Option<&(dyn Error + 'static)>;
    fn display(value: &C, formatter: &mut Formatter<'_>) -> Result;
    fn debug(value: &C, formatter: &mut Formatter<'_>) -> Result;

    // Provided method
    fn preferred_formatting_style(
        value: &C,
        report_formatting_function: FormattingFunction,
    ) -> ContextFormattingStyle { ... }
}
Expand description

Trait for implementing custom formatting and error-chaining behavior for report contexts.

This trait defines how a context type should be formatted when displayed or debugged as part of an error report, and how to navigate to its error source (if any).

§When to Implement

You typically don’t need to implement this trait directly. The rootcause library provides built-in handlers (Error, Display, Debug, Any) that cover most use cases.

Implement this trait when you need custom formatting behavior that the built-in handlers don’t provide, such as:

  • Custom source chain navigation for types that don’t implement std::error::Error
  • Special display formatting that differs from the type’s Display implementation
  • Dynamic formatting based on the context value

§Required Methods

  • source: Returns the underlying error source, if any
  • display: Formats the context for display output
  • debug: Formats the context for debug output

§Optional Methods

  • preferred_formatting_style: Specifies whether to use display or debug formatting when embedded in a report. The default implementation always prefers display formatting.

§Examples

use std::error::Error;

use rootcause_internals::handlers::{
    ContextFormattingStyle, ContextHandler, FormattingFunction,
};

// Custom context type
struct CustomError {
    message: String,
    code: i32,
}

// Custom handler with special formatting
struct CustomHandler;

impl ContextHandler<CustomError> for CustomHandler {
    fn source(_context: &CustomError) -> Option<&(dyn Error + 'static)> {
        None
    }

    fn display(context: &CustomError, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "Error {}: {}", context.code, context.message)
    }

    fn debug(context: &CustomError, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(
            f,
            "CustomError {{ code: {}, message: {:?} }}",
            context.code, context.message
        )
    }
}

Required Methods§

Source

fn source(value: &C) -> Option<&(dyn Error + 'static)>

Returns the underlying error source for this context, if any.

This method enables error chain traversal, allowing you to navigate from a context to its underlying cause. It’s used when displaying the full error chain in a report.

§Returns
  • Some(&dyn Error) if this context has an underlying error source
  • None if this context is a leaf in the error chain
§Examples

For types implementing std::error::Error, delegate to their source method:

use std::error::Error;

use rootcause_internals::handlers::ContextHandler;

struct ErrorHandler;

impl<C: Error> ContextHandler<C> for ErrorHandler {
    fn source(context: &C) -> Option<&(dyn Error + 'static)> {
        context.source()
    }
}
Source

fn display(value: &C, formatter: &mut Formatter<'_>) -> Result

Formats the context using display-style formatting.

This method is called when the context needs to be displayed as part of an error report. It should produce human-readable output suitable for end users.

§Examples
use rootcause_internals::handlers::ContextHandler;

struct DisplayHandler;

impl<C: std::fmt::Display + std::fmt::Debug> ContextHandler<C> for DisplayHandler {
    fn source(_context: &C) -> Option<&(dyn std::error::Error + 'static)> {
        None
    }

    fn display(context: &C, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        std::fmt::Display::fmt(context, f)
    }
}
Source

fn debug(value: &C, formatter: &mut Formatter<'_>) -> Result

Formats the context using debug-style formatting.

This method is called when the context needs to be debug-formatted. It should produce detailed output suitable for developers, potentially including internal state and implementation details.

§Examples
use rootcause_internals::handlers::ContextHandler;

struct DebugHandler;

impl<C: std::fmt::Debug> ContextHandler<C> for DebugHandler {
    fn source(_context: &C) -> Option<&(dyn std::error::Error + 'static)> {
        None
    }

    fn display(context: &C, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "Context of type `{}`", core::any::type_name::<C>())
    }

    fn debug(context: &C, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        std::fmt::Debug::fmt(context, f)
    }
}

Provided Methods§

Source

fn preferred_formatting_style( value: &C, report_formatting_function: FormattingFunction, ) -> ContextFormattingStyle

Specifies the preferred formatting style when this context is embedded in a report.

This method allows the handler to choose between display and debug formatting based on how the report itself is being formatted. The default implementation always returns FormattingFunction::Display, meaning the context will use its display method even when the report is being debug-formatted.

§Arguments
  • value: The context value
  • report_formatting_function: How the report itself is being formatted (Display or Debug)
§Default Behavior

The default implementation ignores the report’s formatting style and always uses display formatting. This is the behavior of all built-in handlers.

§Examples

Custom handler that mirrors the report’s formatting:

use rootcause_internals::handlers::{
    ContextFormattingStyle, ContextHandler, FormattingFunction,
};

struct MirrorHandler;

impl<C: std::fmt::Display + std::fmt::Debug> ContextHandler<C> for MirrorHandler {
    fn source(_context: &C) -> Option<&(dyn std::error::Error + 'static)> {
        None
    }

    fn display(context: &C, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        std::fmt::Display::fmt(context, f)
    }

    fn debug(context: &C, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        std::fmt::Debug::fmt(context, f)
    }

    fn preferred_formatting_style(
        _value: &C,
        report_formatting_function: FormattingFunction,
    ) -> ContextFormattingStyle {
        // Use the same formatting as the report
        ContextFormattingStyle {
            function: report_formatting_function,
        }
    }
}

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementors§