signet 0.0.1

code signing tool
Documentation
use std::fmt;
use std::io::{self, ErrorKind};
use std::path::{Path, PathBuf};

#[derive(Debug)]
pub struct Error {
    cause: Cause,
    path:  PathBuf
}

#[derive(Debug)]
pub enum Cause {
    Invalid(serde_yaml::Error),
    Missing(io::Error),
    System(io::Error),
}

pub trait Context<T> {
    fn context(self, path: &Path) -> Result<T, Error>;
}

impl<T, E: Into<Cause>> Context<T> for Result<T, E> {
    fn context(self, path: &Path) -> Result<T, Error> {
        self.map_err(|error| Error {
            cause: error.into(),
            path:  path.to_owned(),
        })
    }
}

impl std::error::Error for Error {}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let path = self.path.display();
        match &self.cause {
            Cause::Invalid(error) => write!(f, "{path}: {error}"),
            Cause::Missing(_)     => write!(f, "{path} not found"),
            Cause::System(error)  => write!(f, "{path}: {error}"),
        }
    }
}

impl From<io::Error> for Cause {
    fn from(error: io::Error) -> Self {
        match error.kind() {
            ErrorKind::NotFound => Self::Missing(error),
            _                   => Self::System(error),
        }
    }
}

impl From<serde_yaml::Error> for Cause {
    fn from(error: serde_yaml::Error) -> Self {
        Self::Invalid(error)
    }
}