ig_client/
error.rs

1/******************************************************************************
2   Author: Joaquín Béjar García
3   Email: jb@taunais.com
4   Date: 12/5/25
5******************************************************************************/
6use reqwest::StatusCode;
7use std::fmt::{Display, Formatter};
8use std::{fmt, io};
9
10/// Error type for fetch operations
11#[derive(Debug)]
12pub enum FetchError {
13    /// Network error from reqwest
14    Reqwest(reqwest::Error),
15    /// Database error from sqlx
16    Sqlx(sqlx::Error),
17    /// Error during parsing
18    Parser(String),
19}
20
21impl Display for FetchError {
22    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
23        match self {
24            FetchError::Reqwest(e) => write!(f, "network error: {e}"),
25            FetchError::Sqlx(e) => write!(f, "db error: {e}"),
26            FetchError::Parser(msg) => write!(f, "parser error: {msg}"),
27        }
28    }
29}
30
31impl std::error::Error for FetchError {}
32
33impl From<reqwest::Error> for FetchError {
34    fn from(err: reqwest::Error) -> Self {
35        FetchError::Reqwest(err)
36    }
37}
38
39impl From<sqlx::Error> for FetchError {
40    fn from(err: sqlx::Error) -> Self {
41        FetchError::Sqlx(err)
42    }
43}
44
45/// Error type for authentication operations
46#[derive(Debug)]
47pub enum AuthError {
48    /// Network error from reqwest
49    Network(reqwest::Error),
50    /// I/O error
51    Io(io::Error),
52    /// JSON serialization or deserialization error
53    Json(serde_json::Error),
54    /// Other unspecified error
55    Other(String),
56    /// Invalid credentials error
57    BadCredentials,
58    /// Unexpected HTTP status code
59    Unexpected(StatusCode),
60}
61
62impl Display for AuthError {
63    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
64        match self {
65            AuthError::Network(e) => write!(f, "network error: {e}"),
66            AuthError::Io(e) => write!(f, "io error: {e}"),
67            AuthError::Json(e) => write!(f, "json error: {e}"),
68            AuthError::Other(msg) => write!(f, "other error: {msg}"),
69            AuthError::BadCredentials => write!(f, "bad credentials"),
70            AuthError::Unexpected(s) => write!(f, "unexpected http status: {s}"),
71        }
72    }
73}
74
75impl std::error::Error for AuthError {}
76
77impl From<reqwest::Error> for AuthError {
78    fn from(e: reqwest::Error) -> Self {
79        AuthError::Network(e)
80    }
81}
82impl From<Box<dyn std::error::Error + Send + Sync>> for AuthError {
83    fn from(e: Box<dyn std::error::Error + Send + Sync>) -> Self {
84        match e.downcast::<reqwest::Error>() {
85            Ok(req) => AuthError::Network(*req),
86            Err(e) => match e.downcast::<serde_json::Error>() {
87                Ok(js) => AuthError::Json(*js),
88                Err(e) => match e.downcast::<std::io::Error>() {
89                    Ok(ioe) => AuthError::Io(*ioe),
90                    Err(other) => AuthError::Other(other.to_string()),
91                },
92            },
93        }
94    }
95}
96impl From<AppError> for AuthError {
97    fn from(e: AppError) -> Self {
98        match e {
99            AppError::Network(e) => AuthError::Network(e),
100            AppError::Io(e) => AuthError::Io(e),
101            AppError::Json(e) => AuthError::Json(e),
102            AppError::Unexpected(s) => AuthError::Unexpected(s),
103            _ => AuthError::Other("unknown error".to_string()),
104        }
105    }
106}
107
108/// General application error type
109#[derive(Debug)]
110pub enum AppError {
111    /// Network error from reqwest
112    Network(reqwest::Error),
113    /// I/O error
114    Io(io::Error),
115    /// JSON serialization or deserialization error
116    Json(serde_json::Error),
117    /// Unexpected HTTP status code
118    Unexpected(StatusCode),
119    /// Database error from sqlx
120    Db(sqlx::Error),
121    /// Unauthorized access error
122    Unauthorized,
123    /// Resource not found error
124    NotFound,
125    /// API rate limit exceeded
126    RateLimitExceeded,
127    /// Error during serialization or deserialization
128    SerializationError(String),
129    /// WebSocket communication error
130    WebSocketError(String),
131    /// Deserialization error with details
132    Deserialization(String),
133}
134
135impl Display for AppError {
136    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
137        match self {
138            AppError::Network(e) => write!(f, "network error: {e}"),
139            AppError::Io(e) => write!(f, "io error: {e}"),
140            AppError::Json(e) => write!(f, "json error: {e}"),
141            AppError::Unexpected(s) => write!(f, "unexpected http status: {s}"),
142            AppError::Db(e) => write!(f, "db error: {e}"),
143            AppError::Unauthorized => write!(f, "unauthorized"),
144            AppError::NotFound => write!(f, "not found"),
145            AppError::RateLimitExceeded => write!(f, "rate limit exceeded"),
146            AppError::SerializationError(s) => write!(f, "serialization error: {s}"),
147            AppError::WebSocketError(s) => write!(f, "websocket error: {s}"),
148            AppError::Deserialization(s) => write!(f, "deserialization error: {s}"),
149        }
150    }
151}
152
153impl std::error::Error for AppError {}
154
155impl From<reqwest::Error> for AppError {
156    fn from(e: reqwest::Error) -> Self {
157        AppError::Network(e)
158    }
159}
160impl From<io::Error> for AppError {
161    fn from(e: io::Error) -> Self {
162        AppError::Io(e)
163    }
164}
165impl From<serde_json::Error> for AppError {
166    fn from(e: serde_json::Error) -> Self {
167        AppError::Json(e)
168    }
169}
170impl From<sqlx::Error> for AppError {
171    fn from(e: sqlx::Error) -> Self {
172        AppError::Db(e)
173    }
174}
175impl From<AuthError> for AppError {
176    fn from(e: AuthError) -> Self {
177        match e {
178            AuthError::Network(e) => AppError::Network(e),
179            AuthError::Io(e) => AppError::Io(e),
180            AuthError::Json(e) => AppError::Json(e),
181            AuthError::BadCredentials => AppError::Unauthorized,
182            AuthError::Unexpected(s) => AppError::Unexpected(s),
183            _ => AppError::Unexpected(StatusCode::INTERNAL_SERVER_ERROR),
184        }
185    }
186}
187
188impl From<Box<dyn std::error::Error>> for AppError {
189    fn from(e: Box<dyn std::error::Error>) -> Self {
190        match e.downcast::<reqwest::Error>() {
191            Ok(req) => AppError::Network(*req),
192            Err(e) => match e.downcast::<serde_json::Error>() {
193                Ok(js) => AppError::Json(*js),
194                Err(e) => match e.downcast::<std::io::Error>() {
195                    Ok(ioe) => AppError::Io(*ioe),
196                    Err(_) => AppError::Unexpected(StatusCode::INTERNAL_SERVER_ERROR),
197                },
198            },
199        }
200    }
201}