use std::{error, fmt};
use serde_json;
use Response;
#[derive(Debug)]
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 {
match *self {
Error::Transport(ref e) => write!(f, "transport error: {}", e),
Error::Json(ref e) => write!(f, "JSON decode error: {}", e),
Error::Rpc(ref r) => write!(f, "RPC error response: {:?}", r),
Error::BatchDuplicateResponseId(ref v) => {
write!(f, "duplicate RPC batch response ID: {}", v)
}
Error::WrongBatchResponseId(ref v) => write!(f, "wrong RPC batch response ID: {}", v),
Error::NonceMismatch => write!(f, "Nonce of response did not match nonce of request"),
Error::VersionMismatch => write!(f, "`jsonrpc` field set to non-\"2.0\""),
Error::EmptyBatch => write!(f, "batches can't be empty"),
Error::WrongBatchResponseSize => write!(f, "too many responses returned in batch"),
}
}
}
impl error::Error for Error {
fn cause(&self) -> Option<&error::Error> {
match *self {
Error::Transport(ref e) => Some(&**e),
Error::Json(ref e) => Some(e),
_ => None,
}
}
}
#[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: data,
},
StandardError::InvalidRequest => RpcError {
code: -32600,
message: "Invalid Request".to_string(),
data: data,
},
StandardError::MethodNotFound => RpcError {
code: -32601,
message: "Method not found".to_string(),
data: data,
},
StandardError::InvalidParams => RpcError {
code: -32602,
message: "Invalid params".to_string(),
data: data,
},
StandardError::InternalError => RpcError {
code: -32603,
message: "Internal error".to_string(),
data: 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: id,
jsonrpc: Some(String::from("2.0")),
},
Err(err) => Response {
result: None,
error: Some(err),
id: 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);
}
}