substrate_manager/util/
errors.rs

1use core::fmt;
2
3use anyhow::{anyhow, Error};
4use color_eyre::Report;
5
6pub type SubstrateResult<T> = anyhow::Result<T>;
7
8// =============================================================================
9// Verbose error
10
11/// An error wrapper for errors that should only be displayed with `--verbose`.
12///
13/// This should only be used in rare cases. When emitting this error, you
14/// should have a normal error higher up the error-cause chain (like "could
15/// not compile `foo`"), so at least *something* gets printed without
16/// `--verbose`.
17pub struct VerboseError {
18    inner: Error,
19}
20
21impl VerboseError {
22    pub fn new(inner: Error) -> VerboseError {
23        VerboseError { inner }
24    }
25}
26
27impl std::error::Error for VerboseError {
28    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
29        self.inner.source()
30    }
31}
32
33impl fmt::Debug for VerboseError {
34    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
35        self.inner.fmt(f)
36    }
37}
38
39impl fmt::Display for VerboseError {
40    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
41        self.inner.fmt(f)
42    }
43}
44
45// =============================================================================
46// Internal error
47
48/// An unexpected, internal error.
49///
50/// This should only be used for unexpected errors. It prints a message asking
51/// the user to file a bug report.
52pub struct InternalError {
53    inner: Error,
54}
55
56impl InternalError {
57    pub fn new(inner: Error) -> InternalError {
58        InternalError { inner }
59    }
60}
61
62impl std::error::Error for InternalError {
63    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
64        self.inner.source()
65    }
66}
67
68impl fmt::Debug for InternalError {
69    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
70        self.inner.fmt(f)
71    }
72}
73
74impl fmt::Display for InternalError {
75    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
76        self.inner.fmt(f)
77    }
78}
79
80// =============================================================================
81// Already printed error
82
83/// An error that does not need to be printed because it does not add any new
84/// information to what has already been printed.
85pub struct AlreadyPrintedError {
86    inner: Error,
87}
88
89impl AlreadyPrintedError {
90    pub fn new(inner: Error) -> Self {
91        AlreadyPrintedError { inner }
92    }
93}
94
95impl std::error::Error for AlreadyPrintedError {
96    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
97        self.inner.source()
98    }
99}
100
101impl fmt::Debug for AlreadyPrintedError {
102    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
103        self.inner.fmt(f)
104    }
105}
106
107impl fmt::Display for AlreadyPrintedError {
108    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
109        self.inner.fmt(f)
110    }
111}
112
113// =============================================================================
114// CLI errors
115
116pub type CliResult = Result<(), CliError>;
117
118#[derive(Debug)]
119/// The CLI error is the error type used at Substrate's CLI-layer.
120///
121/// All errors from the lib side of Substrate will get wrapped with this error.
122/// Other errors (such as command-line argument validation) will create this
123/// directly.
124pub struct CliError {
125    pub error: Option<anyhow::Error>,
126    /// The process exit code.
127    pub exit_code: i32,
128}
129
130impl CliError {
131    pub fn new(error: anyhow::Error, code: i32) -> CliError {
132        CliError {
133            error: Some(error),
134            exit_code: code,
135        }
136    }
137
138    pub fn code(code: i32) -> CliError {
139        CliError {
140            error: None,
141            exit_code: code,
142        }
143    }
144}
145
146impl From<anyhow::Error> for CliError {
147    fn from(err: anyhow::Error) -> CliError {
148        CliError::new(err, 101)
149    }
150}
151
152impl From<clap::Error> for CliError {
153    fn from(err: clap::Error) -> CliError {
154        let code = if err.use_stderr() { 1 } else { 0 };
155        CliError::new(err.into(), code)
156    }
157}
158
159impl From<std::io::Error> for CliError {
160    fn from(err: std::io::Error) -> CliError {
161        CliError::new(err.into(), 1)
162    }
163}
164
165impl From<Report> for CliError {
166    fn from(err: color_eyre::Report) -> CliError {
167        CliError {
168            error: Some(anyhow!(err)),
169            exit_code: 1,
170        }
171    }
172}