diff --git a/core-client/transports/src/transports/mod.rs b/core-client/transports/src/transports/mod.rs index 00b6f0600..dcbfdeb3b 100644 --- a/core-client/transports/src/transports/mod.rs +++ b/core-client/transports/src/transports/mod.rs @@ -98,16 +98,19 @@ pub fn parse_response( #[serde(deny_unknown_fields)] #[serde(untagged)] pub enum ClientResponse { - /// A regular JSON-RPC request output (single response). + /// A regular JSON-RPC 2.0 request output (single response). Output(jsonrpc_core::Output), /// A notification. Notification(jsonrpc_core::Notification), + /// A regular JSON-RPC 1.0 request output (single response). + OutputVersionOne(jsonrpc_core::OutputVersionOne), } impl ClientResponse { /// Get the id of the response (if any). pub fn id(&self) -> Option { match *self { + ClientResponse::OutputVersionOne(ref output) => Some(output.id().clone()), ClientResponse::Output(ref output) => Some(output.id().clone()), ClientResponse::Notification(_) => None, } @@ -117,7 +120,7 @@ impl ClientResponse { pub fn method(&self) -> Option { match *self { ClientResponse::Notification(ref n) => Some(n.method.to_owned()), - ClientResponse::Output(_) => None, + ClientResponse::Output(_) | ClientResponse::OutputVersionOne(_) => None, } } @@ -140,6 +143,7 @@ impl From for Result { fn from(res: ClientResponse) -> Self { match res { ClientResponse::Output(output) => output.into(), + ClientResponse::OutputVersionOne(output) => output.into(), ClientResponse::Notification(n) => match &n.params { Params::Map(map) => { let subscription = map.get("subscription"); diff --git a/core/src/types/mod.rs b/core/src/types/mod.rs index cb4a28e95..c61fd383d 100644 --- a/core/src/types/mod.rs +++ b/core/src/types/mod.rs @@ -15,5 +15,5 @@ pub use self::error::{Error, ErrorCode}; pub use self::id::Id; pub use self::params::Params; pub use self::request::{Call, MethodCall, Notification, Request}; -pub use self::response::{Failure, Output, Response, Success}; +pub use self::response::{Failure, Output, OutputVersionOne, Response, Success}; pub use self::version::Version; diff --git a/core/src/types/response.rs b/core/src/types/response.rs index f7d54b07b..1ee88a22c 100644 --- a/core/src/types/response.rs +++ b/core/src/types/response.rs @@ -84,6 +84,57 @@ impl From for CoreResult { } } +/// Represents JSON-RPC v1.x output - failure or success +#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct OutputVersionOne { + /// Result + pub result: Option, + /// Error + pub error: Option, + /// Correlation id + pub id: Id, +} + +impl OutputVersionOne { + /// Creates new output given `Result`, `Id` and `Version`. + pub fn from(result: CoreResult, id: Id) -> Self { + match result { + Ok(result) => OutputVersionOne { + id, + result: Some(result), + error: None, + }, + Err(error) => OutputVersionOne { + id, + error: Some(error), + result: None, + }, + } + } + + /// Creates new failure output indicating malformed request. + pub fn invalid_request(id: Id) -> Self { + OutputVersionOne { + id, + error: Some(Error::new(ErrorCode::InvalidRequest)), + result: None, + } + } + + /// Get the correlation id. + pub fn id(&self) -> &Id { + &self.id + } +} + +impl From for CoreResult { + /// Convert into a result. Will be `Ok` if `result` is `Some` and `Err` if `result` is `None`. + fn from(output: OutputVersionOne) -> CoreResult { + output.result.ok_or(output.error.unwrap_or(Error::parse_error())) + } +} + /// Synchronous response #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] #[serde(deny_unknown_fields)] @@ -145,6 +196,20 @@ fn success_output_serialize() { assert_eq!(serialized, r#"{"jsonrpc":"2.0","result":1,"id":1}"#); } +#[test] +fn success_output_serialize_1point0() { + use serde_json::Value; + + let so = OutputVersionOne { + result: Some(Value::from(1)), + error: None, + id: Id::Num(1), + }; + + let serialized = serde_json::to_string(&so).unwrap(); + assert_eq!(serialized, r#"{"result":1,"error":null,"id":1}"#); +} + #[test] fn success_output_deserialize() { use serde_json; @@ -232,6 +297,24 @@ fn single_response_deserialize() { ); } +#[test] +fn single_response_deserialize_1point0() { + use serde_json; + use serde_json::Value; + + let dsr = r#"{"result":1,"error":null,"id":1}"#; + + let deserialized: OutputVersionOne = serde_json::from_str(dsr).unwrap(); + assert_eq!( + deserialized, + OutputVersionOne { + result: Some(Value::from(1)), + error: None, + id: Id::Num(1) + } + ); +} + #[test] fn batch_response_deserialize() { use serde_json;