1use std::fmt;
2
3#[derive(Debug, thiserror::Error)]
4pub enum HtbError {
5 #[error("Not authenticated. Run `htb auth login` first.")]
6 NotAuthenticated,
7
8 #[error("API error ({status}): {message}")]
9 Api { status: u16, message: String },
10
11 #[error("Rate limited. Try again shortly.")]
12 RateLimited,
13
14 #[error("{0}")]
15 Http(#[from] reqwest::Error),
16
17 #[error("{0}")]
18 Io(#[from] std::io::Error),
19
20 #[error("{0}")]
21 Json(#[from] serde_json::Error),
22
23 #[error("Config error: {0}")]
24 Config(String),
25}
26
27#[derive(Debug, serde::Deserialize)]
28pub struct ApiErrorBody {
29 pub message: String,
30}
31
32impl fmt::Display for ApiErrorBody {
33 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
34 write!(f, "{}", self.message)
35 }
36}
37
38#[cfg(test)]
39mod tests {
40 use super::*;
41
42 #[test]
43 fn not_authenticated_display() {
44 let err = HtbError::NotAuthenticated;
45 assert_eq!(
46 err.to_string(),
47 "Not authenticated. Run `htb auth login` first."
48 );
49 }
50
51 #[test]
52 fn api_error_display() {
53 let err = HtbError::Api {
54 status: 403,
55 message: "Incorrect flag".into(),
56 };
57 assert_eq!(err.to_string(), "API error (403): Incorrect flag");
58 }
59}