use std::{error, fmt};
use serde::{Deserialize, Serialize};
use crate::Response;
#[derive(Debug)]
#[non_exhaustive]
pub enum Error {
Transport(Box<dyn error::Error + Send + Sync>),
Json(serde_json::Error),
Rpc(RpcError),
NonceMismatch,
VersionMismatch,
EmptyBatch,
WrongBatchResponseSize,
BatchDuplicateResponseId(serde_json::Value),
WrongBatchResponseId(serde_json::Value),
}
impl From<serde_json::Error> for Error {
fn from(e: serde_json::Error) -> Error {
Error::Json(e)
}
}
impl From<RpcError> for Error {
fn from(e: RpcError) -> Error {
Error::Rpc(e)
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use Error::*;
match *self {
Transport(ref e) => write!(f, "transport error: {}", e),
Json(ref e) => write!(f, "JSON decode error: {}", e),
Rpc(ref r) => write!(f, "RPC error response: {:?}", r),
BatchDuplicateResponseId(ref v) => write!(f, "duplicate RPC batch response ID: {}", v),
WrongBatchResponseId(ref v) => write!(f, "wrong RPC batch response ID: {}", v),
NonceMismatch => write!(f, "nonce of response did not match nonce of request"),
VersionMismatch => write!(f, "`jsonrpc` field set to non-\"2.0\""),
EmptyBatch => write!(f, "batches can't be empty"),
WrongBatchResponseSize => write!(f, "too many responses returned in batch"),
}
}
}
impl error::Error for Error {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
use self::Error::*;
match *self {
Rpc(_)
| NonceMismatch
| VersionMismatch
| EmptyBatch
| WrongBatchResponseSize
| BatchDuplicateResponseId(_)
| WrongBatchResponseId(_) => None,
Transport(ref e) => Some(&**e),
Json(ref e) => Some(e),
}
}
}
#[derive(Debug)]
pub enum StandardError {
ParseError,
InvalidRequest,
MethodNotFound,
InvalidParams,
InternalError,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct RpcError {
pub code: i32,
pub message: String,
pub data: Option<Box<serde_json::value::RawValue>>,
}
pub fn standard_error(
code: StandardError,
data: Option<Box<serde_json::value::RawValue>>,
) -> RpcError {
match code {
StandardError::ParseError => RpcError {
code: -32700,
message: "Parse error".to_string(),
data,
},
StandardError::InvalidRequest => RpcError {
code: -32600,
message: "Invalid Request".to_string(),
data,
},
StandardError::MethodNotFound => RpcError {
code: -32601,
message: "Method not found".to_string(),
data,
},
StandardError::InvalidParams => RpcError {
code: -32602,
message: "Invalid params".to_string(),
data,
},
StandardError::InternalError => RpcError {
code: -32603,
message: "Internal error".to_string(),
data,
},
}
}
pub fn result_to_response(
result: Result<serde_json::Value, RpcError>,
id: serde_json::Value,
) -> Response {
match result {
Ok(data) => Response {
result: Some(
serde_json::value::RawValue::from_string(serde_json::to_string(&data).unwrap())
.unwrap(),
),
error: None,
id,
jsonrpc: Some(String::from("2.0")),
},
Err(err) => Response {
result: None,
error: Some(err),
id,
jsonrpc: Some(String::from("2.0")),
},
}
}
#[cfg(test)]
mod tests {
use super::StandardError::{
InternalError, InvalidParams, InvalidRequest, MethodNotFound, ParseError,
};
use super::{result_to_response, standard_error};
use serde_json;
#[test]
fn test_parse_error() {
let resp = result_to_response(Err(standard_error(ParseError, None)), From::from(1));
assert!(resp.result.is_none());
assert!(resp.error.is_some());
assert_eq!(resp.id, serde_json::Value::from(1));
assert_eq!(resp.error.unwrap().code, -32700);
}
#[test]
fn test_invalid_request() {
let resp = result_to_response(Err(standard_error(InvalidRequest, None)), From::from(1));
assert!(resp.result.is_none());
assert!(resp.error.is_some());
assert_eq!(resp.id, serde_json::Value::from(1));
assert_eq!(resp.error.unwrap().code, -32600);
}
#[test]
fn test_method_not_found() {
let resp = result_to_response(Err(standard_error(MethodNotFound, None)), From::from(1));
assert!(resp.result.is_none());
assert!(resp.error.is_some());
assert_eq!(resp.id, serde_json::Value::from(1));
assert_eq!(resp.error.unwrap().code, -32601);
}
#[test]
fn test_invalid_params() {
let resp = result_to_response(Err(standard_error(InvalidParams, None)), From::from("123"));
assert!(resp.result.is_none());
assert!(resp.error.is_some());
assert_eq!(resp.id, serde_json::Value::from("123"));
assert_eq!(resp.error.unwrap().code, -32602);
}
#[test]
fn test_internal_error() {
let resp = result_to_response(Err(standard_error(InternalError, None)), From::from(-1));
assert!(resp.result.is_none());
assert!(resp.error.is_some());
assert_eq!(resp.id, serde_json::Value::from(-1));
assert_eq!(resp.error.unwrap().code, -32603);
}
}