cargo_build_dist/
errors.rs1use std::fmt::Display;
2
3#[derive(thiserror::Error, Debug)]
8pub struct Error {
9 description: String,
10 explanation: Option<String>,
11 #[source]
12 source: Option<anyhow::Error>,
13 output: Option<String>,
14}
15
16impl Error {
17 pub fn new(description: impl Into<String>) -> Self {
18 Self {
19 description: description.into(),
20 explanation: None,
21 source: None,
22 output: None,
23 }
24 }
25
26 pub fn from_source(source: impl Into<anyhow::Error>) -> Self {
27 Self::new("").with_source(source)
28 }
29
30 pub fn with_source(mut self, source: impl Into<anyhow::Error>) -> Self {
31 self.source = Some(source.into());
32
33 self
34 }
35
36 pub fn with_explanation(mut self, explanation: impl Into<String>) -> Self {
37 self.explanation = Some(explanation.into());
38
39 self
40 }
41
42 pub fn with_output(mut self, output: impl Into<String>) -> Self {
43 self.output = Some(output.into());
44
45 self
46 }
47
48 pub fn description(&self) -> &str {
49 &self.description
50 }
51
52 pub fn source(&self) -> Option<&anyhow::Error> {
53 self.source.as_ref()
54 }
55
56 pub fn explanation(&self) -> Option<&str> {
57 self.explanation.as_deref()
58 }
59
60 pub fn output(&self) -> Option<&str> {
61 self.output.as_deref()
62 }
63
64 pub fn with_context(mut self, description: impl Into<String>) -> Self {
65 if self.description.is_empty() {
66 self.description = description.into();
67
68 self
69 } else {
70 Self::new(description).with_source(self)
71 }
72 }
73}
74
75pub(crate) trait ErrorContext {
76 fn with_context(self, description: impl Into<String>) -> Self;
77 fn with_full_context(
78 self,
79 description: impl Into<String>,
80 explanation: impl Into<String>,
81 ) -> Self;
82}
83
84impl<T> ErrorContext for Result<T> {
85 fn with_context(self, description: impl Into<String>) -> Self {
86 self.map_err(|e| e.with_context(description))
87 }
88
89 fn with_full_context(
90 self,
91 description: impl Into<String>,
92 explanation: impl Into<String>,
93 ) -> Self {
94 self.map_err(|e| e.with_context(description).with_explanation(explanation))
95 }
96}
97
98impl Display for Error {
99 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
100 write!(f, "{}", self.description)?;
101
102 if let Some(source) = self.source.as_ref() {
103 write!(f, ": {}", source)?;
104 }
105
106 if let Some(explanation) = &self.explanation {
107 write!(f, "\n\n{}", explanation)?;
108 }
109
110 Ok(())
111 }
112}
113
114pub type Result<T> = std::result::Result<T, Error>;