use std::fmt;
#[derive(Debug)]
pub enum Error {
Database(sqlx::Error),
Config(String),
Io(std::io::Error),
Json(serde_json::Error),
Other(String),
ParseError(String), InvalidRequest(String), MethodNotFound(String), InvalidParams(String), InternalError(String), Timeout(String), ValidationError(String), NotFound(String), Conflict(String), Unauthorized(String), RateLimited(String), }
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Error::Database(e) => write!(f, "Database error: {}", e),
Error::Config(e) => write!(f, "Configuration error: {}", e),
Error::Io(e) => write!(f, "IO error: {}", e),
Error::Json(e) => write!(f, "JSON error: {}", e),
Error::Other(e) => write!(f, "Error: {}", e),
Error::ParseError(e) => write!(f, "Parse error: {}", e),
Error::InvalidRequest(e) => write!(f, "Invalid request: {}", e),
Error::MethodNotFound(e) => write!(f, "Method not found: {}", e),
Error::InvalidParams(e) => write!(f, "Invalid params: {}", e),
Error::InternalError(e) => write!(f, "Internal error: {}", e),
Error::Timeout(e) => write!(f, "Timeout: {}", e),
Error::ValidationError(e) => write!(f, "Validation error: {}", e),
Error::NotFound(e) => write!(f, "Not found: {}", e),
Error::Conflict(e) => write!(f, "Conflict: {}", e),
Error::Unauthorized(e) => write!(f, "Unauthorized: {}", e),
Error::RateLimited(e) => write!(f, "Rate limited: {}", e),
}
}
}
impl std::error::Error for Error {}
impl From<sqlx::Error> for Error {
fn from(e: sqlx::Error) -> Self {
Error::Database(e)
}
}
impl From<std::io::Error> for Error {
fn from(e: std::io::Error) -> Self {
Error::Io(e)
}
}
impl From<serde_json::Error> for Error {
fn from(e: serde_json::Error) -> Self {
Error::Json(e)
}
}
impl From<anyhow::Error> for Error {
fn from(e: anyhow::Error) -> Self {
Error::Other(e.to_string())
}
}
impl From<url::ParseError> for Error {
fn from(e: url::ParseError) -> Self {
Error::Config(format!("Invalid URL: {}", e))
}
}
impl From<uuid::Error> for Error {
fn from(e: uuid::Error) -> Self {
Error::InvalidParams(format!("Invalid UUID: {}", e))
}
}
impl From<regex::Error> for Error {
fn from(e: regex::Error) -> Self {
Error::InternalError(format!("Regex error: {}", e))
}
}
impl From<tokio::time::error::Elapsed> for Error {
fn from(_: tokio::time::error::Elapsed) -> Self {
Error::Timeout("Operation timed out".to_string())
}
}
impl Error {
pub fn json_rpc_code(&self) -> i32 {
match self {
Error::ParseError(_) => -32700, Error::InvalidRequest(_) => -32600, Error::MethodNotFound(_) => -32601, Error::InvalidParams(_) | Error::ValidationError(_) => -32602, Error::InternalError(_) | Error::Timeout(_) => -32603, Error::Database(_) => -32603, Error::Config(_) => -32603, Error::Io(_) => -32603, Error::Json(_) => -32700, Error::Other(_) => -32603, Error::NotFound(_) => -32001, Error::Conflict(_) => -32002, Error::Unauthorized(_) => -32003, Error::RateLimited(_) => -32004, }
}
pub fn to_json_rpc_error(&self, id: Option<serde_json::Value>) -> serde_json::Value {
serde_json::json!({
"jsonrpc": "2.0",
"id": id,
"error": {
"code": self.json_rpc_code(),
"message": self.to_string()
}
})
}
}
pub type Result<T> = std::result::Result<T, Error>;