ptx_builder/
error.rs

1use std::fmt;
2use std::path::PathBuf;
3
4use colored::*;
5use failure::{Backtrace, Context, Fail};
6use semver::{Version, VersionReq};
7
8#[macro_export]
9macro_rules! bail {
10    ($err:expr) => {
11        return Err($err.into());
12    };
13}
14
15pub type Result<T> = std::result::Result<T, Error>;
16
17#[derive(Debug)]
18pub struct Error {
19    inner: Context<BuildErrorKind>,
20}
21
22#[derive(Debug, PartialEq, Fail, Clone)]
23pub enum BuildErrorKind {
24    CommandNotFound {
25        command: String,
26        hint: String,
27    },
28
29    CommandFailed {
30        command: String,
31        code: i32,
32        stderr: String,
33    },
34    CommandVersionNotFulfilled {
35        command: String,
36        current: Version,
37        required: VersionReq,
38        hint: String,
39    },
40
41    InvalidCratePath(PathBuf),
42    BuildFailed(Vec<String>),
43    InvalidCrateType(String),
44    MissingCrateType,
45    InternalError(String),
46    OtherError,
47}
48
49impl Fail for Error {
50    fn name(&self) -> Option<&str> {
51        self.inner.name()
52    }
53
54    fn cause(&self) -> Option<&Fail> {
55        self.inner.cause()
56    }
57
58    fn backtrace(&self) -> Option<&Backtrace> {
59        self.inner.backtrace()
60    }
61}
62
63impl fmt::Display for Error {
64    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
65        fmt::Display::fmt(&self.inner, formatter)
66    }
67}
68
69impl Error {
70    pub fn kind(&self) -> BuildErrorKind {
71        self.inner.get_context().clone()
72    }
73}
74
75impl From<BuildErrorKind> for Error {
76    fn from(kind: BuildErrorKind) -> Error {
77        Error {
78            inner: Context::new(kind),
79        }
80    }
81}
82
83impl From<Context<BuildErrorKind>> for Error {
84    fn from(inner: Context<BuildErrorKind>) -> Error {
85        Error { inner }
86    }
87}
88
89impl From<Context<String>> for Error {
90    fn from(inner: Context<String>) -> Error {
91        Error {
92            inner: inner.map(BuildErrorKind::InternalError),
93        }
94    }
95}
96
97impl<'a> From<Context<&'a str>> for Error {
98    fn from(inner: Context<&'a str>) -> Error {
99        Self::from(inner.map(String::from))
100    }
101}
102
103impl fmt::Display for BuildErrorKind {
104    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
105        use BuildErrorKind::*;
106
107        match self {
108            CommandNotFound { command, hint } => write!(
109                formatter,
110                "Command not found in PATH: '{}'. {}.",
111                command.bold(),
112                hint.underline()
113            ),
114
115            CommandFailed {
116                command,
117                code,
118                stderr,
119            } => write!(
120                formatter,
121                "Command failed: '{}' with code '{}' and output:\n{}",
122                command.bold(),
123                code,
124                stderr.trim(),
125            ),
126
127            CommandVersionNotFulfilled {
128                command,
129                current,
130                required,
131                hint,
132            } => write!(
133                formatter,
134                "Command version is not fulfilled: '{}' is currently '{}' but '{}' is required. {}.",
135                command.bold(),
136                current.to_string().underline(),
137                required.to_string().underline(),
138                hint.underline(),
139            ),
140
141            InvalidCratePath(path) => write!(
142                formatter,
143                "{}: {}",
144                "Invalid device crate path".bold(),
145                path.display()
146            ),
147
148            BuildFailed(lines) => write!(
149                formatter,
150                "{}\n{}",
151                "Unable to build a PTX crate!".bold(),
152                lines.join("\n")
153            ),
154
155            InvalidCrateType(crate_type) => write!(
156                formatter,
157                "{}: the crate cannot be build as '{}'",
158                "Impossible CrateType".bold(),
159                crate_type
160            ),
161
162            MissingCrateType => write!(
163                formatter,
164                "{}: it's mandatory for mixed-type crates",
165                "Missing CrateType".bold()
166            ),
167
168            InternalError(message) => write!(formatter, "{}: {}", "Internal error".bold(), message),
169            OtherError => write!(formatter, "Other error"),
170        }
171    }
172}