use super::Value;
use serde::{Deserialize, Serialize};
use thiserror::Error;
pub const INVALID_REQUEST: i32 = -32600;
pub const METHOD_NOT_FOUND: i32 = -32601;
pub const INVALID_PARAMS: i32 = -32602;
pub const INTERNAL_ERROR: i32 = -32603;
pub const PARSE_ERROR: i32 = -32700;
#[derive(Debug, Clone, Copy)]
pub enum JsonRpcErrorReason {
ParseError,
InvalidRequest,
MethodNotFound,
InvalidParams,
InternalError,
ServerError(i32),
ApplicationError(i32),
}
impl std::fmt::Display for JsonRpcErrorReason {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
JsonRpcErrorReason::ParseError => write!(f, "Parse error"),
JsonRpcErrorReason::InvalidRequest => write!(f, "Invalid Request"),
JsonRpcErrorReason::MethodNotFound => write!(f, "Method not found"),
JsonRpcErrorReason::InvalidParams => write!(f, "Invalid params"),
JsonRpcErrorReason::InternalError => write!(f, "Internal error"),
JsonRpcErrorReason::ServerError(code) => write!(f, "Server error: {}", code),
JsonRpcErrorReason::ApplicationError(code) => {
write!(f, "Application error: {}", code)
}
}
}
}
impl From<JsonRpcErrorReason> for i32 {
fn from(reason: JsonRpcErrorReason) -> i32 {
match reason {
JsonRpcErrorReason::ParseError => PARSE_ERROR,
JsonRpcErrorReason::InvalidRequest => INVALID_REQUEST,
JsonRpcErrorReason::MethodNotFound => METHOD_NOT_FOUND,
JsonRpcErrorReason::InvalidParams => INVALID_PARAMS,
JsonRpcErrorReason::InternalError => INTERNAL_ERROR,
JsonRpcErrorReason::ServerError(code) | JsonRpcErrorReason::ApplicationError(code) => {
code
}
}
}
}
impl JsonRpcErrorReason {
fn new(code: i32) -> Self {
match code {
PARSE_ERROR => Self::ParseError,
INVALID_REQUEST => Self::InvalidRequest,
METHOD_NOT_FOUND => Self::MethodNotFound,
INVALID_PARAMS => Self::InvalidParams,
INTERNAL_ERROR => Self::InternalError,
-32099..=-32000 => Self::ServerError(code),
_ => Self::ApplicationError(code),
}
}
}
#[derive(Debug, Error, Clone, Serialize, Deserialize, PartialEq)]
pub struct JsonRpcError {
code: i32,
message: String,
data: Value,
}
impl JsonRpcError {
pub fn new(code: JsonRpcErrorReason, message: String, data: Value) -> Self {
Self {
code: code.into(),
message,
data,
}
}
}
impl std::fmt::Display for JsonRpcError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}: {}",
JsonRpcErrorReason::new(self.code),
self.message
)
}
}
#[cfg(feature = "anyhow_error")]
impl From<anyhow::Error> for JsonRpcError {
fn from(error: anyhow::Error) -> Self {
let message = error.to_string();
let data = Value::default();
Self {
code: 1,
message,
data,
}
}
}
impl JsonRpcError {
pub fn error_reason(&self) -> JsonRpcErrorReason {
JsonRpcErrorReason::new(self.code)
}
pub fn code(&self) -> i32 {
self.code
}
}