1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
use std::result::Result as StdResult; #[derive(Debug, Deserialize, PartialEq)] pub struct RpcError { pub code: i32, pub message: String, } #[derive(Debug, Deserialize, PartialEq)] pub struct RpcResponse<R> { pub id: String, pub result: Option<R>, pub error: Option<RpcError>, } impl<R> Into<StdResult<R, RpcError>> for RpcResponse<R> { fn into(self) -> Result<R, RpcError> { match self { RpcResponse { result: Some(result), error: None, .. } => Ok(result), RpcResponse { result: None, error: Some(rpc_error), .. } => Err(rpc_error), _ => panic!("Response must contain either result or error."), } } } impl<R> RpcResponse<R> { pub fn into_result(self) -> StdResult<R, RpcError> { self.into() } pub fn id(&self) -> &str { &self.id } } #[cfg(test)] mod tests { use super::*; use serde_json::from_str; #[test] fn can_deserialize_successful_response_into_generic_type() { let result = r#"{ "jsonrpc": "1.0", "id": "test", "result": 519521, "error": null }"#; let deserialized_response: RpcResponse<i32> = from_str(result).unwrap(); assert_eq!(deserialized_response.into_result(), Ok(519521)); } #[test] fn can_deserialize_successful_btc_rsponse() { let result = r#"{ "id": "curltest", "result": 1, "error": null }"#; let result: RpcResponse<i32> = from_str(result).unwrap(); assert_eq!(result.into_result(), Ok(1)) } #[test] fn can_deserialize_error_response() { let result = r#"{ "id": "test", "jsonrpc": "1.0", "result": null, "error": { "code": -123, "message": "Something went wrong" } }"#; let deserialized_response: RpcResponse<i32> = from_str(result).unwrap(); assert_eq!( deserialized_response.into_result(), Err(RpcError { code: -123, message: "Something went wrong".to_string(), }) ) } }