tetsy_jsonrpc_core/types/
request.rs

1//! jsonrpc request
2
3use super::{Id, Params, Version};
4
5/// Represents jsonrpc request which is a method call.
6#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
7#[serde(deny_unknown_fields)]
8pub struct MethodCall {
9	/// A String specifying the version of the JSON-RPC protocol.
10	pub jsonrpc: Option<Version>,
11	/// A String containing the name of the method to be invoked.
12	pub method: String,
13	/// A Structured value that holds the parameter values to be used
14	/// during the invocation of the method. This member MAY be omitted.
15	#[serde(default = "default_params")]
16	pub params: Params,
17	/// An identifier established by the Client that MUST contain a String,
18	/// Number, or NULL value if included. If it is not included it is assumed
19	/// to be a notification.
20	pub id: Id,
21}
22
23/// Represents jsonrpc request which is a notification.
24#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
25#[serde(deny_unknown_fields)]
26pub struct Notification {
27	/// A String specifying the version of the JSON-RPC protocol.
28	pub jsonrpc: Option<Version>,
29	/// A String containing the name of the method to be invoked.
30	pub method: String,
31	/// A Structured value that holds the parameter values to be used
32	/// during the invocation of the method. This member MAY be omitted.
33	#[serde(default = "default_params")]
34	pub params: Params,
35}
36
37/// Represents single jsonrpc call.
38#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
39#[serde(untagged)]
40pub enum Call {
41	/// Call method
42	MethodCall(MethodCall),
43	/// Fire notification
44	Notification(Notification),
45	/// Invalid call
46	Invalid {
47		/// Call id (if known)
48		#[serde(default = "default_id")]
49		id: Id,
50	},
51}
52
53fn default_params() -> Params {
54	Params::None
55}
56
57fn default_id() -> Id {
58	Id::Null
59}
60
61impl From<MethodCall> for Call {
62	fn from(mc: MethodCall) -> Self {
63		Call::MethodCall(mc)
64	}
65}
66
67impl From<Notification> for Call {
68	fn from(n: Notification) -> Self {
69		Call::Notification(n)
70	}
71}
72
73/// Represents jsonrpc request.
74#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
75#[serde(deny_unknown_fields)]
76#[serde(untagged)]
77pub enum Request {
78	/// Single request (call)
79	Single(Call),
80	/// Batch of requests (calls)
81	Batch(Vec<Call>),
82}
83
84#[cfg(test)]
85mod tests {
86	use super::*;
87	use serde_json::Value;
88
89	#[test]
90	fn method_call_serialize() {
91		use serde_json;
92		use serde_json::Value;
93
94		let m = MethodCall {
95			jsonrpc: Some(Version::V2),
96			method: "update".to_owned(),
97			params: Params::Array(vec![Value::from(1), Value::from(2)]),
98			id: Id::Num(1),
99		};
100
101		let serialized = serde_json::to_string(&m).unwrap();
102		assert_eq!(
103			serialized,
104			r#"{"jsonrpc":"2.0","method":"update","params":[1,2],"id":1}"#
105		);
106	}
107
108	#[test]
109	fn notification_serialize() {
110		use serde_json;
111		use serde_json::Value;
112
113		let n = Notification {
114			jsonrpc: Some(Version::V2),
115			method: "update".to_owned(),
116			params: Params::Array(vec![Value::from(1), Value::from(2)]),
117		};
118
119		let serialized = serde_json::to_string(&n).unwrap();
120		assert_eq!(serialized, r#"{"jsonrpc":"2.0","method":"update","params":[1,2]}"#);
121	}
122
123	#[test]
124	fn call_serialize() {
125		use serde_json;
126		use serde_json::Value;
127
128		let n = Call::Notification(Notification {
129			jsonrpc: Some(Version::V2),
130			method: "update".to_owned(),
131			params: Params::Array(vec![Value::from(1)]),
132		});
133
134		let serialized = serde_json::to_string(&n).unwrap();
135		assert_eq!(serialized, r#"{"jsonrpc":"2.0","method":"update","params":[1]}"#);
136	}
137
138	#[test]
139	fn request_serialize_batch() {
140		use serde_json;
141
142		let batch = Request::Batch(vec![
143			Call::MethodCall(MethodCall {
144				jsonrpc: Some(Version::V2),
145				method: "update".to_owned(),
146				params: Params::Array(vec![Value::from(1), Value::from(2)]),
147				id: Id::Num(1),
148			}),
149			Call::Notification(Notification {
150				jsonrpc: Some(Version::V2),
151				method: "update".to_owned(),
152				params: Params::Array(vec![Value::from(1)]),
153			}),
154		]);
155
156		let serialized = serde_json::to_string(&batch).unwrap();
157		assert_eq!(
158			serialized,
159			r#"[{"jsonrpc":"2.0","method":"update","params":[1,2],"id":1},{"jsonrpc":"2.0","method":"update","params":[1]}]"#
160		);
161	}
162
163	#[test]
164	fn notification_deserialize() {
165		use serde_json;
166		use serde_json::Value;
167
168		let s = r#"{"jsonrpc": "2.0", "method": "update", "params": [1,2]}"#;
169		let deserialized: Notification = serde_json::from_str(s).unwrap();
170
171		assert_eq!(
172			deserialized,
173			Notification {
174				jsonrpc: Some(Version::V2),
175				method: "update".to_owned(),
176				params: Params::Array(vec![Value::from(1), Value::from(2)])
177			}
178		);
179
180		let s = r#"{"jsonrpc": "2.0", "method": "foobar"}"#;
181		let deserialized: Notification = serde_json::from_str(s).unwrap();
182
183		assert_eq!(
184			deserialized,
185			Notification {
186				jsonrpc: Some(Version::V2),
187				method: "foobar".to_owned(),
188				params: Params::None,
189			}
190		);
191
192		let s = r#"{"jsonrpc": "2.0", "method": "update", "params": [1,2], "id": 1}"#;
193		let deserialized: Result<Notification, _> = serde_json::from_str(s);
194		assert!(deserialized.is_err());
195	}
196
197	#[test]
198	fn call_deserialize() {
199		use serde_json;
200
201		let s = r#"{"jsonrpc": "2.0", "method": "update", "params": [1]}"#;
202		let deserialized: Call = serde_json::from_str(s).unwrap();
203		assert_eq!(
204			deserialized,
205			Call::Notification(Notification {
206				jsonrpc: Some(Version::V2),
207				method: "update".to_owned(),
208				params: Params::Array(vec![Value::from(1)])
209			})
210		);
211
212		let s = r#"{"jsonrpc": "2.0", "method": "update", "params": [1], "id": 1}"#;
213		let deserialized: Call = serde_json::from_str(s).unwrap();
214		assert_eq!(
215			deserialized,
216			Call::MethodCall(MethodCall {
217				jsonrpc: Some(Version::V2),
218				method: "update".to_owned(),
219				params: Params::Array(vec![Value::from(1)]),
220				id: Id::Num(1)
221			})
222		);
223
224		let s = r#"{"jsonrpc": "2.0", "method": "update", "params": [], "id": 1}"#;
225		let deserialized: Call = serde_json::from_str(s).unwrap();
226		assert_eq!(
227			deserialized,
228			Call::MethodCall(MethodCall {
229				jsonrpc: Some(Version::V2),
230				method: "update".to_owned(),
231				params: Params::Array(vec![]),
232				id: Id::Num(1)
233			})
234		);
235
236		let s = r#"{"jsonrpc": "2.0", "method": "update", "params": null, "id": 1}"#;
237		let deserialized: Call = serde_json::from_str(s).unwrap();
238		assert_eq!(
239			deserialized,
240			Call::MethodCall(MethodCall {
241				jsonrpc: Some(Version::V2),
242				method: "update".to_owned(),
243				params: Params::None,
244				id: Id::Num(1)
245			})
246		);
247
248		let s = r#"{"jsonrpc": "2.0", "method": "update", "id": 1}"#;
249		let deserialized: Call = serde_json::from_str(s).unwrap();
250		assert_eq!(
251			deserialized,
252			Call::MethodCall(MethodCall {
253				jsonrpc: Some(Version::V2),
254				method: "update".to_owned(),
255				params: Params::None,
256				id: Id::Num(1)
257			})
258		);
259	}
260
261	#[test]
262	fn request_deserialize_batch() {
263		use serde_json;
264
265		let s = r#"[{}, {"jsonrpc": "2.0", "method": "update", "params": [1,2], "id": 1},{"jsonrpc": "2.0", "method": "update", "params": [1]}]"#;
266		let deserialized: Request = serde_json::from_str(s).unwrap();
267		assert_eq!(
268			deserialized,
269			Request::Batch(vec![
270				Call::Invalid { id: Id::Null },
271				Call::MethodCall(MethodCall {
272					jsonrpc: Some(Version::V2),
273					method: "update".to_owned(),
274					params: Params::Array(vec![Value::from(1), Value::from(2)]),
275					id: Id::Num(1)
276				}),
277				Call::Notification(Notification {
278					jsonrpc: Some(Version::V2),
279					method: "update".to_owned(),
280					params: Params::Array(vec![Value::from(1)])
281				})
282			])
283		)
284	}
285
286	#[test]
287	fn request_invalid_returns_id() {
288		use serde_json;
289
290		let s = r#"{"id":120,"method":"my_method","params":["foo", "bar"],"extra_field":[]}"#;
291		let deserialized: Request = serde_json::from_str(s).unwrap();
292
293		match deserialized {
294			Request::Single(Call::Invalid { id: Id::Num(120) }) => {}
295			_ => panic!("Request wrongly deserialized: {:?}", deserialized),
296		}
297	}
298}