#![warn(
unknown_lints,
// ---------- StylisticT
absolute_paths_not_starting_with_crate,
elided_lifetimes_in_paths,
explicit_outlives_requirements,
macro_use_extern_crate,
nonstandard_style, /* group */
noop_method_call,
rust_2018_idioms,
single_use_lifetimes,
trivial_casts,
trivial_numeric_casts,
// ---------- Future
future_incompatible, /* group */
rust_2021_compatibility, /* group */
// ---------- Public
missing_debug_implementations,
// missing_docs,
unreachable_pub,
// ---------- Unsafe
unsafe_code,
unsafe_op_in_unsafe_fn,
// ---------- Unused
unused, /* group */
)]
#![deny(
// ---------- Public
exported_private_dependencies,
// ---------- Deprecated
anonymous_parameters,
bare_trait_objects,
ellipsis_inclusive_range_patterns,
// ---------- Unsafe
deref_nullptr,
drop_bounds,
dyn_drop,
)]
#![cfg_attr(all(feature = "alloc", not(feature = "std")), no_std)]
#[cfg(all(feature = "alloc", not(feature = "std")))]
extern crate alloc;
#[cfg(all(feature = "alloc", not(feature = "std")))]
use alloc::{
boxed::Box,
string::{String, ToString},
};
use core::{
any::type_name_of_val,
clone::Clone,
cmp::PartialEq,
error::Error,
fmt::{Debug, Display, Formatter, Result as FmtResult},
};
pub trait ExtendedError: Error + Clone + Debug + PartialEq {}
#[derive(Clone, Debug, PartialEq)]
pub struct FlatError {
original_type_name: &'static str,
message: String,
source: Option<Box<Self>>,
}
impl<E: Error + Clone + Debug + PartialEq> ExtendedError for E {}
impl Display for FlatError {
#[allow(clippy::format_in_format_args)]
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
if f.alternate() {
write!(
f,
"{} ({}{})",
self.message,
self.source
.as_ref()
.map(|e| format!("source: {e}, "))
.unwrap_or_default(),
format!("original type: `{}`", self.original_type_name),
)
} else {
write!(f, "{}", self.message)
}
}
}
impl Error for FlatError {
#[allow(trivial_casts)]
fn source(&self) -> Option<&(dyn Error + 'static)> {
self.flat_source().map(|err| err as &dyn Error)
}
}
impl FlatError {
pub fn from_any<E>(error: &E) -> Self
where
E: Error + ?Sized,
{
Self {
original_type_name: type_name_of_val(error),
message: error.to_string(),
source: error.source().map(|err| Box::new(FlatError::from_any(err))),
}
}
pub fn new<S: Into<String>>(original_type_name: &'static str, message: S) -> Self {
Self {
original_type_name,
message: message.into(),
source: None,
}
}
pub fn flat_source(&self) -> Option<&FlatError> {
self.source.as_ref().map(|source| source.as_ref())
}
pub fn original_type_name(&self) -> &'static str {
self.original_type_name
}
}
impl From<::core::array::TryFromSliceError> for FlatError {
fn from(e: ::core::array::TryFromSliceError) -> Self {
FlatError::from_any(&e)
}
}
impl From<::core::cell::BorrowError> for FlatError {
fn from(e: ::core::cell::BorrowError) -> Self {
FlatError::from_any(&e)
}
}
#[cfg(any(not(feature = "alloc"), feature = "std"))]
impl From<::std::env::JoinPathsError> for FlatError {
fn from(e: ::std::env::JoinPathsError) -> Self {
FlatError::from_any(&e)
}
}
#[cfg(any(not(feature = "alloc"), feature = "std"))]
impl From<::std::fs::TryLockError> for FlatError {
fn from(e: ::std::fs::TryLockError) -> Self {
FlatError::from_any(&e)
}
}
#[cfg(any(not(feature = "alloc"), feature = "std"))]
impl From<::std::io::Error> for FlatError {
fn from(e: ::std::io::Error) -> Self {
FlatError::from_any(&e)
}
}
#[cfg(any(not(feature = "alloc"), feature = "std"))]
impl<W> From<::std::io::IntoInnerError<W>> for FlatError
where
W: ::std::fmt::Debug + ::std::marker::Send,
{
fn from(e: ::std::io::IntoInnerError<W>) -> Self {
FlatError::from_any(&e)
}
}
#[cfg(any(not(feature = "alloc"), feature = "std"))]
impl From<::std::io::WriterPanicked> for FlatError {
fn from(e: ::std::io::WriterPanicked) -> Self {
FlatError::from_any(&e)
}
}
#[cfg(any(not(feature = "alloc"), feature = "std"))]
impl From<::std::string::FromUtf16Error> for FlatError {
fn from(e: ::std::string::FromUtf16Error) -> Self {
FlatError::from_any(&e)
}
}
#[cfg(any(not(feature = "alloc"), feature = "std"))]
impl<T> From<::std::sync::PoisonError<T>> for FlatError {
fn from(e: ::std::sync::PoisonError<T>) -> Self {
FlatError::from_any(&e)
}
}
#[cfg(any(not(feature = "alloc"), feature = "std"))]
impl<T> From<::std::sync::TryLockError<T>> for FlatError {
fn from(e: ::std::sync::TryLockError<T>) -> Self {
FlatError::from_any(&e)
}
}
#[cfg(any(not(feature = "alloc"), feature = "std"))]
impl From<::std::time::SystemTimeError> for FlatError {
fn from(e: ::std::time::SystemTimeError) -> Self {
FlatError::from_any(&e)
}
}