pub struct Report<Context: ?Sized + 'static = Dynamic, Ownership: 'static = Mutable, ThreadSafety: 'static = SendSync> { /* private fields */ }Expand description
An error report that contains a context, child reports, and attachments.
Report is the main type for creating and working with error reports
in this library. It can contain a root context (typically an error),
zero or more child reports, and zero or more attachments.
§Type Parameters
Report has three type parameters that control its behavior:
- Context (
C): The type of the root error or context (defaults toDynamic) - Ownership (
O): Controls whether the report can be cloned - Thread Safety (
T): Controls whether the report can be sent across threads
§Common Usage
The easiest way to create a Report is with the report!() macro:
let report: Report = report!("file missing");
println!("{report}");You can add context and attachments using method chaining:
let report = report!("database query failed")
.context("failed to fetch user data")
.attach("user_id: 12345");
println!("{report}");Implementations§
Source§impl<C: Sized, T> Report<C, Mutable, T>
impl<C: Sized, T> Report<C, Mutable, T>
Sourcepub fn new(context: C) -> Selfwhere
C: ObjectMarkerFor<T> + Error,
pub fn new(context: C) -> Selfwhere
C: ObjectMarkerFor<T> + Error,
Creates a new Report with the given context.
This method is generic over the thread safety marker T. The context
will use the handlers::Error handler for formatting.
See also:
- The
report!()macro will also create a newReport, but can auto-detect the thread safety marker and handler. Report::new_sendsyncandReport::new_localare more restrictive variants of this function that might help avoid type inference issues.Report::new_customalso allows you to manually specify the handler.
§Examples
let report_sendsync: Report<MyError, Mutable, SendSync> = Report::new(MyError);
let report_local: Report<MyError, Mutable, Local> = Report::new(MyError);Sourcepub fn new_custom<H>(context: C) -> Selfwhere
C: ObjectMarkerFor<T>,
H: ContextHandler<C>,
pub fn new_custom<H>(context: C) -> Selfwhere
C: ObjectMarkerFor<T>,
H: ContextHandler<C>,
Creates a new Report with the given context and handler.
This method is generic over the thread safety marker T.
If you’re having trouble with type inference for the thread safety
parameter, consider using Report::new_sendsync_custom or
Report::new_local_custom instead.
§Examples
let report_sendsync: Report<MyError> = Report::new_custom::<handlers::Debug>(MyError);
let report_local: Report<MyError> = Report::new_custom::<handlers::Display>(MyError);Sourcepub fn from_parts<H>(
context: C,
children: ReportCollection<Dynamic, T>,
attachments: ReportAttachments<T>,
) -> Selfwhere
C: ObjectMarkerFor<T>,
H: ContextHandler<C>,
pub fn from_parts<H>(
context: C,
children: ReportCollection<Dynamic, T>,
attachments: ReportAttachments<T>,
) -> Selfwhere
C: ObjectMarkerFor<T>,
H: ContextHandler<C>,
Creates a new Report with the given context, children, and
attachments.
This method processes hooks during report creation. If you want to skip
hook processing, use Report::from_parts_unhooked instead.
§Examples
let report: Report<String, _, SendSync> = Report::from_parts::<handlers::Display>(
"error".to_string(),
ReportCollection::new(),
ReportAttachments::new(),
);Sourcepub fn from_parts_unhooked<H>(
context: C,
children: ReportCollection<Dynamic, T>,
attachments: ReportAttachments<T>,
) -> Selfwhere
C: ObjectMarkerFor<T>,
H: ContextHandler<C>,
pub fn from_parts_unhooked<H>(
context: C,
children: ReportCollection<Dynamic, T>,
attachments: ReportAttachments<T>,
) -> Selfwhere
C: ObjectMarkerFor<T>,
H: ContextHandler<C>,
Creates a new Report with the given context, children, and
attachments without hook processing.
This method skips hook processing during report creation. If you want
hooks to be processed, use Report::from_parts instead.
§Examples
let report: Report<String, _, SendSync> = Report::from_parts_unhooked::<handlers::Display>(
"error".to_string(),
ReportCollection::new(),
ReportAttachments::new(),
);Sourcepub fn into_parts(
self,
) -> (C, ReportCollection<Dynamic, T>, ReportAttachments<T>)
pub fn into_parts( self, ) -> (C, ReportCollection<Dynamic, T>, ReportAttachments<T>)
Decomposes the Report into its constituent parts.
Returns a tuple containing the context, the children collection and the
attachments collection in that order. This is the inverse operation
of Report::from_parts and Report::from_parts_unhooked.
This method can be useful when you need to:
- Extract and modify individual components of a report
- Rebuild a report with different components
- Transfer components between different reports
- Perform custom processing on specific parts
Note that to exactly reconstruct the original report, you will also need to use the same handler as was used for the original report.
§Examples
// Create a report with some children and attachments
let mut report: Report<String> = Report::from_parts::<handlers::Display>(
"main error".to_string(),
ReportCollection::new(),
ReportAttachments::new(),
);
// Add some content
let child_report = report!("child error").into_dynamic().into_cloneable();
report.children_mut().push(child_report);
report.attachments_mut().push("debug info".into());
// Decompose into parts
let (context, children, attachments) = report.into_parts();
assert_eq!(context, "main error");
assert_eq!(children.len(), 1);
assert!(attachments.len() >= 1); // "debug info" + potential automatic attachments
// Can rebuild with the same or different parts
let rebuilt: Report<String> = Report::from_parts::<handlers::Display>(
context,
children,
attachments,
);Sourcepub fn into_current_context(self) -> C
pub fn into_current_context(self) -> C
Extracts and returns the context value from the Report.
This is a convenience method that consumes the Report and returns
only the context, discarding the children and attachments. It’s
equivalent to calling report.into_parts().0.
This method can be useful when:
- You only need the underlying error or context value
- Converting from a
Reportback to the original error type - Extracting context for logging or forwarding to other systems
- Implementing error conversion traits
§Examples
#[derive(Debug, PartialEq, Clone)]
struct MyError {
message: String,
code: u32,
}
impl std::fmt::Display for MyError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Error {}: {}", self.code, self.message)
}
}
// Create a report with a custom error context
let original_error = MyError {
message: "database connection failed".to_string(),
code: 500,
};
let report: Report<MyError> = report!(original_error.clone());
// Extract just the context, discarding report structure
let extracted_error = report.into_current_context();
assert_eq!(extracted_error, original_error);
assert_eq!(extracted_error.code, 500);
assert_eq!(extracted_error.message, "database connection failed");Sourcepub fn current_context_mut(&mut self) -> &mut C
pub fn current_context_mut(&mut self) -> &mut C
Returns a mutable reference to the current context.
§Examples
use rootcause::prelude::*;
let mut report: Report<String> = report!(String::from("An error occurred"));
let context: &mut String = report.current_context_mut();
context.push_str(" and that's bad");Sourcepub fn context_transform<F, D>(self, f: F) -> Report<D, Mutable, T>
pub fn context_transform<F, D>(self, f: F) -> Report<D, Mutable, T>
Transforms the context type by applying a function, preserving report structure.
Converts the context type in-place without creating new nodes. Children, attachments, and hook data (backtraces, locations) are preserved.
§Examples
enum AppError {
Lib(LibError)
}
let lib_report: Report<LibError> = report!(LibError);
let app_report: Report<AppError> = lib_report.context_transform(AppError::Lib);§See Also
context_transform_nested()- Wraps original as preformatted childcontext()- Adds new parent contextcontext_to()- UsesReportConversiontraitexamples/context_methods.rs- Comparison guide
Sourcepub fn context_transform_nested<F, D>(self, f: F) -> Report<D, Mutable, T>where
F: FnOnce(C) -> D,
D: ObjectMarkerFor<T> + Display + Debug,
PreformattedContext: ObjectMarkerFor<T>,
pub fn context_transform_nested<F, D>(self, f: F) -> Report<D, Mutable, T>where
F: FnOnce(C) -> D,
D: ObjectMarkerFor<T> + Display + Debug,
PreformattedContext: ObjectMarkerFor<T>,
Transforms the context and nests the original report as a preformatted child.
Creates a new parent node with fresh hook data (location, backtrace),
but the original context type is lost—the child becomes
PreformattedContext and cannot be downcast.
§Examples
enum AppError {
Lib(LibError)
}
let lib_report: Report<LibError> = report!(LibError);
let app_report: Report<AppError> = lib_report.context_transform_nested(AppError::Lib);§See Also
context_transform()- Transforms without nestingcontext()- Adds new parent, preserves child’s typepreformat_root()- Lower-level operation used internallyexamples/context_methods.rs- Comparison guide
Sourcepub fn preformat_root(self) -> (C, Report<PreformattedContext, Mutable, T>)where
PreformattedContext: ObjectMarkerFor<T>,
pub fn preformat_root(self) -> (C, Report<PreformattedContext, Mutable, T>)where
PreformattedContext: ObjectMarkerFor<T>,
Extracts the context and returns it with a preformatted version of the report.
Returns a tuple: the original typed context and a new report with
PreformattedContext
containing the string representation. The preformatted report maintains
the same structure (children and attachments). Useful when you need
the typed value for processing and the formatted version for display.
This is a lower-level method primarily for custom transformation logic.
Most users should use
context_transform,
context_transform_nested,
or context_to instead.
See also: preformat (formats entire hierarchy),
into_parts (extracts without formatting),
current_context (reference
without extraction).
§Examples
struct MyError {
code: u32
}
let report: Report<MyError> = report!(MyError { code: 500 });
let (context, preformatted): (MyError, Report<PreformattedContext>) = report.preformat_root();Source§impl<C: ?Sized, T> Report<C, Mutable, T>
impl<C: ?Sized, T> Report<C, Mutable, T>
Sourcepub fn as_mut(&mut self) -> ReportMut<'_, C, T>
pub fn as_mut(&mut self) -> ReportMut<'_, C, T>
Returns a mutable reference to the report.
§Examples
use rootcause::{ReportMut, prelude::*};
let mut report: Report = report!("error message");
let report_mut: ReportMut<'_> = report.as_mut();Sourcepub fn attach<A>(self, attachment: A) -> Self
pub fn attach<A>(self, attachment: A) -> Self
Adds a new attachment to the Report.
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 report: Report = report!("error message");
let with_attachment = report.attach("additional info");Sourcepub fn attach_custom<H, A>(self, attachment: A) -> Selfwhere
A: ObjectMarkerFor<T>,
H: AttachmentHandler<A>,
pub fn attach_custom<H, A>(self, attachment: A) -> Selfwhere
A: ObjectMarkerFor<T>,
H: AttachmentHandler<A>,
Adds a new attachment to the Report.
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 report: Report = report!("error message");
let with_attachment = report.attach_custom::<handlers::Display, _>("info");Sourcepub fn children_mut(&mut self) -> &mut ReportCollection<Dynamic, T>
pub fn children_mut(&mut self) -> &mut ReportCollection<Dynamic, T>
Returns a mutable reference to the child reports.
§Examples
let mut report: Report = report!("error message");
let children_mut: &mut ReportCollection = report.children_mut();Sourcepub fn attachments_mut(&mut self) -> &mut ReportAttachments<T>
pub fn attachments_mut(&mut self) -> &mut ReportAttachments<T>
Returns a mutable reference to the attachments.
§Examples
let mut report: Report = report!("error message");
let attachments_mut: &mut ReportAttachments = report.attachments_mut();Source§impl<C: ?Sized, O, T> Report<C, O, T>
impl<C: ?Sized, O, T> Report<C, O, T>
Sourcepub fn context<D>(self, context: D) -> Report<D, Mutable, T>
pub fn context<D>(self, context: D) -> Report<D, Mutable, T>
Creates a new Report with the given context and sets the current
report as a child of the new report.
The new context will use the handlers::Display handler to format the
context.
This is a convenience method used for chaining method calls; it consumes
the Report and returns it.
If you want a different context handler, you can use
Report::context_custom.
If you want to more directly control the allocation of the new report,
you can use Report::from_parts, which is the underlying method
used to implement this method.
§Examples
let report: Report = report!("initial error");
let contextual_report: Report<&str> = report.context("additional context");Sourcepub fn context_custom<H, D>(self, context: D) -> Report<D, Mutable, T>where
D: ObjectMarkerFor<T>,
H: ContextHandler<D>,
pub fn context_custom<H, D>(self, context: D) -> Report<D, Mutable, T>where
D: ObjectMarkerFor<T>,
H: ContextHandler<D>,
Creates a new Report with the given context and sets the current
report as a child of the new report.
This is a convenience method used for chaining method calls; it consumes
the Report and returns it.
If you want to more directly control the allocation of the new report,
you can use Report::from_parts, which is the underlying method
used to implement this method.
§Examples
let report: Report = report!("initial error");
let contextual_report: Report<&str> = report.context_custom::<handlers::Debug, _>("context");Sourcepub fn context_to<D: ReportConversion<C, O, T>>(self) -> Report<D, Mutable, T>
pub fn context_to<D: ReportConversion<C, O, T>>(self) -> Report<D, Mutable, T>
Converts this report to a different context type using
ReportConversion.
Implement ReportConversion once to define conversion logic, then use
context_to() at call sites. Useful for consistent error type
coercion across your codebase, especially when integrating with
external libraries. You typically need to specify the target type
(::<Type>).
See also: context_transform for direct
conversion,
context_transform_nested for
wrapping, examples/thiserror_interop.rs for integration
patterns.
§Examples
enum AppError { Parse }
impl<T> ReportConversion<std::num::ParseIntError, Mutable, T> for AppError
where AppError: markers::ObjectMarkerFor<T>
{
fn convert_report(report: Report<std::num::ParseIntError, Mutable, T>) -> Report<Self, Mutable, T>
{
report.context(AppError::Parse)
}
}
// After implementing ReportConversion, use at call sites:
let result: Result<i32, Report<AppError>> = "abc".parse::<i32>().context_to();Sourcepub fn children(&self) -> &ReportCollection<Dynamic, T>
pub fn children(&self) -> &ReportCollection<Dynamic, T>
Returns a reference to the child reports.
§Examples
let report: Report = report!("error message");
let children: &ReportCollection = report.children();
assert_eq!(children.len(), 0); // The report has just been created, so it has no childrenSourcepub fn attachments(&self) -> &ReportAttachments<T>
pub fn attachments(&self) -> &ReportAttachments<T>
Returns a reference to the attachments.
§Examples
let report: Report = report!("error message");
let attachments: &ReportAttachments = report.attachments();Sourcepub fn into_dynamic(self) -> Report<Dynamic, O, T>
pub fn into_dynamic(self) -> Report<Dynamic, O, T>
Changes the context type of the Report 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
Report::downcast_report.
§Examples
let report: Report<MyError> = report!(my_error);
let dyn_report: Report<Dynamic> = report.into_dynamic();Sourcepub fn into_cloneable(self) -> Report<C, Cloneable, T>
pub fn into_cloneable(self) -> Report<C, Cloneable, T>
Changes the ownership of the Report to Cloneable.
Calling this method is equivalent to calling report.into(), however
this method has been restricted to only change the ownership mode to
Cloneable.
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 Report only has a single
owner.
After calling this method, you can clone the Report, but you can no
longer add attachments to the Report or otherwise modify the
root node.
To get back a Mutable you need to either:
- Allocate a new root node using e.g.
Report::context. - If there is a single unique owner of the report, you can use
Report::try_into_mutable. - Preformat the root node using
Report::preformat.
§Examples
let report: Report<_, Mutable> = report!(my_error);
let cloneable_report: Report<_, Cloneable> = report.into_cloneable();
let cloned = cloneable_report.clone();Sourcepub fn into_local(self) -> Report<C, O, Local>
pub fn into_local(self) -> Report<C, O, Local>
Changes the thread safety mode of the Report to Local.
Calling this method is equivalent to calling report.into(), however
this method has been restricted to only change the thread safety
mode to Local.
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 all objects in the Report might
actually be Send and Sync.
After calling this method, you can add objects to the Report that
are neither Send nor Sync, but the report itself will no
longer be Send+Sync.
§Examples
let report: Report<_, _, SendSync> = report!(my_error);
let local_report: Report<_, _, Local> = report.into_local();Sourcepub fn try_into_mutable(self) -> Result<Report<C, Mutable, T>, Report<C, O, T>>
pub fn try_into_mutable(self) -> Result<Report<C, Mutable, T>, Report<C, O, T>>
Checks if there is only a single unique owner of the root node of the
Report.
If there is only a single unique owner, this method
marks the current Report as Mutable and returns Ok,
otherwise it returns Err with the original Report.
This method does not actually modify the report in any way. It only has the effect of checking for unique ownership and returns the same report (with different type parameters) no matter the outcome of the check.
§Examples
let cloneable: Report<_, Cloneable> = some_report;
match cloneable.try_into_mutable() {
Ok(mutable) => println!("Converted to mutable"),
Err(cloneable) => println!("Still cloneable"),
}Sourcepub fn as_ref(&self) -> ReportRef<'_, C, O::RefMarker, T>where
O: ReportOwnershipMarker,
pub fn as_ref(&self) -> ReportRef<'_, C, O::RefMarker, T>where
O: ReportOwnershipMarker,
Returns an immutable reference to the report.
§Examples
let report: Report<_, Mutable> = report!("error message");
let report_ref: ReportRef<'_, _, Uncloneable> = report.as_ref();
let report: Report<_, Cloneable> = report!("error message").into_cloneable();
let report_ref: ReportRef<'_, _, Cloneable> = report.as_ref();Sourcepub fn iter_reports(&self) -> ReportIter<'_, O::RefMarker, T> ⓘwhere
O: ReportOwnershipMarker,
pub fn iter_reports(&self) -> ReportIter<'_, O::RefMarker, T> ⓘwhere
O: ReportOwnershipMarker,
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
Report::iter_sub_reports, this method includes the report on
which it was called as the first item in the iteration.
The ownership marker of the returned iterator references matches the
ownership of this report. For mutable reports, the references may
not be cloneable, which can limit how you can use them. If you need
cloneable references, consider using Report::iter_sub_reports
instead, which only iterates over children but guarantees
cloneable references.
See also: Report::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"); // Creates new node with error1 as child
let with_context2 = error2.context("context for error 2"); // Creates new node with error2 as child
// 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());
// At this point our report tree looks like this:
// - context for root error
// - root error
// - context for error 1
// - error 1
// - context for error 2
// - error 2
let all_reports: Vec<String> = root
.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.len(), 6);Sourcepub fn iter_sub_reports(&self) -> ReportIter<'_, Cloneable, T> ⓘwhere
O: ReportOwnershipMarker,
pub fn iter_sub_reports(&self) -> ReportIter<'_, Cloneable, T> ⓘwhere
O: ReportOwnershipMarker,
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 Report::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. This is different from Report::iter_reports,
which returns references that match the ownership marker of the
current report and may not be cloneable for mutable reports.
See also: Report::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"); // Creates new node with error1 as child
let with_context2 = error2.context("context for error 2"); // Creates new node with error2 as child
// 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 sub_reports: Vec<String> = root
.iter_sub_reports() // Note: using iter_sub_reports, not iter_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);Sourcepub fn preformat(&self) -> Report<PreformattedContext, Mutable, SendSync>
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 mut report: Report<NonSendSyncError, Mutable, Local> = report!(non_send_sync_error);
let preformatted: Report<PreformattedContext, Mutable, SendSync> = report.preformat();
assert_eq!(format!("{report}"), format!("{preformatted}"));Sourcepub fn current_context_type_id(&self) -> TypeId
pub fn current_context_type_id(&self) -> TypeId
Returns the TypeId of the current context.
§Examples
let report: Report<MyError> = report!(MyError);
let type_id = report.current_context_type_id();
assert_eq!(type_id, TypeId::of::<MyError>());
let report: Report<Dynamic> = report.into_dynamic();
let type_id = report.current_context_type_id();
assert_eq!(type_id, TypeId::of::<MyError>());Sourcepub fn current_context_type_name(&self) -> &'static str
pub fn current_context_type_name(&self) -> &'static str
Returns the core::any::type_name of the current context.
§Examples
let report: Report<MyError> = report!(MyError);
let type_name = report.current_context_type_name();
assert_eq!(type_name, core::any::type_name::<MyError>());
let report: Report<Dynamic> = report.into_dynamic();
let type_name = report.current_context_type_name();
assert_eq!(type_name, core::any::type_name::<MyError>());Sourcepub fn current_context_handler_type_id(&self) -> TypeId
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 report = Report::new_sendsync_custom::<handlers::Debug>("error message");
let handler_type = report.current_context_handler_type_id();
assert_eq!(handler_type, TypeId::of::<handlers::Debug>());Sourcepub fn current_context_error_source(&self) -> Option<&(dyn Error + 'static)>
pub fn current_context_error_source(&self) -> Option<&(dyn Error + 'static)>
Returns the error source if the context implements Error.
§Examples
let report: Report = report!("error message");
let source: Option<&dyn core::error::Error> = report.current_context_error_source();
assert!(source.is_none()); // The context does not implement Error, so no source
#[derive(Debug, thiserror::Error)]
enum MyError {
#[error("Io error: {0}")]
Io(#[from] std::io::Error),
// ...
}
let report: Report<MyError> = report!(MyError::Io(std::io::Error::other("My inner error")));
let source: Option<&dyn std::error::Error> = report.current_context_error_source();
assert_eq!(format!("{}", source.unwrap()), "My inner error");Sourcepub fn format_current_context(&self) -> impl Display + Debug
pub fn format_current_context(&self) -> impl Display + Debug
Formats the current context with hook processing.
§Examples
let report: Report = report!("error message");
let formatted = report.format_current_context();
println!("{formatted}");Sourcepub fn format_current_context_unhooked(&self) -> impl Display + Debug
pub fn format_current_context_unhooked(&self) -> impl Display + Debug
Formats the current context without hook processing.
§Examples
let report: Report = report!("error message");
let formatted = report.format_current_context_unhooked();
println!("{formatted}");Sourcepub fn format_with<H>(&self, hook: &H) -> impl Display + Debugwhere
H: ReportFormatter,
pub fn format_with<H>(&self, hook: &H) -> impl Display + Debugwhere
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 report = report!("error message");
// Format with ASCII-only output (no Unicode or ANSI colors)
let formatted = report.format_with(&DefaultReportFormatter::ASCII);
println!("{}", formatted);Sourcepub fn preferred_context_formatting_style(
&self,
report_formatting_function: FormattingFunction,
) -> ContextFormattingStyle
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 usingDisplayformatting orDebug
See also Report::preferred_context_formatting_style_unhooked.
§Examples
let report: Report = report!("error message");
let style = report.preferred_context_formatting_style(handlers::FormattingFunction::Display);Sourcepub fn preferred_context_formatting_style_unhooked(
&self,
report_formatting_function: FormattingFunction,
) -> ContextFormattingStyle
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 usingDisplayformatting orDebug
§Examples
let report: Report = report!("error message");
let style =
report.preferred_context_formatting_style_unhooked(handlers::FormattingFunction::Display);Sourcepub fn strong_count(&self) -> usize
pub fn strong_count(&self) -> usize
Returns the number of references to this report.
§Examples
let report: Report = report!("error message");
assert_eq!(report.strong_count(), 1); // We just created the report so it has a single ownerSource§impl<C: Sized, O, T> Report<C, O, T>
impl<C: Sized, O, T> Report<C, O, T>
Sourcepub fn current_context(&self) -> &C
pub fn current_context(&self) -> &C
Returns a reference to the current context.
§Examples
let report: Report<MyError> = report!(my_error);
let context: &MyError = report.current_context();Source§impl<O, T> Report<Dynamic, O, T>
impl<O, T> Report<Dynamic, O, T>
Sourcepub fn downcast_current_context<C>(&self) -> Option<&C>where
C: Sized + 'static,
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 dyn_report: Report<Dynamic> = report.into_dynamic();
let context: Option<&MyError> = dyn_report.downcast_current_context();
assert!(context.is_some());Sourcepub unsafe fn downcast_current_context_unchecked<C>(&self) -> &Cwhere
C: Sized + 'static,
pub unsafe fn downcast_current_context_unchecked<C>(&self) -> &Cwhere
C: Sized + 'static,
Downcasts the current context to a specific type without checking.
§Safety
The caller must ensure:
- The current context is actually of type
C(can be verified by callingcurrent_context_type_id()first)
§Examples
let report: Report<MyError> = report!(MyError);
let dyn_report: Report = report.into_dynamic();
// Verify the type first
if dyn_report.current_context_type_id() == TypeId::of::<MyError>() {
// SAFETY: We verified the type matches
let context: &MyError = unsafe { dyn_report.downcast_current_context_unchecked() };
}Sourcepub fn downcast_report<C>(self) -> Result<Report<C, O, T>, Self>where
C: Sized + 'static,
pub fn downcast_report<C>(self) -> Result<Report<C, O, T>, Self>where
C: Sized + 'static,
Attempts to downcast the report to a specific context type.
Returns Ok(report) if the current context is of type C,
otherwise returns Err(self) with the original report.
§Examples
let report: Report<MyError> = report!(MyError);
let dyn_report: Report = report.into_dynamic();
let downcasted: Result<Report<MyError>, _> = dyn_report.downcast_report();
assert!(downcasted.is_ok());Sourcepub unsafe fn downcast_report_unchecked<C>(self) -> Report<C, O, T>where
C: Sized + 'static,
pub unsafe fn downcast_report_unchecked<C>(self) -> Report<C, O, T>where
C: Sized + 'static,
Downcasts the report to a specific context type without checking.
§Safety
The caller must ensure:
- The current context is actually of type
C(can be verified by callingcurrent_context_type_id()first)
§Examples
let report: Report<MyError> = report!(MyError);
let dyn_report: Report = report.into_dynamic();
// Verify the type first
if dyn_report.current_context_type_id() == TypeId::of::<MyError>() {
// SAFETY: We verified the type matches
let downcasted: Report<MyError> = unsafe { dyn_report.downcast_report_unchecked() };
}Source§impl<C: Sized + Send + Sync> Report<C, Mutable, SendSync>
impl<C: Sized + Send + Sync> Report<C, Mutable, SendSync>
Sourcepub fn new_sendsync(context: C) -> Selfwhere
C: Error,
pub fn new_sendsync(context: C) -> Selfwhere
C: Error,
Creates a new Report with SendSync thread safety.
This is a convenience method that calls Report::new with explicit
SendSync thread safety. Use this method when you’re having
trouble with type inference for the thread safety parameter.
The context will use the handlers::Error handler to format the
context.
§Examples
let report = Report::new_sendsync(MyError);Sourcepub fn new_sendsync_custom<H>(context: C) -> Selfwhere
H: ContextHandler<C>,
pub fn new_sendsync_custom<H>(context: C) -> Selfwhere
H: ContextHandler<C>,
Creates a new Report with SendSync thread safety and the given
handler.
This is a convenience method that calls Report::new_custom with
explicit SendSync thread safety. Use this method when you’re
having trouble with type inference for the thread safety parameter.
§Examples
let report = Report::new_sendsync_custom::<handlers::Display>("error");Source§impl<C: Sized> Report<C, Mutable, Local>
impl<C: Sized> Report<C, Mutable, Local>
Sourcepub fn new_local(context: C) -> Selfwhere
C: Error,
pub fn new_local(context: C) -> Selfwhere
C: Error,
Creates a new Report with Local thread safety.
This is a convenience method that calls Report::new with explicit
Local thread safety. Use this method when you’re having trouble
with type inference for the thread safety parameter.
The context will use the handlers::Error handler to format the
context.
§Examples
let report = Report::new_local(MyError);Sourcepub fn new_local_custom<H>(context: C) -> Selfwhere
H: ContextHandler<C>,
pub fn new_local_custom<H>(context: C) -> Selfwhere
H: ContextHandler<C>,
Creates a new Report with Local thread safety and the given
handler.
This is a convenience method that calls Report::new_custom with
explicit Local thread safety. Use this method when you’re having
trouble with type inference for the thread safety parameter.
§Examples
let report = Report::new_local_custom::<handlers::Display>("error");Trait Implementations§
Source§impl<C: ?Sized, O, T> Extend<Report<C, O, T>> for ReportCollection<C, T>where
O: ReportOwnershipMarker,
impl<C: ?Sized, O, T> Extend<Report<C, O, T>> for ReportCollection<C, T>where
O: ReportOwnershipMarker,
Source§fn extend<I: IntoIterator<Item = Report<C, O, T>>>(&mut self, iter: I)
fn extend<I: IntoIterator<Item = Report<C, O, T>>>(&mut self, iter: I)
Source§fn extend_one(&mut self, item: A)
fn extend_one(&mut self, item: A)
extend_one)Source§fn extend_reserve(&mut self, additional: usize)
fn extend_reserve(&mut self, additional: usize)
extend_one)Source§impl<C: Sized, O, T> Extend<Report<C, O, T>> for ReportCollection<Dynamic, T>where
O: ReportOwnershipMarker,
impl<C: Sized, O, T> Extend<Report<C, O, T>> for ReportCollection<Dynamic, T>where
O: ReportOwnershipMarker,
Source§fn extend<I: IntoIterator<Item = Report<C, O, T>>>(&mut self, iter: I)
fn extend<I: IntoIterator<Item = Report<C, O, T>>>(&mut self, iter: I)
Source§fn extend_one(&mut self, item: A)
fn extend_one(&mut self, item: A)
extend_one)Source§fn extend_reserve(&mut self, additional: usize)
fn extend_reserve(&mut self, additional: usize)
extend_one)Source§impl<C: ?Sized, O> From<Report<C, O>> for Error
Available on crate feature compat-anyhow1 only.
impl<C: ?Sized, O> From<Report<C, O>> for Error
compat-anyhow1 only.Source§impl<C: ?Sized, O> From<Report<C, O>> for Report
Available on crate feature compat-eyre06 only.
impl<C: ?Sized, O> From<Report<C, O>> for Report
compat-eyre06 only.Source§impl<C: ?Sized, O> From<Report<C, O>> for Report<ReportAsError<C>>
Available on crate feature compat-error-stack05 only.
impl<C: ?Sized, O> From<Report<C, O>> for Report<ReportAsError<C>>
compat-error-stack05 only.Source§impl<C: ?Sized, O> From<Report<C, O>> for Report<ReportAsError<C>>
Available on crate feature compat-error-stack06 only.
impl<C: ?Sized, O> From<Report<C, O>> for Report<ReportAsError<C>>
compat-error-stack06 only.Source§impl<C: ?Sized, O, T> FromIterator<Report<C, O, T>> for ReportCollection<C, T>where
O: ReportOwnershipMarker,
impl<C: ?Sized, O, T> FromIterator<Report<C, O, T>> for ReportCollection<C, T>where
O: ReportOwnershipMarker,
Source§impl<C: Sized, O, T> FromIterator<Report<C, O, T>> for ReportCollection<Dynamic, T>where
O: ReportOwnershipMarker,
impl<C: Sized, O, T> FromIterator<Report<C, O, T>> for ReportCollection<Dynamic, T>where
O: ReportOwnershipMarker,
Source§impl<C: ?Sized, O> IntoAnyhow for Report<C, O>
Available on crate feature compat-anyhow1 only.
impl<C: ?Sized, O> IntoAnyhow for Report<C, O>
compat-anyhow1 only.Source§impl<C: ?Sized, O> IntoErrorStack<C> for Report<C, O, SendSync>
Available on crate feature compat-error-stack05 only.
impl<C: ?Sized, O> IntoErrorStack<C> for Report<C, O, SendSync>
compat-error-stack05 only.Source§impl<C: ?Sized, O> IntoErrorStack<C> for Report<C, O, SendSync>
Available on crate feature compat-error-stack06 only.
impl<C: ?Sized, O> IntoErrorStack<C> for Report<C, O, SendSync>
compat-error-stack06 only.