use core::fmt::Display;
use super::{
Attachment, ErrorCode, MissingSeverity, Report, ReportMetadata, Severity, SeverityState,
};
pub trait Diagnostic {
type Value;
type Error;
fn to_report(self) -> Result<Self::Value, Report<Self::Error>>;
fn diag<E2, State2>(
self,
f: impl FnOnce(Report<Self::Error>) -> Report<E2, State2>,
) -> Result<Self::Value, Report<E2, State2>>
where
Self: Sized,
State2: SeverityState,
{
self.to_report().map_err(f)
}
fn to_report_note(
self,
message: impl Display + Send + Sync + 'static,
) -> Result<Self::Value, Report<Self::Error>>
where
Self: Sized,
{
self.to_report().and_then_report(
|report: Report<Self::Error, MissingSeverity>| -> Report<Self::Error, MissingSeverity> {
Report::<Self::Error, MissingSeverity>::attach_note(report, message)
},
)
}
}
impl<T, E> Diagnostic for Result<T, E> {
type Value = T;
type Error = E;
fn to_report(self) -> Result<Self::Value, Report<Self::Error>> {
self.map_err(Report::new)
}
}
pub trait ResultReportExt<T, E, State = MissingSeverity>
where
State: SeverityState,
{
fn and_then_report<NewE, NewState>(
self,
f: impl FnOnce(Report<E, State>) -> Report<NewE, NewState>,
) -> Result<T, Report<NewE, NewState>>
where
NewState: SeverityState;
}
impl<T, E, State> ResultReportExt<T, E, State> for Result<T, Report<E, State>>
where
State: SeverityState,
{
fn and_then_report<NewE, NewState>(
self,
f: impl FnOnce(Report<E, State>) -> Report<NewE, NewState>,
) -> Result<T, Report<NewE, NewState>>
where
NewState: SeverityState,
{
self.map_err(f)
}
}
pub trait InspectReportExt<T, E, State = MissingSeverity>
where
State: SeverityState,
{
fn report_ref(&self) -> Option<&Report<E, State>>;
fn report_attachments(&self) -> Option<&[Attachment]>;
fn report_metadata(&self) -> Option<&ReportMetadata<State>>;
fn report_error_code(&self) -> Option<&ErrorCode>;
fn report_severity(&self) -> Option<Severity>;
fn report_category(&self) -> Option<&str>;
fn report_retryable(&self) -> Option<bool>;
}
impl<T, E, State> InspectReportExt<T, E, State> for Result<T, Report<E, State>>
where
State: SeverityState,
{
fn report_ref(&self) -> Option<&Report<E, State>> {
self.as_ref().err()
}
fn report_attachments(&self) -> Option<&[Attachment]> {
self.report_ref().map(Report::<E, State>::attachments)
}
fn report_metadata(&self) -> Option<&ReportMetadata<State>> {
self.report_ref().map(Report::<E, State>::metadata)
}
fn report_error_code(&self) -> Option<&ErrorCode> {
self.report_ref().and_then(Report::<E, State>::error_code)
}
fn report_severity(&self) -> Option<Severity> {
self.report_ref().and_then(Report::<E, State>::severity)
}
fn report_category(&self) -> Option<&str> {
self.report_ref().and_then(Report::<E, State>::category)
}
fn report_retryable(&self) -> Option<bool> {
self.report_ref().and_then(Report::<E, State>::retryable)
}
}