Skip to main content

rullst_connect/
error.rs

1use thiserror::Error;
2
3/// Official errors of the Rullst Connect library
4#[derive(Error, Debug)]
5pub enum ConnectError {
6    #[error("HTTP request failed: {0}")]
7    Reqwest(String),
8
9    #[error("Failed to parse JSON: {0}")]
10    Json(String),
11
12    #[error("Failed to decode Base64: {0}")]
13    Base64(String),
14
15    #[error("JWT processing failed: {0}")]
16    Jwt(String),
17
18    #[error("System time error: {0}")]
19    Time(String),
20
21    #[error("Missing token or unexpected response: {0}")]
22    Token(String),
23
24    #[error("Provider API Error ({code}): {message}")]
25    ProviderApiError { code: String, message: String },
26
27    #[error("Provider specific error: {0}")]
28    Provider(String),
29
30    #[error("Invalid CSRF state: {0}")]
31    InvalidState(String),
32}
33
34impl From<reqwest::Error> for ConnectError {
35    fn from(err: reqwest::Error) -> Self {
36        ConnectError::Reqwest(err.to_string())
37    }
38}
39
40impl From<serde_json::Error> for ConnectError {
41    fn from(err: serde_json::Error) -> Self {
42        ConnectError::Json(err.to_string())
43    }
44}
45
46impl From<base64::DecodeError> for ConnectError {
47    fn from(err: base64::DecodeError) -> Self {
48        ConnectError::Base64(err.to_string())
49    }
50}
51
52impl From<jsonwebtoken::errors::Error> for ConnectError {
53    fn from(err: jsonwebtoken::errors::Error) -> Self {
54        ConnectError::Jwt(err.to_string())
55    }
56}
57
58impl From<std::time::SystemTimeError> for ConnectError {
59    fn from(err: std::time::SystemTimeError) -> Self {
60        ConnectError::Time(err.to_string())
61    }
62}
63
64#[cfg(test)]
65mod tests {
66    use super::*;
67
68    #[test]
69    fn test_reqwest_error_conversion() {
70        let err = reqwest::Client::new()
71            .get("htt p://invalid")
72            .build()
73            .unwrap_err();
74        let connect_err: ConnectError = err.into();
75        match connect_err {
76            ConnectError::Reqwest(_) => (),
77            _ => panic!("Expected ConnectError::Reqwest"),
78        }
79    }
80
81    #[test]
82    fn test_serde_json_error_conversion() {
83        let err: serde_json::Error =
84            serde_json::from_str::<serde_json::Value>("invalid json").unwrap_err();
85        let connect_err: ConnectError = err.into();
86        match connect_err {
87            ConnectError::Json(_) => (),
88            _ => panic!("Expected ConnectError::Json"),
89        }
90    }
91
92    #[test]
93    fn test_base64_error_conversion() {
94        use base64::Engine;
95        let err = base64::engine::general_purpose::STANDARD
96            .decode("invalid!base64")
97            .unwrap_err();
98        let connect_err: ConnectError = err.into();
99        match connect_err {
100            ConnectError::Base64(_) => (),
101            _ => panic!("Expected ConnectError::Base64"),
102        }
103    }
104
105    #[test]
106    fn test_jwt_error_conversion() {
107        let err = jsonwebtoken::decode_header("invalid.jwt.header").unwrap_err();
108        let connect_err: ConnectError = err.into();
109        match connect_err {
110            ConnectError::Jwt(_) => (),
111            _ => panic!("Expected ConnectError::Jwt"),
112        }
113    }
114
115    #[test]
116    fn test_time_error_conversion() {
117        let err = std::time::SystemTime::UNIX_EPOCH
118            .duration_since(std::time::SystemTime::now())
119            .unwrap_err();
120        let connect_err: ConnectError = err.into();
121        match connect_err {
122            ConnectError::Time(_) => (),
123            _ => panic!("Expected ConnectError::Time"),
124        }
125    }
126}