ystd 0.0.11

An opinionated and batteries included `std` mirror for convenient, correct code and pleasant error messages
Documentation
use crate::prelude::*;

#[derive(Debug, thiserror::Error)]
#[error("{report}")]
pub struct ReportedError<T> {
	pub report: Report,
	#[source]
	pub inner: Option<Arc<T>>,
}

impl<T> ReportedError<T> {
	pub fn empty(report: Report) -> Self {
		Self {
			report,
			inner: None,
		}
	}

	pub fn new(err: T) -> Self
	where
		T: Send + Sync + core::error::Error + 'static,
	{
		let err = Arc::new(err);
		Self {
			report: Report::new(err.clone()),
			inner: Some(err),
		}
	}

	pub fn map_inner<U, F: FnOnce(Arc<T>) -> Option<Arc<U>>>(self, cb: F) -> ReportedError<U> {
		ReportedError {
			report: self.report,
			inner: self.inner.map(|inner| cb(inner)).flatten(),
		}
	}

	pub fn erase_inner<U>(self) -> ReportedError<U> {
		self.map_inner(|_| None)
	}

	pub fn get_inner(&self) -> Option<&T> {
		match &self.inner {
			None => None,
			Some(inner) => Some(inner.as_ref()),
		}
	}
}

#[extension(pub trait WrapReportedErr)]
impl<T, ET> Result<T, ReportedError<ET>>
where
	ET: Send + Sync + 'static,
{
	fn wrap_reported_err(self, msg: impl std::fmt::Display + Send + Sync + 'static) -> Self {
		self.map_err(|err| ReportedError {
			report: err.report.wrap_err(msg),
			inner: err.inner,
		})
	}
}