1use thiserror::Error;
6
7pub type Result<T> = std::result::Result<T, Error>;
9
10#[derive(Error, Debug)]
12pub enum Error {
13 #[error("Configuration error: {0}")]
15 Config(String),
16
17 #[error("Invalid path: {0}")]
19 InvalidPath(String),
20
21 #[error("Alias not found: {0}")]
23 AliasNotFound(String),
24
25 #[error("Alias already exists: {0}")]
27 AliasExists(String),
28
29 #[error("IO error: {0}")]
31 Io(#[from] std::io::Error),
32
33 #[error("TOML parse error: {0}")]
35 TomlParse(#[from] toml::de::Error),
36
37 #[error("TOML serialization error: {0}")]
39 TomlSerialize(#[from] toml::ser::Error),
40
41 #[error("JSON error: {0}")]
43 Json(#[from] serde_json::Error),
44
45 #[error("Invalid URL: {0}")]
47 InvalidUrl(#[from] url::ParseError),
48
49 #[error("Authentication failed: {0}")]
51 Auth(String),
52
53 #[error("Not found: {0}")]
55 NotFound(String),
56
57 #[error("Network error: {0}")]
59 Network(String),
60
61 #[error("Conflict: {0}")]
63 Conflict(String),
64
65 #[error("Unsupported feature: {0}")]
67 UnsupportedFeature(String),
68
69 #[error("{0}")]
71 General(String),
72}
73
74impl Error {
75 pub const fn exit_code(&self) -> i32 {
77 match self {
78 Error::InvalidPath(_) => 2, Error::Config(_) => 2, Error::Network(_) => 3, Error::Auth(_) => 4, Error::NotFound(_) | Error::AliasNotFound(_) => 5, Error::Conflict(_) | Error::AliasExists(_) => 6, Error::UnsupportedFeature(_) => 7, _ => 1, }
87 }
88}
89
90#[cfg(test)]
91mod tests {
92 use super::*;
93
94 #[test]
95 fn test_error_exit_codes() {
96 assert_eq!(Error::InvalidPath("test".into()).exit_code(), 2);
97 assert_eq!(Error::Config("test".into()).exit_code(), 2);
98 assert_eq!(Error::Network("test".into()).exit_code(), 3);
99 assert_eq!(Error::Auth("test".into()).exit_code(), 4);
100 assert_eq!(Error::NotFound("test".into()).exit_code(), 5);
101 assert_eq!(Error::AliasNotFound("test".into()).exit_code(), 5);
102 assert_eq!(Error::Conflict("test".into()).exit_code(), 6);
103 assert_eq!(Error::AliasExists("test".into()).exit_code(), 6);
104 assert_eq!(Error::UnsupportedFeature("test".into()).exit_code(), 7);
105 assert_eq!(Error::General("test".into()).exit_code(), 1);
106 }
107
108 #[test]
109 fn test_error_display() {
110 let err = Error::AliasNotFound("myalias".into());
111 assert_eq!(err.to_string(), "Alias not found: myalias");
112
113 let err = Error::InvalidPath("/bad/path".into());
114 assert_eq!(err.to_string(), "Invalid path: /bad/path");
115 }
116}