use reqwest::StatusCode;
use std::io;
#[derive(Debug, thiserror::Error)]
pub enum FetchError {
#[error("network error: {0}")]
Reqwest(#[from] reqwest::Error),
#[error("db error: {0}")]
Sqlx(#[from] sqlx::Error),
#[error("parser error: {0}")]
Parser(String),
}
#[derive(Debug, thiserror::Error)]
pub enum AuthError {
#[error("network error: {0}")]
Network(#[from] reqwest::Error),
#[error("io error: {0}")]
Io(#[from] io::Error),
#[error("json error: {0}")]
Json(#[from] serde_json::Error),
#[error("other error: {0}")]
Other(String),
#[error("bad credentials")]
BadCredentials,
#[error("unexpected http status: {0}")]
Unexpected(StatusCode),
#[error("rate limit exceeded")]
RateLimitExceeded,
}
impl From<Box<dyn std::error::Error + Send + Sync>> for AuthError {
#[cold]
fn from(e: Box<dyn std::error::Error + Send + Sync>) -> Self {
match e.downcast::<reqwest::Error>() {
Ok(req) => AuthError::Network(*req),
Err(e) => match e.downcast::<serde_json::Error>() {
Ok(js) => AuthError::Json(*js),
Err(e) => match e.downcast::<std::io::Error>() {
Ok(ioe) => AuthError::Io(*ioe),
Err(other) => AuthError::Other(other.to_string()),
},
},
}
}
}
impl From<Box<dyn std::error::Error>> for AuthError {
#[cold]
fn from(e: Box<dyn std::error::Error>) -> Self {
match e.downcast::<reqwest::Error>() {
Ok(req) => AuthError::Network(*req),
Err(e) => match e.downcast::<serde_json::Error>() {
Ok(js) => AuthError::Json(*js),
Err(e) => match e.downcast::<io::Error>() {
Ok(ioe) => AuthError::Io(*ioe),
Err(other) => AuthError::Other(other.to_string()),
},
},
}
}
}
impl From<AppError> for AuthError {
#[cold]
fn from(e: AppError) -> Self {
match e {
AppError::Network(e) => AuthError::Network(e),
AppError::Io(e) => AuthError::Io(e),
AppError::Json(e) => AuthError::Json(e),
AppError::Unexpected(s) => AuthError::Unexpected(s),
_ => AuthError::Other(e.to_string()),
}
}
}
#[derive(Debug, thiserror::Error)]
pub enum AppError {
#[error("network error: {0}")]
Network(#[from] reqwest::Error),
#[error("io error: {0}")]
Io(#[from] io::Error),
#[error("json error: {0}")]
Json(#[from] serde_json::Error),
#[error("unexpected http status: {0}")]
Unexpected(StatusCode),
#[error("db error: {0}")]
Db(#[from] sqlx::Error),
#[error("unauthorized")]
Unauthorized,
#[error("oauth token expired")]
OAuthTokenExpired,
#[error("not found")]
NotFound,
#[error("rate limit exceeded")]
RateLimitExceeded,
#[error("historical data allowance exceeded, resets in {allowance_expiry} seconds")]
HistoricalDataAllowanceExceeded {
allowance_expiry: u64,
},
#[error("serialization error: {0}")]
SerializationError(String),
#[error("websocket error: {0}")]
WebSocketError(String),
#[error("deserialization error: {0}")]
Deserialization(String),
#[error("invalid input: {0}")]
InvalidInput(String),
#[error("generic error: {0}")]
Generic(String),
}
impl From<AuthError> for AppError {
#[cold]
fn from(e: AuthError) -> Self {
match e {
AuthError::Network(e) => AppError::Network(e),
AuthError::Io(e) => AppError::Io(e),
AuthError::Json(e) => AppError::Json(e),
AuthError::BadCredentials => AppError::Unauthorized,
AuthError::Unexpected(s) => AppError::Unexpected(s),
_ => AppError::Unexpected(StatusCode::INTERNAL_SERVER_ERROR),
}
}
}
impl From<Box<dyn std::error::Error>> for AppError {
#[cold]
fn from(e: Box<dyn std::error::Error>) -> Self {
match e.downcast::<reqwest::Error>() {
Ok(req) => AppError::Network(*req),
Err(e) => match e.downcast::<serde_json::Error>() {
Ok(js) => AppError::Json(*js),
Err(e) => match e.downcast::<std::io::Error>() {
Ok(ioe) => AppError::Io(*ioe),
Err(_) => AppError::Unexpected(StatusCode::INTERNAL_SERVER_ERROR),
},
},
}
}
}
impl From<String> for AppError {
#[cold]
fn from(e: String) -> Self {
AppError::Generic(e)
}
}
impl From<lightstreamer_rs::utils::LightstreamerError> for AppError {
#[cold]
fn from(e: lightstreamer_rs::utils::LightstreamerError) -> Self {
AppError::WebSocketError(e.to_string())
}
}