pub struct ReportRef<'a, Context: ?Sized + 'static = Dynamic, Ownership: 'static = Cloneable, ThreadSafety: 'static = SendSync> { /* private fields */ }Expand description
A reference to a Report.
ReportRef is a lightweight, copyable reference to a report that
allows you to inspect report data without taking ownership. It’s the
primary way to work with reports in a read-only manner.
§Key Characteristics
- Always
Copy+Clone: UnlikeReport, allReportRefinstances can be freely copied regardless of their ownership marker - Lifetime-bound: Tied to the lifetime of the underlying report
- Type parameters: Like
Report, has context typeC, ownership markerO, and thread safety markerT
§Ownership Markers
The ownership marker on ReportRef indicates what the underlying
report’s ownership status is:
Cloneable: The underlying report is shared (can useclone_arcto get an ownedReport)Uncloneable: The underlying report has unique ownership (cannot useclone_arc)
Note that when you create a ReportRef from a Report marked as
Mutable, it becomes a ReportRef with the Uncloneable marker
to prevent cloning while mutable access exists.
§Examples
use rootcause::{ReportRef, markers::Uncloneable, prelude::*};
let report: Report = report!("error message");
// Get a reference - this is Uncloneable because report is Mutable
let report_ref: ReportRef<'_, _, Uncloneable> = report.as_ref();
// Inspect the report
println!("{}", report_ref);
assert_eq!(report_ref.children().len(), 0);Implementations§
Source§impl<'a, C: Sized, O, T> ReportRef<'a, C, O, T>
impl<'a, C: Sized, O, T> ReportRef<'a, C, O, T>
Sourcepub fn current_context(self) -> &'a C
pub fn current_context(self) -> &'a C
Returns a reference to the current context.
§Examples
let report_ref: ReportRef<'_, MyError> = report.as_ref();
let context: &MyError = report_ref.current_context();Source§impl<'a, C: ?Sized, O, T> ReportRef<'a, C, O, T>
impl<'a, C: ?Sized, O, T> ReportRef<'a, C, O, T>
Sourcepub fn children(self) -> &'a ReportCollection<Dynamic, T>
pub fn children(self) -> &'a ReportCollection<Dynamic, T>
Returns a reference to the child reports.
§Examples
let report = report!("parent error").into_cloneable();
let report_ref: ReportRef<'_, _, _> = report.as_ref();
let children: &ReportCollection = report_ref.children();
assert_eq!(children.len(), 0); // The report has just been created, so it has no childrenSourcepub fn attachments(self) -> &'a ReportAttachments<T>
pub fn attachments(self) -> &'a ReportAttachments<T>
Returns a reference to the attachments.
§Examples
let report_ref: ReportRef<'_> = report.as_ref();
let attachments: &ReportAttachments = report_ref.attachments();Sourcepub fn into_dynamic(self) -> ReportRef<'a, Dynamic, O, T>
pub fn into_dynamic(self) -> ReportRef<'a, Dynamic, O, T>
Changes the context type of the ReportRef 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
ReportRef::downcast_report.
§Examples
let report_ref: ReportRef<'_, MyError> = report.as_ref();
let dyn_report_ref: ReportRef<'_, Dynamic> = report_ref.into_dynamic();Sourcepub fn into_uncloneable(self) -> ReportRef<'a, C, Uncloneable, T>
pub fn into_uncloneable(self) -> ReportRef<'a, C, Uncloneable, T>
Changes the ownership mode of the ReportRef to Uncloneable.
Calling this method is equivalent to calling report.into(), however
this method has been restricted to only change the ownership mode to
Uncloneable.
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 ReportRef references a report
that could potentially be cloned via clone_arc.
This is useful when you need a type that explicitly cannot use
clone_arc, typically for API boundaries or when working with
mutable reports.
§Examples
let report_ref: ReportRef<'_, MyError, Cloneable> = report.as_ref();
let dyn_report_ref: ReportRef<'_, MyError, Uncloneable> = report_ref.into_uncloneable();Sourcepub fn into_local(self) -> ReportRef<'a, C, O, Local>
pub fn into_local(self) -> ReportRef<'a, C, O, Local>
Changes the thread safety mode of the ReportRef 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 ReportRef are
actually Send and Sync.
This is useful when you need to work with a report reference in a
context that doesn’t require Send + Sync, or when the report
may contain thread-local data that isn’t actually being used.
§Examples
let report_ref: ReportRef<'_, _, _, SendSync> = report.as_ref();
let local_report_ref: ReportRef<'_, _, _, Local> = report_ref.into_local();Sourcepub fn iter_reports(self) -> ReportIter<'a, O, T> ⓘ
pub fn iter_reports(self) -> ReportIter<'a, O, 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
ReportRef::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. If you need cloneable references, consider
using ReportRef::iter_sub_reports instead, which only iterates
over children but guarantees cloneable references.
See also: ReportRef::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_ref: ReportRef<'_, &'static str, Uncloneable> = root.as_ref();
let all_reports: Vec<String> = root_ref
.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);Sourcepub fn iter_sub_reports(self) -> ReportIter<'a, Cloneable, T> ⓘ
pub fn iter_sub_reports(self) -> ReportIter<'a, 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 ReportRef::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: ReportRef::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_ref: ReportRef<'_, &'static str, Uncloneable> = root.as_ref();
let sub_reports: Vec<String> = root_ref
.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);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 report_ref: ReportRef<'_, NonSendSyncError, Uncloneable, Local> = report.as_ref();
let preformatted: Report<PreformattedContext, Mutable, SendSync> = report_ref.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_ref: ReportRef<'_, MyError> = report.as_ref();
let type_id = report_ref.current_context_type_id();
assert_eq!(type_id, TypeId::of::<MyError>());
let report_ref: ReportRef<'_, Dynamic> = report_ref.into_dynamic();
let type_id = report_ref.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_ref: ReportRef<'_, MyError> = report.as_ref();
let type_name = report_ref.current_context_type_name();
assert_eq!(type_name, core::any::type_name::<MyError>());
let report_ref: ReportRef<'_, Dynamic> = report_ref.into_dynamic();
let type_name = report_ref.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 report_ref: ReportRef<'_, &'static str, Uncloneable> = report.as_ref();
let handler_type = report_ref.current_context_handler_type_id();
assert_eq!(handler_type, TypeId::of::<handlers::Debug>());Sourcepub fn current_context_error_source(self) -> Option<&'a (dyn Error + 'static)>
pub fn current_context_error_source(self) -> Option<&'a (dyn Error + 'static)>
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_ref: ReportRef<'_> = report.as_ref();
let formatted = report_ref.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_ref: ReportRef<'_> = report.as_ref();
let formatted = report_ref.format_current_context_unhooked();
println!("{formatted}");Sourcepub fn format_with<H: ReportFormatter>(self, hook: &H) -> impl Display + Debug
pub fn format_with<H: ReportFormatter>(self, hook: &H) -> impl Display + Debug
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").into_cloneable();
let report_ref = report.as_ref();
// Format with ASCII-only output (no Unicode or ANSI colors)
let formatted = report_ref.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
§Examples
let report_ref: ReportRef<'_> = report.as_ref();
let style =
report_ref.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_ref: ReportRef<'_> = report.as_ref();
let style = report_ref
.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 mut report: Report = report!("error message");
let report_ref: ReportRef<'_, _, _> = report.as_ref();
assert_eq!(report_ref.strong_count(), 1); // The report has just been created, so it has a single ownerSource§impl<'a, O, T> ReportRef<'a, Dynamic, O, T>
impl<'a, O, T> ReportRef<'a, Dynamic, O, T>
Sourcepub fn downcast_current_context<C>(self) -> Option<&'a C>where
C: Sized + 'static,
pub fn downcast_current_context<C>(self) -> Option<&'a 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_ref: ReportRef<'_, MyError> = report.as_ref();
let dyn_report_ref: ReportRef<'_, Dynamic> = report_ref.into_dynamic();
let context: Option<&MyError> = dyn_report_ref.downcast_current_context();
assert!(context.is_some());Sourcepub unsafe fn downcast_current_context_unchecked<C>(self) -> &'a Cwhere
C: Sized + 'static,
pub unsafe fn downcast_current_context_unchecked<C>(self) -> &'a 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_ref: ReportRef<'_, Dynamic> = report.as_ref();
// Verify the type first
if report_ref.current_context_type_id() == TypeId::of::<MyError>() {
// SAFETY: We verified the type matches
let context: &MyError = unsafe { report_ref.downcast_current_context_unchecked() };
}Sourcepub fn downcast_report<C>(self) -> Option<ReportRef<'a, C, O, T>>where
C: Sized,
pub fn downcast_report<C>(self) -> Option<ReportRef<'a, C, O, T>>where
C: Sized,
Attempts to downcast the report to a specific context type.
Returns Some(report_ref) if the current context is of type C,
otherwise returns None.
§Examples
let report_ref: ReportRef<'_, MyError> = report.as_ref();
let dyn_report_ref: ReportRef<'_, Dynamic> = report_ref.into_dynamic();
let downcasted: Option<ReportRef<'_, MyError>> = dyn_report_ref.downcast_report::<MyError>();
assert!(downcasted.is_some());Sourcepub unsafe fn downcast_report_unchecked<C>(self) -> ReportRef<'a, C, O, T>where
C: Sized,
pub unsafe fn downcast_report_unchecked<C>(self) -> ReportRef<'a, C, O, T>where
C: Sized,
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_ref: ReportRef<'_, Dynamic> = report.as_ref();
// Verify the type first
if report_ref.current_context_type_id() == TypeId::of::<MyError>() {
// SAFETY: We verified the type matches
let downcasted = unsafe { report_ref.downcast_report_unchecked::<MyError>() };
}Source§impl<'a, C: ?Sized, T> ReportRef<'a, C, Cloneable, T>
impl<'a, C: ?Sized, T> ReportRef<'a, C, Cloneable, T>
Sourcepub fn clone_arc(self) -> Report<C, Cloneable, T>
pub fn clone_arc(self) -> Report<C, Cloneable, T>
Clones the underlying triomphe::Arc of the report, returning
a new owned Report that references the same root node.
This method is only available when the ownership marker is
Cloneable, indicating that the underlying report can be safely
cloned.
§Examples
use rootcause::{ReportRef, markers::Cloneable, prelude::*};
let report1: Report<_, Cloneable> = report!("error").into_cloneable();
let report_ref: ReportRef<'_, _, Cloneable> = report1.as_ref();
// Clone the Arc to get a new owned Report
let report2: Report<_, Cloneable> = report_ref.clone_arc();
// Both reports reference the same underlying data
assert_eq!(format!("{}", report1), format!("{}", report2));Trait Implementations§
Source§impl<'a, C: ?Sized, T> Extend<ReportRef<'a, C, Cloneable, T>> for ReportCollection<C, T>
impl<'a, C: ?Sized, T> Extend<ReportRef<'a, C, Cloneable, T>> for ReportCollection<C, T>
Source§fn extend<I: IntoIterator<Item = ReportRef<'a, C, Cloneable, T>>>(
&mut self,
iter: I,
)
fn extend<I: IntoIterator<Item = ReportRef<'a, C, Cloneable, 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<'a, C: Sized, T> Extend<ReportRef<'a, C, Cloneable, T>> for ReportCollection<Dynamic, T>
impl<'a, C: Sized, T> Extend<ReportRef<'a, C, Cloneable, T>> for ReportCollection<Dynamic, T>
Source§fn extend<I: IntoIterator<Item = ReportRef<'a, C, Cloneable, T>>>(
&mut self,
iter: I,
)
fn extend<I: IntoIterator<Item = ReportRef<'a, C, Cloneable, 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)