wee_woo/lib.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
#![no_std]
#![doc = env!("CARGO_PKG_DESCRIPTION")]
use core::{error::Error, fmt, iter};
/// An extension trait for [`Error`]s.
pub trait ErrorExt {
/// Attach a source to the current error.
///
/// The value of `source` will be returned by the [`Error::source`] and
/// [`Error::cause`] implementations of the returned value. Note that the
/// latter is deprecated.
///
/// See also [`ErrorExt::caused`]
fn with_source<Source>(
self,
source: Source,
) -> ErrorWithSource<Self, Source>
where
Self: Sized;
/// Set `self` as the source of the given error.
///
/// The value of `self` will be returned by the [`Error::source`] and
/// [`Error::cause`] implementations of the returned value. Note that the
/// latter is deprecated.
///
/// See also [`ErrorExt::with_source`]
fn caused<Error>(self, error: Error) -> ErrorWithSource<Error, Self>
where
Self: Sized;
/// [`Display`] an [`Error`] and its [`source`]s with a separator.
///
/// [`Display`]: fmt::Display
/// [`source`]: Error::source
fn display_with_sources<I>(&self, infix: I) -> DisplayWithSources<&Self, I>
where
Self: Sized;
}
impl<This> ErrorExt for This
where
This: Error,
{
fn with_source<Source>(
self,
source: Source,
) -> ErrorWithSource<Self, Source>
where
Self: Sized,
{
ErrorWithSource {
this: self,
source,
}
}
fn caused<Error>(self, error: Error) -> ErrorWithSource<Error, Self>
where
Self: Sized,
{
ErrorWithSource {
this: error,
source: self,
}
}
fn display_with_sources<I>(&self, infix: I) -> DisplayWithSources<&Self, I>
where
Self: Sized,
{
DisplayWithSources {
error: self,
infix,
}
}
}
/// [`Display`] an [`Error`] and its [`source`]s with a separator.
///
/// [`Display`]: fmt::Display
/// [`source`]: Error::source
pub struct DisplayWithSources<E, I> {
/// The error (and its sources) to write.
pub error: E,
/// Separator to write between the error and each subsequent source.
pub infix: I,
}
impl<E, I> fmt::Display for DisplayWithSources<E, I>
where
E: Error,
I: fmt::Display,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.error)?;
let mut source = self.error.source();
source
.into_iter()
.chain(iter::from_fn(|| {
source = source.and_then(Error::source);
source
}))
.try_for_each(|source| write!(f, "{}{source}", self.infix))
}
}
/// An [`Error`] with a [`source`] [`Error`].
///
/// This is useful for constructing ad-hoc chains of errors.
///
/// [`source`]: Error::source
#[derive(Debug)]
pub struct ErrorWithSource<This, Source> {
/// The current error.
///
/// Note that calling [`Error::source`] on an [`ErrorWithSource`] will not
/// call [`Error::source`] on [`this`]; [`source`] will always be returned
/// instead.
///
/// [`this`]: ErrorWithSource#structfield.this
/// [`source`]: ErrorWithSource#structfield.source
pub this: This,
/// The error that caused the current error.
///
/// This value will be returned by [`ErrorWithSource`]'s [`Error::source`]
/// and [`Error::cause`] implementations. Note that the latter is
/// deprecated.
pub source: Source,
}
impl<This, Source> Error for ErrorWithSource<This, Source>
where
This: fmt::Display + fmt::Debug,
Source: Error + 'static,
{
fn source(&self) -> Option<&(dyn Error + 'static)> {
Some(&self.source)
}
fn cause(&self) -> Option<&dyn Error> {
Some(&self.source)
}
}
impl<This, Source> fmt::Display for ErrorWithSource<This, Source>
where
This: fmt::Display,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.this.fmt(f)
}
}