Skip to main content

ReportMut

Struct ReportMut 

Source
pub struct ReportMut<'a, Context: ?Sized + 'static = Dynamic, ThreadSafety: 'static = SendSync> { /* private fields */ }
Expand description

A mutable reference to a Report.

ReportMut provides mutable access to a report’s children and attachments while maintaining safe borrowing semantics. Unlike owned reports, mutable references cannot be consumed for chaining operations like Report::context or Report::attach.

§Key Characteristics

  • Not Copy or Clone: Ensures exclusive mutable access
  • Lifetime-bound: Tied to the lifetime of the underlying report
  • Two type parameters: Has context type C and thread safety marker T (no ownership marker since mutable references are always uniquely owned)

§Thread Safety

Unlike Report and ReportRef, you cannot change the thread safety marker on ReportMut:

  • You cannot convert SendSyncLocal because that would allow adding non-thread-safe data to a report that should remain thread-safe
  • You cannot convert LocalSendSync because that would allow cloning a child report with thread-local data and sending it across threads

§Common Usage

use rootcause::{ReportMut, prelude::*};

let mut report: Report = report!("error message");

// Get mutable access to modify children or attachments
let mut report_mut: ReportMut<'_> = report.as_mut();
report_mut
    .children_mut()
    .push(report!("child error").into_cloneable());

println!("{}", report);

Implementations§

Source§

impl<'a, C: Sized, T> ReportMut<'a, C, T>

Source

pub fn current_context(&self) -> &C

Returns a reference to the current context.

§Examples
let report_mut: ReportMut<'_, MyError> = report.as_mut();
let context: &MyError = report_mut.current_context();
Source

pub fn current_context_mut(&mut self) -> &mut C

Returns a mutable reference to the current context.

§Examples
let mut report_mut: ReportMut<'_, String> = report.as_mut();
let context: &mut String = report_mut.current_context_mut();
context.push_str(" and that's bad");
Source

pub fn into_current_context_mut(self) -> &'a mut C

Turns the ReportMut into a mutable reference to the current context with the same lifetime.

§Examples
let report_mut: ReportMut<'_, String> = report.as_mut();
let context: &mut String = report_mut.into_current_context_mut();
context.push_str(" and that's bad");
Source§

impl<'a, C: ?Sized, T> ReportMut<'a, C, T>

Source

pub fn children(&self) -> &ReportCollection<Dynamic, T>

Returns an immutable reference to the child reports.

§Examples
let mut report: Report = report!("error message");
let report_mut: ReportMut<'_> = report.as_mut();
let children: &ReportCollection = report_mut.children();
assert_eq!(children.len(), 0); // The report has just been created, so it has no children
Source

pub fn children_mut(&mut self) -> &mut ReportCollection<Dynamic, T>

Returns a mutable reference to the child reports.

§Examples
let mut report_mut: ReportMut<'_> = report.as_mut();
let children_mut: &mut ReportCollection = report_mut.children_mut();
Source

pub fn into_children_mut(self) -> &'a mut ReportCollection<Dynamic, T>

Consumes the ReportMut and returns a mutable reference to the child reports with the same lifetime.

§Examples
let report_mut: ReportMut<'_> = report.as_mut();
let children_mut: &mut ReportCollection = report_mut.into_children_mut();
Source

pub fn attachments(&self) -> &ReportAttachments<T>

Returns an immutable reference to the attachments.

§Examples
let report_mut: ReportMut<'_> = report.as_mut();
let attachments: &ReportAttachments = report_mut.attachments();
Source

pub fn attachments_mut(&mut self) -> &mut ReportAttachments<T>

Returns a mutable reference to the attachments.

§Examples
let mut report_mut: ReportMut<'_> = report.as_mut();
let attachments_mut: &mut ReportAttachments = report_mut.attachments_mut();
Source

pub fn attach<A>(self, attachment: A) -> Self
where A: ObjectMarkerFor<T> + Display + Debug,

Adds a new attachment.

This is a convenience method used for chaining method calls; it consumes the ReportMut and returns it.

If you want more direct control over the attachments, you can use the ReportMut::attachments_mut.

§Examples
let mut report: Report = report!("error message");
let mut report_mut = report.as_mut();
report_mut = report_mut.attach("additional info");
Source

pub fn attach_custom<H, A>(self, attachment: A) -> Self

Adds a new attachment.

This is a convenience method used for chaining method calls; it consumes the Report and returns it.

If you want more direct control over the attachments, you can use the Report::attachments_mut.

§Examples
let mut report: Report = report!("error message");
let mut report_mut = report.as_mut();
report_mut = report_mut.attach_custom::<handlers::Display, _>("info");
Source

pub fn into_attachments_mut(self) -> &'a mut ReportAttachments<T>

Consumes the ReportMut and returns a mutable reference to the attachments with the same lifetime.

§Examples
let report_mut: ReportMut<'_> = report.as_mut();
let attachments_mut: &mut ReportAttachments = report_mut.into_attachments_mut();
Source

pub fn into_dynamic(self) -> ReportMut<'a, Dynamic, T>

Changes the context type of the ReportMut to Dynamic.

Calling this method is equivalent to calling report.into(), however this method has been restricted to only change the context mode to Dynamic.

This method can be useful to help with type inference or to improve code readability, as it more clearly communicates intent.

This method does not actually modify the report in any way. It only has the effect of “forgetting” that the context actually has the type C.

To get back the report with a concrete C you can use the method ReportMut::downcast_report.

§Examples
let report: ReportMut<'_, MyError> = report.as_mut();
let local_report: ReportMut<'_, Dynamic> = report.into_dynamic();
Source

pub fn as_ref(&self) -> ReportRef<'_, C, Uncloneable, T>

Returns an immutable reference to the report.

§Examples
let report_mut: ReportMut<'_, MyError> = report.as_mut();
let report_ref: ReportRef<'_, MyError, markers::Uncloneable> = report_mut.as_ref();
Source

pub fn into_ref(self) -> ReportRef<'a, C, Uncloneable, T>

Consumes the ReportMut and returns a ReportRef with same lifetime.

§Examples
let report_mut: ReportMut<'_, MyError> = report.as_mut();
let report_ref: ReportRef<'_, MyError, markers::Uncloneable> = report_mut.into_ref();
Source

pub fn as_mut(&mut self) -> ReportMut<'_, C, T>

Reborrows the ReportMut to return a new ReportMut with a shorter lifetime

§Examples
let mut report_mut: ReportMut<'_, MyError> = report.as_mut();
{
    // Create a new mutable reference with a shorter lifetime
    let mut borrowed_report_mut: ReportMut<'_, MyError> = report_mut.as_mut();
}
// After dropping the inner reference report, we can still use the outer one
let _context: &MyError = report_mut.current_context();
Source

pub fn iter_reports(&self) -> ReportIter<'_, Uncloneable, T>

Returns an iterator over the complete report hierarchy including this report.

The iterator visits reports in a depth-first order: it first visits the current report, then recursively visits each child report and all of their descendants before moving to the next sibling. Unlike ReportMut::iter_sub_reports, this method includes the report on which it was called as the first item in the iteration.

Since this is a mutable reference, the returned iterator references are Uncloneable to ensure proper borrowing semantics.

See also: ReportMut::iter_sub_reports for iterating only over child reports with cloneable references.

§Examples
// Create base reports
let error1: Report = report!("error 1");
let error2: Report = report!("error 2");

// Build hierarchy using .context() which creates new nodes
let with_context1 = error1.context("context for error 1");
let with_context2 = error2.context("context for error 2");

// Create root that contains both context nodes as children
let mut root = report!("root error").context("context for root error");
root.children_mut()
    .push(with_context1.into_dynamic().into_cloneable());
root.children_mut()
    .push(with_context2.into_dynamic().into_cloneable());

let root_mut: ReportMut<'_, &'static str> = root.as_mut();

let all_reports: Vec<String> = root_mut
    .iter_reports()
    .map(|report| report.format_current_context().to_string())
    .collect();

assert_eq!(all_reports[0], "context for root error"); // Current report is included
assert_eq!(all_reports[1], "root error");
assert_eq!(all_reports[2], "context for error 1");
assert_eq!(all_reports.len(), 6);
Source

pub fn iter_sub_reports(&self) -> ReportIter<'_, Cloneable, T>

Returns an iterator over child reports in the report hierarchy (excluding this report).

The iterator visits reports in a depth-first order: it first visits the current report’s children, then recursively visits each child report and all of their descendants before moving to the next sibling. Unlike ReportMut::iter_reports, this method does NOT include the report on which it was called - only its descendants.

This method always returns cloneable report references, making it suitable for scenarios where you need to store or pass around the report references.

See also: ReportMut::iter_reports for iterating over all reports including the current one.

§Examples
// Create base reports
let error1: Report = report!("error 1");
let error2: Report = report!("error 2");

// Build hierarchy using .context() which creates new nodes
let with_context1 = error1.context("context for error 1");
let with_context2 = error2.context("context for error 2");

// Create root that contains both context nodes as children
let mut root = report!("root error").context("context for root error");
root.children_mut()
    .push(with_context1.into_dynamic().into_cloneable());
root.children_mut()
    .push(with_context2.into_dynamic().into_cloneable());

let root_mut: ReportMut<'_, &'static str> = root.as_mut();

let sub_reports: Vec<String> = root_mut
    .iter_sub_reports()
    .map(|report| report.format_current_context().to_string())
    .collect();

// Current "root" report is NOT included in the results
assert_eq!(sub_reports[0], "root error");
assert_eq!(sub_reports[1], "context for error 1");
assert_eq!(sub_reports.len(), 5);
Source

pub fn preformat(&self) -> Report<PreformattedContext, Mutable, SendSync>

Creates a new report, which has the same structure as the current report, but has all the contexts and attachments preformatted.

This can be useful, as the new report is mutable because it was just created, and additionally the new report is Send+Sync.

§Examples
let report_mut: ReportMut<'_, NonSendSyncError, markers::Local> = report.as_mut();
let preformatted: Report<PreformattedContext, markers::Mutable, markers::SendSync> =
    report_mut.preformat();
assert_eq!(format!("{report}"), format!("{preformatted}"));
Source

pub fn current_context_type_id(&self) -> TypeId

Returns the TypeId of the current context.

§Examples
let report_mut: ReportMut<'_, MyError> = report.as_mut();
let type_id = report_mut.current_context_type_id();
assert_eq!(type_id, TypeId::of::<MyError>());

let report_mut: ReportMut<'_, Dynamic> = report_mut.into_dynamic();
let type_id = report_mut.current_context_type_id();
assert_eq!(type_id, TypeId::of::<MyError>());
Source

pub fn current_context_type_name(&self) -> &'static str

Returns the core::any::type_name of the current context.

§Examples
let report_mut: ReportMut<'_, MyError> = report.as_mut();
let type_name = report_mut.current_context_type_name();
assert_eq!(type_name, core::any::type_name::<MyError>());

let report_mut: ReportMut<'_, Dynamic> = report_mut.into_dynamic();
let type_name = report_mut.current_context_type_name();
assert_eq!(type_name, core::any::type_name::<MyError>());
Source

pub fn current_context_handler_type_id(&self) -> TypeId

Returns the TypeId of the handler used for the current context.

This can be useful for debugging or introspection to understand which handler was used to format the context.

§Examples
let mut report = Report::new_sendsync_custom::<handlers::Debug>("error message");
let report_mut = report.as_mut();
let handler_type = report_mut.current_context_handler_type_id();
assert_eq!(handler_type, TypeId::of::<handlers::Debug>());
Source

pub fn current_context_error_source(&self) -> Option<&(dyn Error + 'static)>

Returns the error source if the context implements Error.

§Examples
let mut report: Report = report!("error message");
let report_mut = report.as_mut();
let source = report_mut.current_context_error_source();
assert!(source.is_none()); // The context does not implement Error, so no source
Source

pub fn format_current_context(&self) -> impl Display + Debug

Formats the current context with hook processing.

§Examples
let mut report: Report = report!("error message");
let report_mut = report.as_mut();
let formatted = report_mut.format_current_context();
println!("{formatted}");
Source

pub fn format_current_context_unhooked(&self) -> impl Display + Debug

Formats the current context without hook processing.

§Examples
let mut report: Report = report!("error message");
let report_mut = report.as_mut();
let formatted = report_mut.format_current_context_unhooked();
println!("{formatted}");
Source

pub fn format_with<H>(&self, hook: &H) -> impl Display + Debug
where H: ReportFormatter,

Formats the entire report using a specific report formatting hook.

This method allows you to format a report with a custom formatter without globally registering it. This is useful for:

  • One-off custom formatting
  • Testing different formatters
  • Using different formatters in different parts of your application

Unlike the default Display and Debug implementations which use the globally registered hook, this method uses the hook you provide directly.

§Examples
use rootcause::{hooks::builtin_hooks::report_formatter::DefaultReportFormatter, prelude::*};

let mut report = report!("error message");
let report_mut = report.as_mut();

// Format with ASCII-only output (no Unicode or ANSI colors)
let formatted = report_mut.format_with(&DefaultReportFormatter::ASCII);
println!("{}", formatted);
Source

pub fn preferred_context_formatting_style( &self, report_formatting_function: FormattingFunction, ) -> ContextFormattingStyle

Gets the preferred formatting style for the context with hook processing.

§Arguments
  • report_formatting_function: Whether the report in which this context will be embedded is being formatted using Display formatting or Debug
§Examples
let mut report: Report = report!("error message");
let report_mut = report.as_mut();
let style =
    report_mut.preferred_context_formatting_style(handlers::FormattingFunction::Display);
Source

pub fn preferred_context_formatting_style_unhooked( &self, report_formatting_function: FormattingFunction, ) -> ContextFormattingStyle

Gets the preferred formatting style for the context without hook processing.

§Arguments
  • report_formatting_function: Whether the report in which this context will be embedded is being formatted using Display formatting or Debug
§Examples
let mut report: Report = report!("error message");
let report_mut = report.as_mut();
let style = report_mut
    .preferred_context_formatting_style_unhooked(handlers::FormattingFunction::Display);
Source

pub fn strong_count(&self) -> usize

Returns the number of references to this report.

§Examples
let mut report: Report = report!("error message");
let report_mut = report.as_mut();
assert_eq!(report_mut.strong_count(), 1);
Source§

impl<'a, T> ReportMut<'a, Dynamic, T>

Source

pub fn downcast_current_context<C>(&self) -> Option<&C>
where C: Sized + 'static,

Attempts to downcast the current context to a specific type.

Returns Some(&C) if the current context is of type C, otherwise returns None.

§Examples
let report: Report<MyError> = report!(MyError);
let mut dyn_report: Report = report.into_dynamic();
let mut_report = dyn_report.as_mut();
let context: Option<&MyError> = mut_report.downcast_current_context();
assert!(context.is_some());
Source

pub fn downcast_current_context_mut<C>(&mut self) -> Option<&mut C>
where C: Sized + 'static,

Attempts to downcast the current context to a specific type.

Returns Some(&mut C) if the current context is of type C, otherwise returns None.

§Examples
let report: Report<MyError> = report!(MyError);
let mut dyn_report: Report = report.into_dynamic();
let mut mut_report = dyn_report.as_mut();
let context: Option<&mut MyError> = mut_report.downcast_current_context_mut();
assert!(context.is_some());
Source

pub unsafe fn downcast_current_context_unchecked<C>(&self) -> &C
where C: Sized + 'static,

Downcasts the current context to a specific type without checking.

§Safety

The caller must ensure:

  1. The current context is actually of type C (can be verified by calling current_context_type_id() first)
§Examples
let report: Report<MyError> = report!(MyError);
let mut dyn_report: Report = report.into_dynamic();
let mut_report = dyn_report.as_mut();

// Verify the type first
if mut_report.current_context_type_id() == TypeId::of::<MyError>() {
    // SAFETY: We verified the type matches
    let context: &MyError = unsafe { mut_report.downcast_current_context_unchecked() };
}
Source

pub unsafe fn downcast_current_context_mut_unchecked<C>(&mut self) -> &mut C
where C: Sized + 'static,

Downcasts the current context to a specific type without checking.

§Safety

The caller must ensure:

  1. The current context is actually of type C (can be verified by calling current_context_type_id() first)
§Examples
let report: Report<MyError> = report!(MyError);
let mut dyn_report: Report = report.into_dynamic();
let mut mut_report = dyn_report.as_mut();

// Verify the type first
if mut_report.current_context_type_id() == TypeId::of::<MyError>() {
    // SAFETY: We verified the type matches
    let context: &mut MyError = unsafe { mut_report.downcast_current_context_mut_unchecked() };
}
Source

pub fn downcast_report<C>( self, ) -> Result<ReportMut<'a, C, T>, ReportMut<'a, Dynamic, T>>
where C: Sized + 'static,

Attempts to downcast the entire report to a specific context type.

Returns Ok(ReportMut<C>) if the current context is of type C, otherwise returns Err(self) with the original report.

§Examples
let report: Report<MyError> = report!(MyError);
let mut dyn_report: Report = report.into_dynamic();
let mut_report = dyn_report.as_mut();
let downcasted: Result<_, _> = mut_report.downcast_report::<MyError>();
assert!(downcasted.is_ok());
Source

pub unsafe fn downcast_report_unchecked<C>(self) -> ReportMut<'a, C, T>
where C: Sized + 'static,

Downcasts the entire report to a specific context type without checking.

§Safety

The caller must ensure:

  1. The current context is actually of type C (can be verified by calling current_context_type_id() first)
§Examples
let report: Report<MyError> = report!(MyError);
let mut dyn_report: Report = report.into_dynamic();
let mut_report = dyn_report.as_mut();

// Verify the type first
if mut_report.current_context_type_id() == TypeId::of::<MyError>() {
    // SAFETY: We verified the type matches
    let downcasted = unsafe { mut_report.downcast_report_unchecked::<MyError>() };
}

Trait Implementations§

Source§

impl<'a, C: ?Sized, T> Debug for ReportMut<'a, C, T>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'a, C: ?Sized, T> Display for ReportMut<'a, C, T>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'a, C: Sized> From<ReportMut<'a, C>> for ReportMut<'a, Dynamic, SendSync>

Source§

fn from(report: ReportMut<'a, C, SendSync>) -> Self

Converts to this type from the input type.
Source§

impl<'a, C: Sized> From<ReportMut<'a, C, Local>> for ReportMut<'a, Dynamic, Local>

Source§

fn from(report: ReportMut<'a, C, Local>) -> Self

Converts to this type from the input type.
Source§

impl<'a, C: ?Sized, T> Unpin for ReportMut<'a, C, T>

Auto Trait Implementations§

§

impl<'a, Context, ThreadSafety> Freeze for ReportMut<'a, Context, ThreadSafety>
where Context: ?Sized,

§

impl<'a, Context, ThreadSafety> RefUnwindSafe for ReportMut<'a, Context, ThreadSafety>
where Context: RefUnwindSafe + ?Sized, ThreadSafety: RefUnwindSafe,

§

impl<'a, Context = Dynamic, ThreadSafety = SendSync> !Send for ReportMut<'a, Context, ThreadSafety>

§

impl<'a, Context = Dynamic, ThreadSafety = SendSync> !Sync for ReportMut<'a, Context, ThreadSafety>

§

impl<'a, Context = Dynamic, ThreadSafety = SendSync> !UnwindSafe for ReportMut<'a, Context, ThreadSafety>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<O> ObjectMarkerFor<Local> for O
where O: 'static,

Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.