#![cfg_attr(feature = "std", doc = include_str!("../README.md"))]
#![cfg_attr(
not(feature = "std"),
doc = "Quality of life utilities for error handling in Rust."
)]
#![cfg_attr(not(any(feature = "std", test)), no_std)]
#![warn(missing_docs)]
#[cfg(feature = "alloc")]
extern crate alloc;
use core::{error::Error, fmt, iter, marker::PhantomData};
use derive_where::derive_where;
mod add;
mod chain;
mod connectors;
pub mod indent;
mod main_result;
#[cfg(feature = "alloc")]
pub mod many_errors;
mod oneline;
#[cfg(feature = "std")]
pub mod path_display;
mod suggestion;
pub mod with_context;
pub use add::{Add, separator};
pub use chain::Chain;
pub use connectors::{Ascii, Connectors, TreeConnectors, Unicode};
pub use main_result::{DisplaySwapDebug, MainResult, MainResultWithSuggestion, WithSuggestion};
#[cfg(feature = "alloc")]
pub use many_errors::{
Bullets, IntoIter, Iter, IterMut, Joined, List, ManyErrors, Node, Subgroup, Tree,
};
pub use oneline::OneLine;
#[cfg(feature = "std")]
pub use path_display::DisplayPath;
pub use suggestion::{Suggest, Suggestion};
pub use with_context::WithContext;
pub trait Format<E: ?Sized> {
fn fmt(error: &E, f: &mut fmt::Formatter<'_>) -> fmt::Result;
}
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct AsDisplay;
impl<T: fmt::Display + ?Sized> Format<T> for AsDisplay {
fn fmt(value: &T, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(value, f)
}
}
pub fn chain<'a>(error: &'a dyn Error) -> impl Iterator<Item = &'a dyn Error> + 'a {
iter::successors(Some(error), |e| Error::source(*e))
}
pub trait FormatError {
fn one_line(&self) -> Formatted<&Self, OneLine> {
self.formatted::<OneLine>()
}
fn chain(&self) -> Formatted<&Self, Chain> {
self.formatted::<Chain>()
}
fn suggestion(&self) -> Formatted<&Self, Suggestion>
where
Self: Suggest,
{
self.formatted::<Suggestion>()
}
fn formatted<F>(&self) -> Formatted<&Self, F> {
Formatted::new(self)
}
}
impl<E: Error + ?Sized> FormatError for E {}
#[derive_where(Clone, Copy, Default, PartialEq, Eq, Hash; E)]
pub struct Formatted<E, F = OneLine>(E, PhantomData<fn() -> F>);
impl<E, F> Formatted<E, F> {
pub const fn new(error: E) -> Self {
Formatted(error, PhantomData)
}
}
impl<E, F: Format<E>> fmt::Display for Formatted<E, F> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
F::fmt(&self.0, f)
}
}
impl<E: fmt::Debug, F: fmt::Debug + Default> fmt::Debug for Formatted<E, F> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Formatted")
.field("error", &self.0)
.field("format", &F::default())
.finish()
}
}
#[cfg(test)]
pub(crate) mod tests;