1#[derive(Debug, thiserror::Error)]
5#[non_exhaustive]
6pub enum ApiError {
7 #[error("Unauthorized: invalid or missing API key")]
10 Unauthorized,
11
12 #[error("Rate limited — retry after {retry_after:?} seconds")]
18 RateLimit {
19 retry_after: Option<u64>,
21 },
22
23 #[error("Not found")]
26 NotFound,
27
28 #[error("Server error (HTTP {status})")]
31 ServerError {
32 status: u16,
34 },
35
36 #[error("Network error: {0}")]
38 NetworkError(#[from] reqwest::Error),
39
40 #[error("Failed to parse API response: {0}")]
42 ParseError(String),
43}
44
45#[cfg(test)]
46mod tests {
47 use super::*;
48
49 #[test]
50 fn unauthorized_display() {
51 let err = ApiError::Unauthorized;
52 assert_eq!(err.to_string(), "Unauthorized: invalid or missing API key");
53 }
54
55 #[test]
56 fn rate_limit_with_retry_after() {
57 let err = ApiError::RateLimit {
58 retry_after: Some(60),
59 };
60 assert!(err.to_string().contains("60"));
61 }
62
63 #[test]
64 fn rate_limit_without_retry_after() {
65 let err = ApiError::RateLimit { retry_after: None };
66 assert!(err.to_string().contains("None"));
67 }
68
69 #[test]
70 fn not_found_display() {
71 let err = ApiError::NotFound;
72 assert_eq!(err.to_string(), "Not found");
73 }
74
75 #[test]
76 fn server_error_display() {
77 let err = ApiError::ServerError { status: 503 };
78 assert!(err.to_string().contains("503"));
79 }
80
81 #[test]
82 fn parse_error_display() {
83 let err = ApiError::ParseError("missing field `id`".to_owned());
84 assert!(err.to_string().contains("missing field `id`"));
85 }
86}