docket 0.7.1

Simple markdown to HTML documentation rendering
use std::{io, path::PathBuf};

/// Docket Error Type
///
/// This type contains all the error kinds generated by Docket. Some library
/// functions may return more specific error kinds. All error kinds used within
/// this project should be coercable to this type.
#[derive(Debug)]
pub enum Error {
    /// Source path for documentation set was not a directory
    SourcePathNotADirectory(PathBuf),
    /// A generic IO Error occured
    Io(io::Error),
    /// Annotated inner error
    Annotated(String, Box<dyn std::error::Error>),
}

impl Error {
    pub fn annotated<S, E>(anno: S, err: E) -> Self
    where
        S: Into<String>,
        E: std::error::Error + 'static,
    {
        Error::Annotated(anno.into(), Box::new(err))
    }
}

impl std::fmt::Display for Error {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Error::SourcePathNotADirectory(path) => {
                write!(
                    f,
                    "Source path is not a directory, or can not be opened: {:?}",
                    path
                )
            }
            Error::Io(io) => io.fmt(f),
            Error::Annotated(anno, e) => {
                write!(f, "{}: {}", anno, e)
            }
        }
    }
}

impl std::error::Error for Error {
    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        match self {
            Error::Io(ioerr) => Some(ioerr),
            _ => None,
        }
    }
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Self {
        Error::Io(err)
    }
}

/// Docket Result Type
///
/// Shorthand result type for functions returning docket errors.
pub type Result<T> = std::result::Result<T, Error>;

pub(crate) trait ResultExt<T, A: Into<String>> {
    fn annotate_err(self, anno: A) -> Result<T>;
}

impl<T, E, A> ResultExt<T, A> for std::result::Result<T, E>
where
    E: std::error::Error + 'static,
    A: Into<String>,
{
    fn annotate_err(self, anno: A) -> Result<T> {
        self.map_err(|err| Error::annotated(anno, err))
    }
}