mod inner;
use std::fmt::{Debug, Display, Formatter, Result as FmtResult};
use std::process::{ExitCode, Termination};
use crate::context::AbstractContext;
use crate::kind::Kind;
use crate::AnyError;
use inner::ReportInner;
pub struct Report<C, K>(ReportVariant<C, K>)
where
C: AbstractContext<Entry: Display>,
K: Kind;
impl<C, K> Report<C, K>
where
C: AbstractContext<Entry: Display>,
K: Kind,
{
pub fn wrap(error: AnyError<C, K>) -> Self {
error.into()
}
pub fn capture(func: impl FnOnce() -> Result<(), AnyError<C, K>>) -> Self {
match func() {
Ok(_) => Self(ReportVariant::Success),
Err(err) => err.into(),
}
}
pub fn pretty(self, pretty: bool) -> Self {
match self.0 {
ReportVariant::Failure(report) => report.pretty(pretty).into(),
v => Self(v),
}
}
pub fn kind(self, kind: bool) -> Self {
match self.0 {
ReportVariant::Failure(report) => report.kind(kind).into(),
v => Self(v),
}
}
pub fn backtrace(self, backtrace: bool) -> Self {
match self.0 {
ReportVariant::Failure(report) => report.backtrace(backtrace).into(),
v => Self(v),
}
}
pub fn context(self, context: bool) -> Self {
match self.0 {
ReportVariant::Failure(report) => report.context(context).into(),
v => Self(v),
}
}
fn render(&self, f: &mut Formatter<'_>) -> FmtResult {
match &self.0 {
ReportVariant::Failure(report) => report.render(f),
_ => Ok(()),
}
}
}
impl<C, K> From<ReportInner<C, K>> for Report<C, K>
where
C: AbstractContext<Entry: Display>,
K: Kind,
{
fn from(value: ReportInner<C, K>) -> Self {
Self(ReportVariant::Failure(value))
}
}
impl<C, K> From<AnyError<C, K>> for Report<C, K>
where
C: AbstractContext<Entry: Display>,
K: Kind,
{
fn from(error: AnyError<C, K>) -> Self {
Self(ReportVariant::Failure(ReportInner::from(error)))
}
}
impl<C, K> Termination for Report<C, K>
where
C: AbstractContext<Entry: Display>,
K: Kind,
{
fn report(self) -> ExitCode {
match self.0 {
ReportVariant::Success => ExitCode::SUCCESS,
ReportVariant::Failure(report) => {
eprintln!("{report}");
ExitCode::FAILURE
}
}
}
}
impl<C, K> Debug for Report<C, K>
where
C: AbstractContext<Entry: Display>,
K: Kind,
{
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
self.render(f)
}
}
impl<C, K> Display for Report<C, K>
where
C: AbstractContext<Entry: Display>,
K: Kind,
{
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
self.render(f)
}
}
enum ReportVariant<C, K>
where
C: AbstractContext<Entry: Display>,
K: Kind,
{
Success,
Failure(ReportInner<C, K>),
}