jsonrpc_client_transports/transports/
mod.rs1use jsonrpc_core::{Call, Error, Id, MethodCall, Notification, Params, Version};
4use jsonrpc_pubsub::SubscriptionId;
5use serde::{Deserialize, Serialize};
6use serde_json::Value;
7
8use crate::{CallMessage, NotifyMessage, RpcError};
9
10pub mod duplex;
11#[cfg(feature = "http")]
12pub mod http;
13#[cfg(feature = "ipc")]
14pub mod ipc;
15pub mod local;
16#[cfg(feature = "ws")]
17pub mod ws;
18
19pub use duplex::duplex;
20
21pub struct RequestBuilder {
23 id: u64,
24}
25
26impl RequestBuilder {
27 pub fn new() -> Self {
29 RequestBuilder { id: 0 }
30 }
31
32 fn next_id(&mut self) -> Id {
33 let id = self.id;
34 self.id = id + 1;
35 Id::Num(id)
36 }
37
38 fn single_request(&mut self, method: String, params: Params) -> (Id, String) {
40 let id = self.next_id();
41 let request = jsonrpc_core::Request::Single(Call::MethodCall(MethodCall {
42 jsonrpc: Some(Version::V2),
43 method,
44 params,
45 id: id.clone(),
46 }));
47 (
48 id,
49 serde_json::to_string(&request).expect("Request serialization is infallible; qed"),
50 )
51 }
52
53 fn call_request(&mut self, msg: &CallMessage) -> (Id, String) {
54 self.single_request(msg.method.clone(), msg.params.clone())
55 }
56
57 fn subscribe_request(&mut self, subscribe: String, subscribe_params: Params) -> (Id, String) {
58 self.single_request(subscribe, subscribe_params)
59 }
60
61 fn unsubscribe_request(&mut self, unsubscribe: String, sid: SubscriptionId) -> (Id, String) {
62 self.single_request(unsubscribe, Params::Array(vec![Value::from(sid)]))
63 }
64
65 fn notification(&mut self, msg: &NotifyMessage) -> String {
66 let request = jsonrpc_core::Request::Single(Call::Notification(Notification {
67 jsonrpc: Some(Version::V2),
68 method: msg.method.clone(),
69 params: msg.params.clone(),
70 }));
71 serde_json::to_string(&request).expect("Request serialization is infallible; qed")
72 }
73}
74
75pub fn parse_response(
82 response: &str,
83) -> Result<(Id, Result<Value, RpcError>, Option<String>, Option<SubscriptionId>), RpcError> {
84 jsonrpc_core::serde_from_str::<ClientResponse>(response)
85 .map_err(|e| RpcError::ParseError(e.to_string(), Box::new(e)))
86 .map(|response| {
87 let id = response.id().unwrap_or(Id::Null);
88 let sid = response.subscription_id();
89 let method = response.method();
90 let value: Result<Value, Error> = response.into();
91 let result = value.map_err(RpcError::JsonRpcError);
92 (id, result, method, sid)
93 })
94}
95
96#[derive(Debug, PartialEq, Clone, Deserialize, Serialize)]
98#[serde(deny_unknown_fields)]
99#[serde(untagged)]
100pub enum ClientResponse {
101 Output(jsonrpc_core::Output),
103 Notification(jsonrpc_core::Notification),
105}
106
107impl ClientResponse {
108 pub fn id(&self) -> Option<Id> {
110 match *self {
111 ClientResponse::Output(ref output) => Some(output.id().clone()),
112 ClientResponse::Notification(_) => None,
113 }
114 }
115
116 pub fn method(&self) -> Option<String> {
118 match *self {
119 ClientResponse::Notification(ref n) => Some(n.method.to_owned()),
120 ClientResponse::Output(_) => None,
121 }
122 }
123
124 pub fn subscription_id(&self) -> Option<SubscriptionId> {
126 match *self {
127 ClientResponse::Notification(ref n) => match &n.params {
128 jsonrpc_core::Params::Map(map) => match map.get("subscription") {
129 Some(value) => SubscriptionId::parse_value(value),
130 None => None,
131 },
132 _ => None,
133 },
134 _ => None,
135 }
136 }
137}
138
139impl From<ClientResponse> for Result<Value, Error> {
140 fn from(res: ClientResponse) -> Self {
141 match res {
142 ClientResponse::Output(output) => output.into(),
143 ClientResponse::Notification(n) => match &n.params {
144 Params::Map(map) => {
145 let subscription = map.get("subscription");
146 let result = map.get("result");
147 let error = map.get("error");
148
149 match (subscription, result, error) {
150 (Some(_), Some(result), _) => Ok(result.to_owned()),
151 (Some(_), _, Some(error)) => {
152 let error = serde_json::from_value::<Error>(error.to_owned())
153 .ok()
154 .unwrap_or_else(Error::parse_error);
155 Err(error)
156 }
157 _ => Ok(n.params.into()),
158 }
159 }
160 _ => Ok(n.params.into()),
161 },
162 }
163 }
164}
165
166#[cfg(test)]
167mod tests {
168 use super::*;
169 use jsonrpc_core::{Failure, Notification, Output, Params, Success, Value, Version};
170
171 #[test]
172 fn notification_deserialize() {
173 let dsr = r#"{"jsonrpc":"2.0","method":"hello","params":[10]}"#;
174
175 let deserialized: ClientResponse = jsonrpc_core::serde_from_str(dsr).unwrap();
176 assert_eq!(
177 deserialized,
178 ClientResponse::Notification(Notification {
179 jsonrpc: Some(Version::V2),
180 method: "hello".into(),
181 params: Params::Array(vec![Value::from(10)]),
182 })
183 );
184 }
185
186 #[test]
187 fn success_deserialize() {
188 let dsr = r#"{"jsonrpc":"2.0","result":1,"id":1}"#;
189
190 let deserialized: ClientResponse = jsonrpc_core::serde_from_str(dsr).unwrap();
191 assert_eq!(
192 deserialized,
193 ClientResponse::Output(Output::Success(Success {
194 jsonrpc: Some(Version::V2),
195 id: Id::Num(1),
196 result: 1.into(),
197 }))
198 );
199 }
200
201 #[test]
202 fn failure_output_deserialize() {
203 let dfo = r#"{"jsonrpc":"2.0","error":{"code":-32700,"message":"Parse error"},"id":1}"#;
204
205 let deserialized: ClientResponse = jsonrpc_core::serde_from_str(dfo).unwrap();
206 assert_eq!(
207 deserialized,
208 ClientResponse::Output(Output::Failure(Failure {
209 jsonrpc: Some(Version::V2),
210 error: Error::parse_error(),
211 id: Id::Num(1)
212 }))
213 );
214 }
215}