use core::fmt;
use std::{borrow::Cow, error};
use crate::{Context, CreateError, CustomError, ErrorKind, FullErrorContent, StaticErrorContent};
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Clone, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct BoxedError<'text, Kind> {
pub(crate) content: Box<CustomError<'text, Kind>>,
}
impl<'text, Kind: 'text> StaticErrorContent<'text> for BoxedError<'text, Kind> {
fn get_short_description(&self) -> Cow<'text, str> {
self.content.short_description.clone()
}
fn get_long_description(&self) -> Cow<'text, str> {
self.content.long_description.clone()
}
fn get_suggestions<'a>(&'a self) -> Cow<'a, [Cow<'text, str>]> {
Cow::Borrowed(self.content.suggestions.as_slice())
}
fn get_version(&self) -> Cow<'text, str> {
self.content.version.clone()
}
}
impl<'text, Kind: 'text + Clone + PartialEq + ErrorKind> FullErrorContent<'text, Kind>
for BoxedError<'text, Kind>
{
type UnderlyingError = CustomError<'text, Kind>;
fn get_kind(&self) -> Kind {
self.content.kind.clone()
}
fn get_contexts<'a>(&'a self) -> Cow<'a, [Context<'text>]> {
Cow::Borrowed(self.content.contexts.as_slice())
}
fn get_underlying_errors<'a>(&'a self) -> Cow<'a, [Self::UnderlyingError]> {
Cow::Borrowed(self.content.underlying_errors.as_slice())
}
}
impl<'text, Kind: ErrorKind + 'text + Clone> CreateError<'text, Kind> for BoxedError<'text, Kind> {
fn small(
kind: Kind,
short_desc: impl Into<Cow<'text, str>>,
long_desc: impl Into<Cow<'text, str>>,
) -> Self {
Self {
content: Box::new(CustomError::small(kind, short_desc, long_desc)),
}
}
fn long_description(mut self, long_desc: impl Into<Cow<'text, str>>) -> Self {
self.content.long_description = long_desc.into();
self
}
fn suggestions(
mut self,
suggestions: impl IntoIterator<Item = impl Into<Cow<'text, str>>>,
) -> Self {
self.content
.suggestions
.extend(suggestions.into_iter().map(|s| s.into()));
self
}
fn version(mut self, version: impl Into<Cow<'text, str>>) -> Self {
self.content.version = version.into();
self
}
fn replace_context(mut self, context: Context<'text>) -> Self {
self.content.contexts = vec![context];
self
}
fn add_contexts(mut self, contexts: impl IntoIterator<Item = Context<'text>>) -> Self {
self.content.contexts.extend(contexts);
self
}
fn add_contexts_ref(&mut self, contexts: impl IntoIterator<Item = Context<'text>>) {
self.content.contexts.extend(contexts);
}
fn add_context(mut self, context: Context<'text>) -> Self {
self.content.contexts.push(context);
self
}
fn add_underlying_errors(
mut self,
underlying_errors: impl IntoIterator<Item = impl Into<Self::UnderlyingError>>,
) -> Self {
self.content
.underlying_errors
.extend(underlying_errors.into_iter().map(|e| e.into()));
self
}
fn add_underlying_error(mut self, underlying_error: impl Into<Self::UnderlyingError>) -> Self {
self.content.underlying_errors.push(underlying_error.into());
self
}
fn overwrite_line_index(mut self, line_index: u32) -> Self {
self.content.contexts = self
.content
.contexts
.into_iter()
.map(|c| c.line_index(line_index))
.collect();
self
}
}
impl<'text, Kind: ErrorKind> BoxedError<'text, Kind> {
pub fn to_owned(self) -> BoxedError<'static, Kind> {
BoxedError {
content: Box::new((*self.content).to_owned()),
}
}
}
impl<Kind: ErrorKind + Clone> fmt::Debug for BoxedError<'_, Kind> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.display(f, None, true)
}
}
impl<Kind: ErrorKind + Clone> fmt::Display for BoxedError<'_, Kind> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.display(f, None, true)
}
}
impl<Kind: ErrorKind + Clone> error::Error for BoxedError<'_, Kind> {}
impl<'text, Kind: ErrorKind> From<CustomError<'text, Kind>> for BoxedError<'text, Kind> {
fn from(value: CustomError<'text, Kind>) -> Self {
Self {
content: Box::new(value),
}
}
}