diagprint 0.8.1

A Rust diagnostics lifecycle framework for structured diagnostics, rendering, remediation, CI, editors, and telemetry.
Documentation
use crate::Cause;
use std::{error::Error, io as std_io};

pub(crate) mod io;

pub(crate) fn cause_chain<I, S>(messages: I) -> Option<Cause>
where
    I: IntoIterator<Item = S>,
    S: Into<String>,
{
    let messages: Vec<String> = messages.into_iter().map(Into::into).collect();

    let mut current = None;

    for message in messages.into_iter().rev() {
        current = Some(match current.take() {
            Some(source) => Cause::new(message).caused_by(source),
            None => Cause::new(message),
        });
    }

    current
}

pub(crate) fn cause_chain_from_sources<E>(error: &E) -> Option<Cause>
where
    E: Error + ?Sized,
{
    let mut messages = Vec::new();
    let mut current = error.source();

    while let Some(source) = current {
        messages.push(source.to_string());
        current = source.source();
    }

    cause_chain(messages)
}

pub(crate) fn find_io_error_in_sources<E>(error: &E) -> Option<&std_io::Error>
where
    E: Error + ?Sized + 'static,
{
    let mut current = error.source();

    while let Some(source) = current {
        if let Some(io_error) = source.downcast_ref::<std_io::Error>() {
            return Some(io_error);
        }

        current = source.source();
    }

    None
}