1pub type Result<T> = std::result::Result<T, Error>;
5
6#[derive(Debug, thiserror::Error)]
8pub enum Error {
9 #[error("Validation error: {message}")]
10 Validation { message: String },
11
12 #[error("Routing error: {message}")]
13 Routing { message: String },
14
15 #[error("Proxy error: {message}")]
16 Proxy { message: String },
17
18 #[error("Latency simulation error: {message}")]
19 Latency { message: String },
20
21 #[error("Configuration error: {message}")]
22 Config { message: String },
23
24 #[error("Protocol not found: {message}")]
25 ProtocolNotFound { message: String },
26
27 #[error("Protocol disabled: {message}")]
28 ProtocolDisabled { message: String },
29
30 #[error("Protocol handler in use: {message}")]
31 ProtocolHandlerInUse { message: String },
32
33 #[error("Protocol validation error: {message}")]
34 ProtocolValidationError { protocol: String, message: String },
35
36 #[error("IO error: {0}")]
37 Io(#[from] std::io::Error),
38
39 #[error("JSON error: {0}")]
40 Json(#[from] serde_json::Error),
41
42 #[error("YAML error: {0}")]
43 Yaml(#[from] serde_yaml::Error),
44
45 #[error("HTTP error: {0}")]
46 Http(#[from] reqwest::Error),
47
48 #[error("URL parse error: {0}")]
49 UrlParse(#[from] url::ParseError),
50
51 #[error("Regex error: {0}")]
52 Regex(#[from] regex::Error),
53
54 #[error("Generic error: {0}")]
55 Generic(String),
56
57 #[error("Encryption error: {0}")]
58 Encryption(#[from] crate::encryption::EncryptionError),
59
60 #[error("JavaScript error: {0}")]
61 JavaScript(#[from] rquickjs::Error),
62}
63
64impl From<String> for Error {
65 fn from(message: String) -> Self {
66 Self::Generic(message)
67 }
68}
69
70impl Error {
71 pub fn validation<S: Into<String>>(message: S) -> Self {
73 Self::Validation {
74 message: message.into(),
75 }
76 }
77
78 pub fn routing<S: Into<String>>(message: S) -> Self {
80 Self::Routing {
81 message: message.into(),
82 }
83 }
84
85 pub fn proxy<S: Into<String>>(message: S) -> Self {
87 Self::Proxy {
88 message: message.into(),
89 }
90 }
91
92 pub fn latency<S: Into<String>>(message: S) -> Self {
94 Self::Latency {
95 message: message.into(),
96 }
97 }
98
99 pub fn config<S: Into<String>>(message: S) -> Self {
101 Self::Config {
102 message: message.into(),
103 }
104 }
105
106 pub fn protocol_not_found<S: Into<String>>(message: S) -> Self {
108 Self::ProtocolNotFound {
109 message: message.into(),
110 }
111 }
112
113 pub fn protocol_disabled<S: Into<String>>(message: S) -> Self {
115 Self::ProtocolDisabled {
116 message: message.into(),
117 }
118 }
119
120 pub fn protocol_handler_in_use<S: Into<String>>(message: S) -> Self {
122 Self::ProtocolHandlerInUse {
123 message: message.into(),
124 }
125 }
126
127 pub fn protocol_validation_error<S: Into<String>>(protocol: S, message: S) -> Self {
129 Self::ProtocolValidationError {
130 protocol: protocol.into(),
131 message: message.into(),
132 }
133 }
134
135 pub fn generic<S: Into<String>>(message: S) -> Self {
137 Self::Generic(message.into())
138 }
139}
140
141#[cfg(test)]
142mod tests {
143 use super::*;
144
145 #[test]
146 fn test_validation_error() {
147 let err = Error::validation("test validation");
148 assert!(err.to_string().contains("Validation error"));
149 assert!(err.to_string().contains("test validation"));
150 }
151
152 #[test]
153 fn test_routing_error() {
154 let err = Error::routing("test routing");
155 assert!(err.to_string().contains("Routing error"));
156 assert!(err.to_string().contains("test routing"));
157 }
158
159 #[test]
160 fn test_proxy_error() {
161 let err = Error::proxy("test proxy");
162 assert!(err.to_string().contains("Proxy error"));
163 assert!(err.to_string().contains("test proxy"));
164 }
165
166 #[test]
167 fn test_latency_error() {
168 let err = Error::latency("test latency");
169 assert!(err.to_string().contains("Latency simulation error"));
170 assert!(err.to_string().contains("test latency"));
171 }
172
173 #[test]
174 fn test_config_error() {
175 let err = Error::config("test config");
176 assert!(err.to_string().contains("Configuration error"));
177 assert!(err.to_string().contains("test config"));
178 }
179
180 #[test]
181 fn test_generic_error() {
182 let err = Error::generic("test generic");
183 assert!(err.to_string().contains("Generic error"));
184 assert!(err.to_string().contains("test generic"));
185 }
186
187 #[test]
188 fn test_from_string() {
189 let err: Error = "test message".to_string().into();
190 assert!(matches!(err, Error::Generic(_)));
191 assert!(err.to_string().contains("test message"));
192 }
193
194 #[test]
195 fn test_json_error_conversion() {
196 let json_err = serde_json::from_str::<serde_json::Value>("invalid json");
197 assert!(json_err.is_err());
198 let err: Error = json_err.unwrap_err().into();
199 assert!(matches!(err, Error::Json(_)));
200 }
201
202 #[test]
203 fn test_url_parse_error_conversion() {
204 let url_err = url::Url::parse("not a url");
205 assert!(url_err.is_err());
206 let err: Error = url_err.unwrap_err().into();
207 assert!(matches!(err, Error::UrlParse(_)));
208 }
209
210 #[test]
211 #[allow(clippy::invalid_regex)]
212 fn test_regex_error_conversion() {
213 let regex_err = regex::Regex::new("[invalid(");
214 assert!(regex_err.is_err());
215 let err: Error = regex_err.unwrap_err().into();
216 assert!(matches!(err, Error::Regex(_)));
217 }
218
219 #[test]
220 fn test_error_display() {
221 let errors = vec![
222 (Error::validation("msg"), "Validation error: msg"),
223 (Error::routing("msg"), "Routing error: msg"),
224 (Error::proxy("msg"), "Proxy error: msg"),
225 (Error::latency("msg"), "Latency simulation error: msg"),
226 (Error::config("msg"), "Configuration error: msg"),
227 (Error::generic("msg"), "Generic error: msg"),
228 ];
229
230 for (err, expected) in errors {
231 assert_eq!(err.to_string(), expected);
232 }
233 }
234}