failed again. just fucking use eyre or color-eyre ffs

work
Avril 4 years ago
parent 9538f4bc46
commit 3d254efc4b
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -4,133 +4,320 @@ use std::{
fmt,
};
pub trait Context
#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd, Default)]
pub struct Context
{
fn line(&self) -> Option<u32>;
fn column(&self) -> Option<u32>;
fn file(&self) -> Option<&str>;
file: Option<&'static str>,
line: Option<u32>,
column: Option<u32>,
}
pub trait Reporter
impl Context
{
type Error: error::Error + ?Sized;
pub fn with_all(file: &'static str, line: u32, column: u32) -> Self
{
Self {
file: Some(file),
line: Some(line),
column: Some(column)
}
}
}
#[inline] fn context(&self) -> Option<&dyn Context>
impl fmt::Display for Context
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
None
if let Some(file) = self.file {
write!(f, "{} ", file)
} else {
write!(f, "? ")
}?;
if let Some(line) = self.line {
write!(f, "{}:", line)
} else {
write!(f, "?:")
}?;
if let Some(column) = self.column {
write!(f, "{}", column)
} else {
write!(f, "?")
}
}
fn source(&self) -> &Self::Error;
fn short_message(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result;
#[inline] fn long_message(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
}
#[macro_export] macro_rules! context {
() => ($crate::error::Context::with_all(file!(), line!(), column!()));
}
#[derive(Debug)]
pub struct ContextError<E>(E, Context)
where E: error::Error;
impl<E> ContextError<E>
where E: error::Error
{
pub fn with_context(from: E, ctx: Context) -> Self
{
self.short_message(f)
Self(from, ctx)
}
}
pub struct ShortMessage<R>(R)
where R: Reporter;
impl<E> error::Error for ContextError<E>
where E: error::Error + 'static
{
fn source(&self) -> Option<&(dyn error::Error + 'static)>
{
Some(&self.0)
}
}
impl<R> fmt::Display for ShortMessage<R>
where R: Reporter
impl<E> fmt::Display for ContextError<E>
where E: error::Error
{
#[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
self.0.short_message(f)
write!(f, "{}: {}", self.1, self.0)
}
}
pub struct LongMessage<R>(R)
where R: Reporter;
#[macro_export] macro_rules! error {
($msg:expr) => {
{
pub struct DisplayError<D>(D) where D: fmt::Display;
impl<D> fmt::Debug for DisplayError<D>
where D: fmt::Display
{
#[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
write!(f, "{}", std::any::type_name::<Self>())
}
}
impl<D> fmt::Display for DisplayError<D>
where D: fmt::Display
{
#[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
self.0.fmt(f)
}
}
impl<D> error::Error for DisplayError<D>
where D: fmt::Display{}
impl<R> fmt::Display for LongMessage<R>
where R: Reporter
$crate::error::ContextError::with_context(DisplayError($msg), context!())
}
};
(&fmt:literal $($tt:tt)*) => ($crate::error!(format!($literal $($tt)*)));
}
pub struct Wrap<E,D>(E,D);
impl<E,D> Wrap<E,D>
where E: error::Error + 'static,
D: fmt::Display
{
#[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
pub fn long_message(&self) -> impl fmt::Display + '_
{
self.0.long_message(f)
pub struct LongMessage<'a, E,D>(&'a Wrap<E,D>);
impl<'a, E,D> fmt::Display for LongMessage<'a,E,D>
where E: error::Error + 'static,
D: fmt::Display
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
use error::Error;
for (num, next) in (1..).zip(std::iter::successors(self.0.source(), |e| e.source()))
{
writeln!(f, " [{}] -> {}", num, next)?;
}
Ok(())
}
}
LongMessage(self)
}
}
impl<E> Reporter for Box<E>
where E: error::Error + ?Sized
impl<E,D> fmt::Display for Wrap<E,D>
where D: fmt::Display
{
type Error = E;
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
write!(f, "{}", self.1)
}
}
fn source(&self) -> &Self::Error
impl<E,D> fmt::Debug for Wrap<E,D>
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
&self
write!(f, "{}", std::any::type_name::<Self>())
}
fn short_message(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
}
impl<E,D> error::Error for Wrap<E,D>
where E: error::Error + 'static,
D: fmt::Display
{
fn source(&self) -> Option<&(dyn error::Error + 'static)>
{
write!(f, "{}", &self)
Some(&self.0)
}
}
impl<'a, R> Reporter for &'a R
where R: Reporter
pub trait WrapErrExt<T,E>: Sized
{
type Error = <R as Reporter>::Error;
#[inline] fn context(&self) -> Option<&dyn Context>
#[inline] fn wrap_err<F,D>(self, val: D) -> Result<T, Wrap<E, D>>
where D: fmt::Display
{
(*self).context()
self.wrap_err_with(|| val)
}
fn source(&self) -> &Self::Error
fn wrap_err_with<F,D>(self, func: F) -> Result<T, Wrap<E, D>>
where D: fmt::Display,
F: FnOnce() -> D;
}
impl<T,E> WrapErrExt<T,E> for Result<T,E>
{
fn wrap_err_with<F,D>(self, func: F) -> Result<T, Wrap<E, D>>
where D: fmt::Display,
F: FnOnce() -> D
{
(*self).source()
self.map_err(|e| Wrap(e, func()))
}
}
// We can now define the reporter trait, like last time, and then out own reporter type for `Wrap<E,D>` that prints its long message properly
pub trait Reporter
{
type Error: error::Error + ?Sized;
#[inline] fn long_message(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result
{
Ok(())
}
fn short_message(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result;
fn source(&self) -> &Self::Error;
}
impl<E> Reporter for Box<E>
where E: error::Error + ?Sized
{
type Error = E;
fn short_message(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
(*self).short_message(f)
write!(f, "{}", self)
}
#[inline] fn long_message(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
fn source(&self) -> &Self::Error
{
(*self).long_message(f)
self
}
}
pub struct Wrap<E,M>(E, M);
pub struct WrapReporter<E,D>(Wrap<E,D>);
impl<E,M> Reporter for Wrap<E,M>
where E: Reporter,
M: fmt::Display
impl<E,D> Reporter for WrapReporter<E,D>
where E: error::Error + 'static,
D: fmt::Display
{
type Error = E::Error;
type Error = E;
fn short_message(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
write!(f, "{}", self.0)
}
#[inline] fn context(&self) -> Option<&dyn Context>
fn long_message(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
self.0.context()
write!(f, "{}", self.0.long_message())
}
fn source(&self) -> &Self::Error
{
self.0.source()
&self.0.0
}
}
impl<E,D> From<Wrap<E,D>> for WrapReporter<E,D>
{
fn from(from: Wrap<E,D>) -> Self
{
Self(from)
}
}
pub struct Report<E>(Box<E>) where E: ?Sized;
impl<E> From<E> for Report<E>
where E: error::Error
{
fn from(from: E) -> Self
{
Self(Box::new(from))
}
}
impl<E> From<Box<E>> for Report<E>
where E: error::Error + 'static + ?Sized
{
fn from(from: Box<E>) -> Self
{
Self(from)
}
}
impl<E> Reporter for Report<E>
where E: error::Error + ?Sized
{
type Error = E;
fn short_message(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
write!(f, "{}", self.1)
write!(f, "{}", self.0)
}
#[inline] fn long_message(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
fn source(&self) -> &Self::Error
{
write!(f, "{}", self.1)?;
self.0.long_message(f) //ehh, also failed
&self.0
}
}
#[cfg(test)]
mod tests {
mod test
{
use super::*;
fn test() -> Box<dyn error::Error>
#[test]
fn test()
{
Box::new(std::io::Error::new(std::io::ErrorKind::UnexpectedEof, "uhhhhh"))
let err: Result<(), _> = Err(error!("hello world"))
.wrap_err_with(|| error!("thing failed"))
.wrap_err_with(|| error!("top level failed again"));
if let Err(err) = err
{
panic!("{}\n\n{}", err, err.long_message());
}
}
#[test]
fn atest()
fn report()
{
let bx = test();
assert_eq!(format!("{}", LongMessage(&bx)), format!("{}", bx));
fn one() -> Result<(), Report<dyn error::Error>>
{
let err: Result<(), _> = Err(error!("hello world"))
.wrap_err_with(|| error!("thing failed"))
.wrap_err_with(|| error!("top level failed again"));
Ok(err?) //failed again. just fucking use eyre
}
}
}

Loading…
Cancel
Save