ptx-builder 0.5.3

NVPTX build helper
Documentation
use std::fmt;
use std::path::PathBuf;

use colored::*;
use failure::{Backtrace, Context, Fail};
use semver::{Version, VersionReq};

#[macro_export]
macro_rules! bail {
    ($err:expr) => {
        return Err($err.into());
    };
}

pub type Result<T> = std::result::Result<T, Error>;

#[derive(Debug)]
pub struct Error {
    inner: Context<BuildErrorKind>,
}

#[derive(Debug, PartialEq, Fail, Clone)]
pub enum BuildErrorKind {
    CommandNotFound {
        command: String,
        hint: String,
    },

    CommandFailed {
        command: String,
        code: i32,
        stderr: String,
    },
    CommandVersionNotFulfilled {
        command: String,
        current: Version,
        required: VersionReq,
        hint: String,
    },

    InvalidCratePath(PathBuf),
    BuildFailed(Vec<String>),
    InvalidCrateType(String),
    MissingCrateType,
    InternalError(String),
    OtherError,
}

impl Fail for Error {
    fn name(&self) -> Option<&str> {
        self.inner.name()
    }

    fn cause(&self) -> Option<&Fail> {
        self.inner.cause()
    }

    fn backtrace(&self) -> Option<&Backtrace> {
        self.inner.backtrace()
    }
}

impl fmt::Display for Error {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&self.inner, formatter)
    }
}

impl Error {
    pub fn kind(&self) -> BuildErrorKind {
        self.inner.get_context().clone()
    }
}

impl From<BuildErrorKind> for Error {
    fn from(kind: BuildErrorKind) -> Error {
        Error {
            inner: Context::new(kind),
        }
    }
}

impl From<Context<BuildErrorKind>> for Error {
    fn from(inner: Context<BuildErrorKind>) -> Error {
        Error { inner }
    }
}

impl From<Context<String>> for Error {
    fn from(inner: Context<String>) -> Error {
        Error {
            inner: inner.map(BuildErrorKind::InternalError),
        }
    }
}

impl<'a> From<Context<&'a str>> for Error {
    fn from(inner: Context<&'a str>) -> Error {
        Self::from(inner.map(String::from))
    }
}

impl fmt::Display for BuildErrorKind {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        use BuildErrorKind::*;

        match self {
            CommandNotFound { command, hint } => write!(
                formatter,
                "Command not found in PATH: '{}'. {}.",
                command.bold(),
                hint.underline()
            ),

            CommandFailed {
                command,
                code,
                stderr,
            } => write!(
                formatter,
                "Command failed: '{}' with code '{}' and output:\n{}",
                command.bold(),
                code,
                stderr.trim(),
            ),

            CommandVersionNotFulfilled {
                command,
                current,
                required,
                hint,
            } => write!(
                formatter,
                "Command version is not fulfilled: '{}' is currently '{}' but '{}' is required. {}.",
                command.bold(),
                current.to_string().underline(),
                required.to_string().underline(),
                hint.underline(),
            ),

            InvalidCratePath(path) => write!(
                formatter,
                "{}: {}",
                "Invalid device crate path".bold(),
                path.display()
            ),

            BuildFailed(lines) => write!(
                formatter,
                "{}\n{}",
                "Unable to build a PTX crate!".bold(),
                lines.join("\n")
            ),

            InvalidCrateType(crate_type) => write!(
                formatter,
                "{}: the crate cannot be build as '{}'",
                "Impossible CrateType".bold(),
                crate_type
            ),

            MissingCrateType => write!(
                formatter,
                "{}: it's mandatory for mixed-type crates",
                "Missing CrateType".bold()
            ),

            InternalError(message) => write!(formatter, "{}: {}", "Internal error".bold(), message),
            OtherError => write!(formatter, "Other error"),
        }
    }
}