logerr 0.1.0

Seamless error type logging
Documentation
use std::error::Error;
use crate::LoggableError;

/// Macro to derive `LoggableError` on types from the stdlib
macro_rules! generate_impl {
    ($err:ty) => {
        impl<T> LoggableError<T> for Result<T, $err> {
            fn print_error<F: Fn(&str)>(self, fun: F) -> Self {
                if let Err(ref err) = self {
                    let mut msg = format!("ERROR: {err}");
                    if let Some(cause) = err.source() {
                        msg = format!("{msg}\ncause: {}", cause.to_string());
                    }
                    fun(&msg);
                }
                self
            }
        }
    }
}

// std::alloc
generate_impl!(std::alloc::LayoutError);

// std::cell
generate_impl!(std::cell::BorrowError);
generate_impl!(std::cell::BorrowMutError);

// std::char
generate_impl!(std::char::CharTryFromError);
generate_impl!(std::char::DecodeUtf16Error);
generate_impl!(std::char::ParseCharError);
generate_impl!(std::char::TryFromCharError);

// std::collections
generate_impl!(std::collections::TryReserveError);

// std::convert
generate_impl!(std::convert::Infallible);

// std::env
generate_impl!(std::env::JoinPathsError);
generate_impl!(std::env::VarError);

// std::error
// TODO: Maybe have a look at Report?

// std::ffi
generate_impl!(std::ffi::FromBytesWithNulError);
generate_impl!(std::ffi::FromVecWithNulError);
generate_impl!(std::ffi::IntoStringError);
generate_impl!(std::ffi::NulError);

// std::fmt
generate_impl!(std::fmt::Error);

// std::io
generate_impl!(std::io::Error);
impl<T, W: Send + std::fmt::Debug> LoggableError<T> for Result<T, std::io::IntoInnerError<W>> {
    fn print_error<F: Fn(&str)>(self, fun: F) -> Self {
        if let Err(ref err) = self {
            let mut msg = format!("ERROR: {err}");
            if let Some(cause) = err.source() {
                msg = format!("{msg}\ncause: {}", cause.to_string());
            }
            fun(&msg);
        }
        self
    }
}
generate_impl!(std::io::WriterPanicked);

// std::net
generate_impl!(std::net::AddrParseError);

// std::num
generate_impl!(std::num::ParseFloatError);
generate_impl!(std::num::ParseIntError);
generate_impl!(std::num::TryFromIntError);

// std::os
#[cfg(windows)]
generate_impl!(std::os::windows::io::InvalidHandleError);
#[cfg(windows)]
generate_impl!(std::os::windows::io::NullHandleError);

// std::path
generate_impl!(std::path::StripPrefixError);

// std::str
generate_impl!(std::str::ParseBoolError);
generate_impl!(std::str::Utf8Error);

// std::string
generate_impl!(std::string::FromUtf8Error);
generate_impl!(std::string::FromUtf16Error);

// std::sync
generate_impl!(std::sync::PoisonError<T>);
generate_impl!(std::sync::TryLockError<T>);

// std::thread
generate_impl!(std::thread::AccessError);

// std::time
generate_impl!(std::time::SystemTimeError);