1use std::error::Error;
2use std::fmt;
3
4#[derive(Debug, Clone, Eq, PartialEq)]
5pub struct AppError {
6 message: String,
7 exit_code: i32,
8}
9
10impl AppError {
11 pub fn new(message: impl Into<String>) -> Self {
12 Self {
13 message: message.into(),
14 exit_code: 1,
15 }
16 }
17
18 pub fn invalid_input(message: impl Into<String>) -> Self {
19 Self {
20 message: message.into(),
21 exit_code: 2,
22 }
23 }
24
25 pub fn message(&self) -> &str {
26 &self.message
27 }
28
29 pub fn exit_code(&self) -> i32 {
30 self.exit_code
31 }
32}
33
34impl fmt::Display for AppError {
35 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
36 formatter.write_str(&self.message)
37 }
38}
39
40impl Error for AppError {}
41
42#[cfg(test)]
43mod tests {
44 use super::*;
45
46 #[test]
47 fn invalid_input_uses_cli_error_exit_code() {
48 let error = AppError::invalid_input("bad value");
49
50 assert_eq!(error.message(), "bad value");
51 assert_eq!(error.exit_code(), 2);
52 assert_eq!(error.to_string(), "bad value");
53 }
54}