human_errors/helpers.rs
1pub use super::Error;
2use std::error;
3
4/// A basic error triggered by something the user has done.
5///
6/// Constructs a new [Error] describing a failure which was the result of an
7/// action that the user has taken. This error includes a description of what
8/// occurred, as well as some advice for the user to try to mitigate the problem.
9///
10/// # Examples
11/// ```
12/// use human_errors;
13///
14/// human_errors::user(
15/// "We could not open the config file you provided.",
16/// "Make sure that the file exists and is readable by the application.",
17/// );
18/// ```
19pub fn user(description: &str, advice: &str) -> Error {
20 Error::UserError(description.to_string(), advice.to_string(), None, None)
21}
22
23/// An error triggered by something the user has done, with a deeper cause.
24///
25/// Constructs a new [Error] describing a failure which was the result of an
26/// action that the user has taken. This error includes a description of what
27/// occurred, as well as some advice for the user to try to mitigate the problem.
28/// It also includes the details of another error which resulted in this failure,
29/// as well as any advice that error may provide.
30///
31/// # Examples
32/// ```
33/// use human_errors;
34///
35/// human_errors::user_with_cause(
36/// "We could not open the config file you provided.",
37/// "Make sure that you've specified a valid config file with the --config option.",
38/// human_errors::user(
39/// "We could not find a file at /home/user/.config/demo.yml",
40/// "Make sure that the file exists and is readable by the application."
41/// )
42/// );
43/// ```
44pub fn user_with_cause(description: &str, advice: &str, cause: Error) -> Error {
45 Error::UserError(
46 description.to_string(),
47 advice.to_string(),
48 Some(Box::from(cause)),
49 None,
50 )
51}
52
53/// An error triggered by something the user has done, with a deeper cause.
54///
55/// Constructs a new [Error] describing a failure which was the result of an
56/// action that the user has taken. This error includes a description of what
57/// occurred, as well as some advice for the user to try to mitigate the problem.
58/// It also includes the details of another error which resulted in this failure.
59///
60/// **NOTE**: The internal error may be any type which may be converted into a [Box<std::error::Error>].
61///
62/// # Examples
63/// ```
64/// use human_errors;
65///
66/// human_errors::user_with_internal(
67/// "We could not open the config file you provided.",
68/// "Make sure that the file exists and is readable by the application.",
69/// human_errors::detailed_message("ENOENT 2: No such file or directory")
70/// );
71/// ```
72pub fn user_with_internal<T>(description: &str, advice: &str, internal: T) -> Error
73where
74 T: Into<Box<dyn error::Error + Send + Sync>>,
75{
76 Error::UserError(
77 description.to_string(),
78 advice.to_string(),
79 None,
80 Some(internal.into()),
81 )
82}
83
84/// An error triggered by the system rather than the user.
85///
86/// Constructs a new [Error] describing a failure which was the result of a failure
87/// in the system, rather than a user's action. This error includes a description of what
88/// occurred, as well as some advice for the user to try to mitigate the problem.
89///
90/// # Examples
91/// ```
92/// use human_errors;
93///
94/// human_errors::system(
95/// "We could not open the config file you provided.",
96/// "Make sure that the file exists and is readable by the application."
97/// );
98/// ```
99pub fn system(description: &str, advice: &str) -> Error {
100 Error::SystemError(description.to_string(), advice.to_string(), None, None)
101}
102
103/// An error triggered by the system rather than the user, with a deeper cause.
104///
105/// Constructs a new [Error] describing a failure which was the result of a failure
106/// in the system, rather than a user's action. This error includes a description of what
107/// occurred, as well as some advice for the user to try to mitigate the problem.
108/// It also includes the details of another error which resulted in this failure,
109/// as well as any advice that error may provide.
110///
111/// # Examples
112/// ```
113/// use human_errors;
114///
115/// human_errors::system_with_cause(
116/// "We could not open the config file you provided.",
117/// "Make sure that you've specified a valid config file with the --config option.",
118/// human_errors::system(
119/// "We could not find a file at /home/user/.config/demo.yml",
120/// "Make sure that the file exists and is readable by the application."
121/// )
122/// );
123/// ```
124pub fn system_with_cause(description: &str, advice: &str, cause: Error) -> Error {
125 Error::SystemError(
126 description.to_string(),
127 advice.to_string(),
128 Some(Box::from(cause)),
129 None,
130 )
131}
132
133/// An error triggered by the system rather than the user, with a deeper cause.
134///
135/// Constructs a new [Error] describing a failure which was the result of a failure
136/// in the system, rather than a user's action. This error includes a description of what
137/// occurred, as well as some advice for the user to try to mitigate the problem.
138/// It also includes the details of another error which resulted in this failure.
139///
140/// **NOTE**: The internal error may be any type which may be converted into a [Box<std::error::Error>].
141///
142/// # Examples
143/// ```
144/// use human_errors;
145///
146/// human_errors::system_with_internal(
147/// "We could not open the config file you provided.",
148/// "Make sure that the file exists and is readable by the application.",
149/// human_errors::detailed_message("ENOENT 2: No such file or directory")
150/// );
151/// ```
152pub fn system_with_internal<T>(description: &str, advice: &str, internal: T) -> Error
153where
154 T: Into<Box<dyn error::Error + Send + Sync>>,
155{
156 Error::SystemError(
157 description.to_string(),
158 advice.to_string(),
159 None,
160 Some(internal.into()),
161 )
162}
163
164#[cfg(test)]
165mod tests {
166 use super::*;
167
168 #[test]
169 fn test_description() {
170 assert_eq!(
171 user(
172 "Something bad happened",
173 "Avoid bad things happening in future"
174 )
175 .description(),
176 "Something bad happened"
177 );
178
179 assert_eq!(
180 system(
181 "Something bad happened",
182 "Avoid bad things happening in future"
183 )
184 .description(),
185 "Something bad happened"
186 );
187 }
188
189 #[test]
190 fn test_message_basic() {
191 assert_eq!(
192 user(
193 "Something bad happened.",
194 "Avoid bad things happening in future"
195 )
196 .message(),
197 "Oh no! Something bad happened.\n\nTo try and fix this, you can:\n - Avoid bad things happening in future"
198 );
199
200 assert_eq!(
201 system(
202 "Something bad happened.",
203 "Avoid bad things happening in future"
204 )
205 .message(),
206 "Whoops! Something bad happened. (This isn't your fault)\n\nTo try and fix this, you can:\n - Avoid bad things happening in future"
207 );
208 }
209
210 #[test]
211 fn test_message_cause() {
212 assert_eq!(
213 user_with_cause(
214 "Something bad happened.",
215 "Avoid bad things happening in future",
216 user("You got rate limited by GitHub.", "Wait a few minutes and try again.")
217 )
218 .message(),
219 "Oh no! Something bad happened.\n\nThis was caused by:\n - You got rate limited by GitHub.\n\nTo try and fix this, you can:\n - Wait a few minutes and try again.\n - Avoid bad things happening in future"
220 );
221
222 assert_eq!(
223 system_with_cause(
224 "Something bad happened.",
225 "Avoid bad things happening in future",
226 system("You got rate limited by GitHub.", "Wait a few minutes and try again.")
227 )
228 .message(),
229 "Whoops! Something bad happened. (This isn't your fault)\n\nThis was caused by:\n - You got rate limited by GitHub.\n\nTo try and fix this, you can:\n - Wait a few minutes and try again.\n - Avoid bad things happening in future"
230 );
231 }
232
233 #[test]
234 fn test_message_empty_causes() {
235 assert_eq!(
236 user_with_cause(
237 "Something bad happened.",
238 "",
239 user("You got rate limited by GitHub.", "Wait a few minutes and try again.")
240 )
241 .message(),
242 "Oh no! Something bad happened.\n\nThis was caused by:\n - You got rate limited by GitHub.\n\nTo try and fix this, you can:\n - Wait a few minutes and try again."
243 );
244 }
245}