tokio_jsonrpc/server.rs
1// Copyright 2017 tokio-jsonrpc Developers
2//
3// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
4// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5// http://opensource.org/licenses/MIT>, at your option. This file may not be
6// copied, modified, or distributed except according to those terms.
7
8//! The [`Server`](trait.Server.html) trait and helpers.
9//!
10//! The `Server` trait for the use by the [`Endpoint`](../endpoint/struct.Endpoint.html) is defined
11//! here. Furthermore, some helpers for convenient creation and composition of servers are
12//! available. Note that not all of these helpers are necessarily zero-cost, at least at this time.
13
14use futures::{Future, IntoFuture};
15use serde::Serialize;
16use serde_json::{to_value, Value};
17
18use endpoint::ServerCtl;
19use message::RpcError;
20
21/// The server endpoint.
22///
23/// This is usually implemented by the end application and provides the actual functionality of the
24/// RPC server. It allows composition of more servers together.
25///
26/// The default implementations of the callbacks return None, indicating that the given method is
27/// not known. It allows implementing only RPCs or only notifications without having to worry about
28/// the other callback. If you want a server that does nothing at all, use
29/// [`Empty`](struct.Empty.html).
30pub trait Server {
31 /// The successfull result of the RPC call.
32 type Success: Serialize;
33 /// The result of the RPC call
34 ///
35 /// Once the future resolves, the value or error is sent to the client as the reply. The reply
36 /// is wrapped automatically.
37 type RpcCallResult: IntoFuture<Item = Self::Success, Error = RpcError> + 'static;
38 /// The result of the RPC call.
39 ///
40 /// As the client doesn't expect anything in return, both the success and error results are
41 /// thrown away and therefore (). However, it still makes sense to distinguish success and
42 /// error.
43 type NotificationResult: IntoFuture<Item = (), Error = ()> + 'static;
44 /// Called when the client requests something.
45 ///
46 /// This is a callback from the [endpoint](../endpoint/struct.Endpoint.html) when the client
47 /// requests something. If the method is unknown, it shall return `None`. This allows
48 /// composition of servers.
49 ///
50 /// Conversion of parameters and handling of errors is up to the implementer of this trait.
51 /// However, the [`jsonrpc_params`](../macro.jsonrpc_params.html) macro may help in that
52 /// regard.
53 fn rpc(
54 &self, _ctl: &ServerCtl, _method: &str, _params: &Option<Value>
55 ) -> Option<Self::RpcCallResult> {
56 None
57 }
58 /// Called when the client sends a notification.
59 ///
60 /// This is a callback from the [endpoint](../endpoint/struct.Endpoint.html) when the client
61 /// requests something. If the method is unknown, it shall return `None`. This allows
62 /// composition of servers.
63 ///
64 /// Conversion of parameters and handling of errors is up to the implementer of this trait.
65 /// However, the [`jsonrpc_params`](../macro.jsonrpc_params.html) macro may help in that
66 /// regard.
67 fn notification(
68 &self, _ctl: &ServerCtl, _method: &str, _params: &Option<Value>
69 ) -> Option<Self::NotificationResult> {
70 None
71 }
72 /// Called when the endpoint is initialized.
73 ///
74 /// It provides a default empty implementation, which can be overriden to hook onto the
75 /// initialization.
76 fn initialized(&self, _ctl: &ServerCtl) {}
77}
78
79/// A RPC server that knows no methods.
80///
81/// You can use this if you want to have a client-only
82/// [Endpoint](../endpoint/struct.Endpoint.html). It simply terminates the server part right away.
83/// Or, more conveniently, use `Endpoint`'s
84/// [`client_only`](../endpoint/struct.Endpoint.html#method.client_only) method.
85pub struct Empty;
86
87impl Server for Empty {
88 type Success = ();
89 type RpcCallResult = Result<(), RpcError>;
90 type NotificationResult = Result<(), ()>;
91 fn initialized(&self, ctl: &ServerCtl) {
92 ctl.terminate();
93 }
94}
95
96/// An RPC server wrapper with dynamic dispatch.
97///
98/// This server wraps another server and converts it into a common ground, so multiple different
99/// servers can be used as trait objects. Basically, it boxes the futures it returns and converts
100/// the result into `serde_json::Value`. It can then be used together with
101/// [`ServerChain`](struct.ServerChain.html) easilly. Note that this conversion incurs
102/// runtime costs.
103pub struct AbstractServer<S: Server>(S);
104
105impl<S: Server> AbstractServer<S> {
106 /// Wraps another server into an abstract server.
107 pub fn new(server: S) -> Self {
108 AbstractServer(server)
109 }
110 /// Unwraps the abstract server and provides the one inside back.
111 pub fn into_inner(self) -> S {
112 self.0
113 }
114}
115
116/// A RPC call result wrapping trait objects.
117pub type BoxRpcCallResult = Box<Future<Item = Value, Error = RpcError>>;
118/// A notification call result wrapping trait objects.
119pub type BoxNotificationResult = Box<Future<Item = (), Error = ()>>;
120
121impl<S: Server> Server for AbstractServer<S> {
122 type Success = Value;
123 type RpcCallResult = BoxRpcCallResult;
124 type NotificationResult = BoxNotificationResult;
125 fn rpc(
126 &self, ctl: &ServerCtl, method: &str, params: &Option<Value>
127 ) -> Option<Self::RpcCallResult> {
128 self.0
129 .rpc(ctl, method, params)
130 .map(|f| -> Box<Future<Item = Value, Error = RpcError>> {
131 let future = f.into_future().map(|result| {
132 to_value(result)
133 .expect("Your result type is not convertible to JSON, which is a bug")
134 });
135 Box::new(future)
136 })
137 }
138 fn notification(
139 &self, ctl: &ServerCtl, method: &str, params: &Option<Value>
140 ) -> Option<Self::NotificationResult> {
141 // It seems the type signature is computed from inside the closure and it doesn't fit on
142 // the outside, so we need to declare it manually :-(
143 self.0
144 .notification(ctl, method, params)
145 .map(|f| -> Box<Future<Item = (), Error = ()>> { Box::new(f.into_future()) })
146 }
147 fn initialized(&self, ctl: &ServerCtl) {
148 self.0.initialized(ctl)
149 }
150}
151
152/// A type to store servers as trait objects.
153///
154/// See also [`AbstractServer`](struct.AbstractServer.html) and
155/// [`ServerChain`](struct.ServerChain.html).
156pub type BoxServer = Box<
157 Server<
158 Success = Value,
159 RpcCallResult = Box<Future<Item = Value, Error = RpcError>>,
160 NotificationResult = Box<Future<Item = (), Error = ()>>,
161 >,
162>;
163
164/// A server that chains several other servers.
165///
166/// This composes multiple servers into one. When a notification or an rpc comes, it tries one by
167/// one and passes the call to each of them. If the server provides an answer, the iteration is
168/// stopped and that answer is returned. If the server refuses the given method name, another
169/// server in the chain is tried, until one is found or we run out of servers.
170///
171/// Initialization is called on all the servers.
172///
173/// The [`AbstractServer`](struct.AbstractServer.html) is one of the ways to plug servers with
174/// incompatible future and success types inside.
175pub struct ServerChain(Vec<BoxServer>);
176
177impl ServerChain {
178 /// Construct a new server.
179 pub fn new(subservers: Vec<BoxServer>) -> Self {
180 ServerChain(subservers)
181 }
182 /// Consume the server and return the subservers inside.
183 pub fn into_inner(self) -> Vec<BoxServer> {
184 self.0
185 }
186 /// Iterate through the servers and return the first result that is `Some(_)`.
187 fn iter_chain<R, F: Fn(&BoxServer) -> Option<R>>(&self, f: F) -> Option<R> {
188 for sub in &self.0 {
189 let result = f(sub);
190 if result.is_some() {
191 return result;
192 }
193 }
194 None
195 }
196}
197
198impl Server for ServerChain {
199 type Success = Value;
200 type RpcCallResult = BoxRpcCallResult;
201 type NotificationResult = BoxNotificationResult;
202 fn rpc(
203 &self, ctl: &ServerCtl, method: &str, params: &Option<Value>
204 ) -> Option<Self::RpcCallResult> {
205 self.iter_chain(|sub| sub.rpc(ctl, method, params))
206 }
207 fn notification(
208 &self, ctl: &ServerCtl, method: &str, params: &Option<Value>
209 ) -> Option<Self::NotificationResult> {
210 self.iter_chain(|sub| sub.notification(ctl, method, params))
211 }
212 fn initialized(&self, ctl: &ServerCtl) {
213 for sub in &self.0 {
214 sub.initialized(ctl);
215 }
216 }
217}
218
219/// Parses the parameters of an RPC or a notification.
220///
221/// The [`Server`](server/trait.Server.html) receives `&Option<Value>` as the parameters when its
222/// `notification` or `rpc` method is called and it needs to handle it. This means checking for
223/// validity and converting it to appropriate types. This is tedious.
224///
225/// This macro helps with that. In it's basic usage, you pass the received parameters and parameter
226/// definitions for what you want and receive a tuple of converted ones. In case the parameters are
227/// invalid, it returns early with an `Some(IntoFuture<_, Error = RpcError>)` directly from your
228/// function (which is the return type of the callbacks).
229///
230/// Note that while this macro may be used directly, the macro
231/// [`jsonrpc_server_impl`](macro.jsonrpc_server_impl.html) which builds the whole `Server` trait
232/// implementation uses it internally and it is the preferred way to use it.
233///
234/// By default, it accepts both parameters passed by a name (inside a JSON object) or by position
235/// (inside an array). If you insist your clients must use named or positional parameters, prefix
236/// the parameter definitions by `named` or `positional` respectively. The `positional` omits the
237/// parameter names in the definitions.
238///
239/// This also handles optional arguments in the `named` case (and when auto-detecting and a JSON
240/// object is provided).
241///
242/// If an empty parameter definition is provided, the macro checks that no parameters were sent
243/// (accepts no parameters sent, `null` sent as parameters and an empty object or array).
244///
245/// If a single parameter is passed, in addition to trying positional and named parameters, the
246/// macro tries to convert the whole `Value` into the given type. This allows you to ask for
247/// a structure that holds all the named parameters.
248///
249/// If you want to force the single parameter conversion of the whole `Value`, you can use the
250/// macro as `jsonrpc_params!(params, single Type)`. However, in this case it returns
251/// `Result<Type, RpcError>` ‒ since it is expected you might want to try both named and
252/// positional decoding yourself. Also, it expects `&Value`, not `&Option<Value>`.
253///
254/// You can also force the macro to return the `Result<(Type, Type, ...), RpcError>` if you prefer,
255/// by prefixing the parameter definitions with the `wrap` token.
256///
257/// The macro has other variants than the mentioned here. They are mostly used internally by the
258/// macro itself and aren't meant to be used directly.
259///
260/// # Examples
261///
262/// Basic usage, parse an integer and a boolean:
263///
264/// ```rust
265/// # #[macro_use] extern crate tokio_jsonrpc;
266/// # #[macro_use] extern crate serde_json;
267/// # use tokio_jsonrpc::message::RpcError;
268/// # use serde_json::Value;
269/// fn parse(params: &Option<Value>) -> Option<Result<(i32, bool), RpcError>> {
270/// Some(Ok(jsonrpc_params!(params, "num" => i32, "b" => bool)))
271/// }
272///
273/// # fn main() {
274/// assert_eq!((42, true), parse(&Some(json!([42, true]))).unwrap().unwrap());
275/// assert_eq!((42, true), parse(&Some(json!({"num": 42, "b": true}))).unwrap().unwrap());
276/// parse(&None).unwrap().unwrap_err();
277/// parse(&Some(json!({"num": "hello", "b": false}))).unwrap().unwrap_err();
278/// // Return by the macro instead of exit
279/// assert_eq!((42, true), jsonrpc_params!(&Some(json!({"num": 42, "b": true})),
280/// wrap "num" => i32, "b" => bool).unwrap());
281/// jsonrpc_params!(&None, wrap "num" => i32, "b" => bool).unwrap_err();
282/// # }
283/// ```
284///
285/// Usage with enforcing named parameters. Also, the integer is optional. Enforcing positional
286/// works in a similar way, with the `positional` token.
287///
288/// ```rust
289/// # #[macro_use] extern crate tokio_jsonrpc;
290/// # #[macro_use] extern crate serde_json;
291/// # use tokio_jsonrpc::message::RpcError;
292/// # use serde_json::Value;
293/// fn parse(params: &Option<Value>) -> Option<Result<(Option<i32>, bool), RpcError>> {
294/// Some(Ok(jsonrpc_params!(params, named "num" => Option<i32>, "b" => bool)))
295/// }
296///
297/// # fn main() {
298/// parse(&Some(json!([42, true]))).unwrap().unwrap_err();
299/// assert_eq!((Some(42), true), parse(&Some(json!({"num": 42, "b": true}))).unwrap().unwrap());
300/// assert_eq!((None, false),
301/// parse(&Some(json!({"b": false, "extra": "ignored"}))).unwrap().unwrap());
302/// parse(&None).unwrap().unwrap_err();
303/// parse(&Some(json!({"num": "hello", "b": false}))).unwrap().unwrap_err();
304/// # }
305/// ```
306///
307/// Enforcing positional parameters:
308///
309/// ```rust
310/// # #[macro_use] extern crate tokio_jsonrpc;
311/// # #[macro_use] extern crate serde_json;
312/// # use tokio_jsonrpc::message::RpcError;
313/// # use serde_json::Value;
314/// fn parse(params: &Option<Value>) -> Option<Result<(i32, bool), RpcError>> {
315/// Some(Ok(jsonrpc_params!(params, positional i32, bool)))
316/// }
317///
318/// # fn main() {
319/// assert_eq!((42, true), parse(&Some(json!([42, true]))).unwrap().unwrap());
320/// # }
321/// ```
322///
323/// Decoding into a structure works like this:
324///
325/// ```rust
326/// # #[macro_use] extern crate tokio_jsonrpc;
327/// # #[macro_use] extern crate serde_json;
328/// # #[macro_use] extern crate serde_derive;
329/// # use tokio_jsonrpc::message::RpcError;
330/// # use serde_json::Value;
331///
332/// #[derive(PartialEq, Debug, Deserialize)]
333/// struct Params {
334/// num: Option<i32>,
335/// b: bool,
336/// }
337///
338/// fn parse(params: &Option<Value>) -> Option<Result<Params, RpcError>> {
339/// let (params,) = jsonrpc_params!(params, "params" => Params);
340/// Some(Ok(params))
341/// }
342///
343/// # fn main() {
344/// let expected = Params {
345/// num: Some(42),
346/// b: true,
347/// };
348/// let expected_optional = Params {
349/// num: None,
350/// b: false,
351/// };
352///
353/// assert_eq!(expected, parse(&Some(json!([42, true]))).unwrap().unwrap());
354/// assert_eq!(expected, parse(&Some(json!({"num": 42, "b": true}))).unwrap().unwrap());
355/// assert_eq!(expected_optional, parse(&Some(json!({"b": false}))).unwrap().unwrap());
356/// // This is accepted mostly as a side effect.
357/// assert_eq!(expected, parse(&Some(json!([{"num": 42, "b": true}]))).unwrap().unwrap());
358/// // As is this.
359/// assert_eq!(expected, parse(&Some(json!({"params": {"num": 42, "b": true}}))).unwrap().unwrap());
360/// // If you mind the above limitations, you can ask directly for a single value decoding.
361/// // That returs a Result directly.
362/// assert_eq!(expected,
363/// jsonrpc_params!(&json!({"num": 42, "b": true}), single Params).unwrap());
364/// jsonrpc_params!(&json!([{"num": 42, "b": true}]), single Params).unwrap_err();
365/// # }
366/// ```
367#[macro_export]
368macro_rules! jsonrpc_params {
369 // When the user asks for no params to be present. In that case we allow no params or null or
370 // empty array or dictionary, for better compatibility. This is probably more benevolent than
371 // the spec allows.
372 ( $value:expr, ) => {
373 match *$value {
374 // Accept the empty values
375 None |
376 Some($crate::macro_exports::Value::Null) => (),
377 Some($crate::macro_exports::Value::Array(ref arr)) if arr.len() == 0 => (),
378 Some($crate::macro_exports::Value::Object(ref obj)) if obj.len() == 0 => (),
379 // If it's anything else, complain
380 _ => {
381 return Some(Err($crate::message::RpcError::
382 invalid_params(Some("Expected no params".to_owned()))).into());
383 },
384 }
385 };
386 // A convenience conversion
387 ( $value:expr ) => { jsonrpc_params!($value,) };
388 // An internal helper to decode a single variable and provide a Result instead of returning
389 // from the function.
390 ( $value:expr, single $vartype:ty ) => {{
391 // Fix the type
392 let val: &$crate::macro_exports::Value = $value;
393 $crate::macro_exports::from_value::<$vartype>(val.clone()).map_err(|e| {
394 $crate::message::RpcError::invalid_params(Some(format!("Incompatible type: {}", e)))
395 })
396 }};
397 // A helper to count number of arguments
398 ( arity $head:ty ) => { 1 };
399 ( arity $head:ty, $( $tail:ty ),* ) => { 1 + jsonrpc_params!(arity $( $tail ),*) };
400 // A helper to recurse on decoding of positional arguments
401 ( $spl:expr, accum ( $( $result:tt )* ), positional_decode $vtype:ty ) => {
402 ( $( $result )*
403 {
404 let spl: &[$crate::macro_exports::Value] = $spl;
405 match jsonrpc_params!(&spl[0], single $vtype) {
406 Ok(result) => result,
407 Err(e) => return Some(Err(e)),
408 }
409 },
410 )
411 };
412 ( $spl:expr, accum ( $( $result:tt )* ),
413 positional_decode $htype:ty, $( $ttype:ty ),+ ) => {{
414 let spl: &[$crate::macro_exports::Value] = $spl;
415 jsonrpc_params!(&spl[1..], accum (
416 $( $result )*
417 {
418 match jsonrpc_params!(&spl[0], single $htype) {
419 Ok(result) => result,
420 Err(e) => return Some(Err(e)),
421 }
422 },
423 ), positional_decode $( $ttype ),+ )
424 }};
425 // Possibly multiple arguments, enforcing positional coding (in an array)
426 // It uses recursion to count and access the items in the vector
427 ( $value:expr, positional $( $vartype:ty ),+ ) => {{
428 let val: &$crate::macro_exports::Option<$crate::macro_exports::Value> = $value;
429 match *val {
430 None => return Some(Err($crate::message::RpcError::
431 invalid_params(Some("Expected parameters".to_owned()))).into()),
432 Some($crate::macro_exports::Value::Array(ref vec)) => {
433 let cnt = jsonrpc_params!(arity $( $vartype ),+);
434 if cnt != vec.len() {
435 let err = format!("Wrong number of parameters: expected: {}, got: {}", cnt,
436 vec.len());
437 return Some(Err($crate::message::RpcError::invalid_params(Some(err))).into());
438 }
439 let spl: &[$crate::macro_exports::Value] = &vec[..];
440 jsonrpc_params!(spl, accum (), positional_decode $( $vartype ),+)
441 },
442 Some(_) => {
443 return Some(Err($crate::message::RpcError::
444 invalid_params(Some("Expected an array as parameters".to_owned())))
445 .into());
446 },
447 }
448 }};
449 // Decode named arguments.
450 // It can handle optional arguments in a way, but it has its limits (eg. a non-optional string
451 // defaults to an empty one if it is missing).
452 ( $value:expr, named $( $varname:expr => $vartype:ty ),+ ) => {{
453 let val: &$crate::macro_exports::Option<$crate::macro_exports::Value> = $value;
454 match *val {
455 None => return Some(Err($crate::message::RpcError::
456 invalid_params(Some("Expected parameters".to_owned()))).into()),
457 Some($crate::macro_exports::Value::Object(ref map)) => {
458 (
459 $(
460 {
461 // Yes, stupid borrow checker… can't we get a global constant that
462 // never gets dropped?
463 let null = $crate::macro_exports::Value::Null;
464 let subval = map.get($varname).unwrap_or(&null);
465 match jsonrpc_params!(subval, single $vartype) {
466 Ok(result) => result,
467 Err(e) => return Some(Err(e)),
468 }
469 },
470 )+
471 )
472 },
473 Some(_) => {
474 return Some(Err($crate::message::RpcError::
475 invalid_params(Some("Expected an object as parameters".to_owned())))
476 .into());
477 },
478 }
479 }};
480 // Decode params, decide if named or positional based on what arrived
481 ( $value:expr, decide $( $varname:expr => $vartype:ty ),+ ) => {{
482 let val: &$crate::macro_exports::Option<$crate::macro_exports::Value> = $value;
483 match *val {
484 None => return Some(Err($crate::message::RpcError::
485 invalid_params(Some("Expected parameters".to_owned()))).into()),
486 Some($crate::macro_exports::Value::Array(_)) => {
487 jsonrpc_params!(val, positional $( $vartype ),+)
488 },
489 Some($crate::macro_exports::Value::Object(_)) => {
490 jsonrpc_params!(val, named $( $varname => $vartype ),+)
491 },
492 Some(_) => {
493 return Some(Err($crate::message::RpcError::
494 invalid_params(Some("Expected an object or an array as parameters"
495 .to_owned()))).into());
496 },
497 }
498 }};
499 // A special case for a single param.
500 //
501 // We allow decoding it directly, mostly to support users with a complex all-params structure.
502 ( $value:expr, $varname:expr => $vartype:ty ) => {{
503 let val: &$crate::macro_exports::Option<$crate::macro_exports::Value> = $value;
504 // First try decoding directly
505 let single = val.as_ref().map(|val| jsonrpc_params!(val, single $vartype));
506 if let Some(Ok(result)) = single {
507 (result,)
508 } else {
509 // If direct single decoding didn't work, try the usual multi-param way.
510 jsonrpc_params!(val, decide $varname => $vartype)
511 }
512 }};
513 // Propagate multiple params.
514 ( $value:expr, $( $varname:expr => $vartype:ty ),+ ) => {
515 jsonrpc_params!($value, decide $( $varname => $vartype ),+)
516 };
517 // Return multiple values as a result
518 ( $value:expr, wrap $( $varname:expr => $vartype:ty ),+ ) => {
519 {
520 fn convert(params: &$crate::macro_exports::Option<$crate::macro_exports::Value>)
521 -> $crate::macro_exports::Option<
522 $crate::macro_exports::Result<($( $vartype, )+),
523 $crate::message::RpcError>> {
524 Some(Ok(jsonrpc_params!(params, $( $varname => $vartype ),+)))
525 }
526 convert($value).unwrap()
527 }
528 };
529 ( $value:expr, wrap named $( $varname:expr => $vartype:ty ),+ ) => {
530 {
531 fn convert(params: &$crate::macro_exports::Option<$crate::macro_exports::Value>)
532 -> $crate::macro_exports::Option<
533 $crate::macro_exports::Result<($( $vartype, )+),
534 $crate::message::RpcError>> {
535 Some(Ok(jsonrpc_params!(params, named $( $varname => $vartype ),+)))
536 }
537 convert($value).unwrap()
538 }
539 };
540 ( $value:expr, wrap positional $( $vartype:ty ),+ ) => {
541 {
542 fn convert(params: &$crate::macro_exports::Option<$crate::macro_exports::Value>)
543 -> $crate::macro_exports::Option<
544 $crate::macro_exports::Result<($( $vartype, )+),
545 $crate::message::RpcError>> {
546 Some(Ok(jsonrpc_params!(params, positional $( $vartype ),+)))
547 }
548 convert($value).unwrap()
549 }
550 };
551}
552
553/*
554 The intention:
555
556 jsonrpc_server! {
557 X {
558 rpcs {
559 hello(i: usize); // Will call x.hello(i), convert parameters, convert result…
560 }
561 notifications {
562 hi(x: String); // Will call x.hi(…)
563 }
564 init // Will call x.init
565 }
566 }
567
568
569 */
570
571/*
572trace_macros!(true);
573// TODO: We want to be able to accept arrays of different kinds of data, possibly alternatives…
574macro_rules! json_param {
575 ( (), $value:ident ) => { () };
576 ( $param:ty, $value:ident ) => {
577 match *$value {
578 None => unimplemented!(),
579 Some(ref v) => {
580 let result: Result<$param, _> = from_value(v.clone());
581 match result {
582 Ok(r) => r,
583 Err(_) => unimplemented!(),
584 }
585 },
586 }
587 }
588}
589macro_rules! json_rpc_impl {
590 ( $( $method:pat => ($param:ty) $code:block ),* ) => {
591 // TODO Use $crate for the types and absolute paths for Value
592 fn rpc(&self, ctl: &ServerCtl, method: &str, param: &Option<Value>) ->
593 Option<Self::RpcCallResult> {
594 match method {
595 $( $method => {
596 let input = json_param!($param, param);
597 let result = $code;
598 let mapped = result.map(|r| to_value(r).expect("Error converting RPC result"));
599 Some(Box::new(mapped.into_future()))
600 }, )*
601 _ => None,
602 }
603 }
604 };
605}
606
607 struct X;
608
609 impl Server for X {
610 type Success = Value;
611 type RpcCallResult = BoxRpcCallResult;
612 type NotificationResult = BoxNotificationResult;
613 json_rpc_impl!{
614 "test" => (usize) {
615 Ok(42)
616 },
617 "another" => (bool) {
618 Ok("Hello".to_owned())
619 }
620 }
621 }
622 */
623
624#[cfg(test)]
625mod tests {
626 use std::cell::{Cell, RefCell};
627 use serde_json::Map;
628
629 use super::*;
630
631 /// Check the empty server is somewhat sane.
632 #[test]
633 fn empty() {
634 let server = Empty;
635 let (ctl, dropped, _killed) = ServerCtl::new_test();
636 // As we can't reasonably check all possible method names, do so for just a bunch
637 for method in ["method", "notification", "check"].iter() {
638 assert!(server.rpc(&ctl, method, &None).is_none());
639 assert!(server.notification(&ctl, method, &None).is_none());
640 }
641 // It terminates the ctl on the server side on initialization
642 server.initialized(&ctl);
643 dropped.wait().unwrap();
644 }
645
646 /// A server that logs what has been called.
647 #[derive(Default, Debug, PartialEq)]
648 struct LogServer {
649 serial: Cell<usize>,
650 rpc: RefCell<Vec<usize>>,
651 notification: RefCell<Vec<usize>>,
652 initialized: RefCell<Vec<usize>>,
653 }
654
655 impl LogServer {
656 fn update(&self, what: &RefCell<Vec<usize>>) {
657 let serial = self.serial.get() + 1;
658 self.serial.set(serial);
659 what.borrow_mut().push(serial);
660 }
661 }
662
663 impl Server for LogServer {
664 type Success = bool;
665 type RpcCallResult = Result<bool, RpcError>;
666 type NotificationResult = Result<(), ()>;
667 fn rpc(
668 &self, _ctl: &ServerCtl, method: &str, params: &Option<Value>
669 ) -> Option<Self::RpcCallResult> {
670 self.update(&self.rpc);
671 match method {
672 "test" => {
673 assert!(params.is_none());
674 Some(Ok(true))
675 },
676 _ => None,
677 }
678 }
679 fn notification(
680 &self, _ctl: &ServerCtl, method: &str, params: &Option<Value>
681 ) -> Option<Self::NotificationResult> {
682 self.update(&self.notification);
683 assert!(params.is_none());
684 match method {
685 "notification" => Some(Ok(())),
686 _ => None,
687 }
688 }
689 fn initialized(&self, _ctl: &ServerCtl) {
690 self.update(&self.initialized);
691 }
692 }
693
694 /// Testing of the abstract server
695 ///
696 /// Just checking the data gets through and calling everything, there's nothing much to test
697 /// anyway.
698 #[test]
699 fn abstract_server() {
700 let log_server = LogServer::default();
701 let abstract_server = AbstractServer::new(log_server);
702 let (ctl, _, _) = ServerCtl::new_test();
703 let rpc_result = abstract_server
704 .rpc(&ctl, "test", &None)
705 .unwrap()
706 .wait()
707 .unwrap();
708 assert_eq!(Value::Bool(true), rpc_result);
709 abstract_server
710 .notification(&ctl, "notification", &None)
711 .unwrap()
712 .wait()
713 .unwrap();
714 assert!(abstract_server.rpc(&ctl, "another", &None).is_none());
715 assert!(
716 abstract_server
717 .notification(&ctl, "another", &None)
718 .is_none()
719 );
720 abstract_server.initialized(&ctl);
721 let log_server = abstract_server.into_inner();
722 let expected = LogServer {
723 serial: Cell::new(5),
724 rpc: RefCell::new(vec![1, 3]),
725 notification: RefCell::new(vec![2, 4]),
726 initialized: RefCell::new(vec![5]),
727 };
728 assert_eq!(expected, log_server);
729 }
730
731 struct AnotherServer;
732
733 impl Server for AnotherServer {
734 type Success = usize;
735 type RpcCallResult = Result<usize, RpcError>;
736 type NotificationResult = Result<(), ()>;
737 fn rpc(
738 &self, _ctl: &ServerCtl, method: &str, params: &Option<Value>
739 ) -> Option<Self::RpcCallResult> {
740 assert!(params.as_ref().unwrap().is_null());
741 match method {
742 "another" => Some(Ok(42)),
743 _ => None,
744 }
745 }
746 // Ignore the other methods
747 }
748
749 /// Test the chain.
750 ///
751 /// By the asserts on params in the servers we check that only whan should be called is.
752 #[test]
753 fn chain() {
754 let empty_server = Empty;
755 let log_server = LogServer::default();
756 let another_server = AnotherServer;
757 let (ctl, dropped, _killed) = ServerCtl::new_test();
758 let chain = ServerChain::new(vec![
759 Box::new(AbstractServer::new(empty_server)),
760 Box::new(AbstractServer::new(log_server)),
761 Box::new(AbstractServer::new(another_server)),
762 ]);
763 chain.initialized(&ctl);
764 dropped.wait().unwrap();
765 assert_eq!(
766 Value::Bool(true),
767 chain.rpc(&ctl, "test", &None).unwrap().wait().unwrap()
768 );
769 assert_eq!(
770 json!(42),
771 chain
772 .rpc(&ctl, "another", &Some(Value::Null))
773 .unwrap()
774 .wait()
775 .unwrap()
776 );
777 assert!(chain.rpc(&ctl, "wrong", &Some(Value::Null)).is_none());
778 chain
779 .notification(&ctl, "notification", &None)
780 .unwrap()
781 .wait()
782 .unwrap();
783 assert!(chain.notification(&ctl, "another", &None).is_none());
784 // It would be great to check what is logged inside the log server. But downcasting a trait
785 // object seems to be a big pain and probably isn't worth it here.
786 }
787
788 /// A guard object that panics when dropped unless it has been disarmed first.
789 ///
790 /// We use it to check the macro we test didn't short-circuit the test by returning early. Note
791 /// that it causes a double panic if the test fails (in that case you want to temporarily
792 /// remove the panic guard from that test).
793 ///
794 /// Most of the following tests don't need it, as they call the macro indirectly, by wrapping
795 /// it into a function (and such function can't return in the caller).
796 struct PanicGuard(bool);
797
798 impl PanicGuard {
799 /// A constructor. Creates an armed guerd.
800 fn new() -> Self {
801 PanicGuard(true)
802 }
803 /// Disarm the guard → it won't panic when dropped.
804 fn disarm(&mut self) {
805 self.0 = false;
806 }
807 }
808
809 impl Drop for PanicGuard {
810 fn drop(&mut self) {
811 if self.0 {
812 panic!("PanicGuard dropped without being disarmed");
813 }
814 }
815 }
816
817 /// Test the panic guard itself
818 #[test]
819 #[should_panic]
820 fn panic_guard() {
821 PanicGuard::new();
822 }
823
824 /// Expect no params and return whanever we got from the macro.
825 ///
826 /// It is a separate function so the return error thing from the macro doesn't end the test
827 /// prematurely (actually, it wouldn't, as the return type doesn't match).
828 fn expect_no_params(params: &Option<Value>) -> Option<Result<(), RpcError>> {
829 // Check that we can actually assign it somewhere (this may be needed in other macros later
830 // on.
831 let () = jsonrpc_params!(params,);
832 Some(Ok(()))
833 }
834
835 /// Test the jsonrpc_params macro when we expect no parameters.
836 #[test]
837 fn params_macro_none() {
838 // These are legal no-params, at least for us
839 expect_no_params(&None).unwrap().unwrap();
840 expect_no_params(&Some(Value::Null)).unwrap().unwrap();
841 expect_no_params(&Some(Value::Array(Vec::new())))
842 .unwrap()
843 .unwrap();
844 expect_no_params(&Some(Value::Object(Map::new())))
845 .unwrap()
846 .unwrap();
847 // Some illegal values
848 expect_no_params(&Some(Value::Bool(true)))
849 .unwrap()
850 .unwrap_err();
851 expect_no_params(&Some(json!([42, "hello"])))
852 .unwrap()
853 .unwrap_err();
854 expect_no_params(&Some(json!({"hello": 42})))
855 .unwrap()
856 .unwrap_err();
857 expect_no_params(&Some(json!(42))).unwrap().unwrap_err();
858 expect_no_params(&Some(json!("hello")))
859 .unwrap()
860 .unwrap_err();
861 }
862
863 /// Test the single-param jsonrpc_params helper variant.
864 #[test]
865 fn single_param() {
866 let mut guard = PanicGuard::new();
867 // A valid conversion
868 // Make sure the return type fits
869 let result: Result<bool, RpcError> = jsonrpc_params!(&Value::Bool(true), single bool);
870 assert!(result.unwrap());
871 // Some invalid conversions
872 jsonrpc_params!(&Value::Null, single bool).unwrap_err();
873 jsonrpc_params!(&Value::Array(Vec::new()), single bool).unwrap_err();
874 guard.disarm();
875 }
876
877 /// A helper function to decode two values as positional arguments.
878 ///
879 /// This is to prevent attempt to return errors from within the test function.
880 fn bool_str_positional(value: &Option<Value>) -> Option<Result<(bool, String), RpcError>> {
881 let (b, s) = jsonrpc_params!(value, positional bool, String);
882 Some(Ok((b, s)))
883 }
884
885 /// Like above, but with only a single variable.
886 ///
887 /// As single-values are handled slightly differently at a syntax level (eg, a tuple with only
888 /// one element needs a terminating comma) and also differently in the macro (they are
889 /// sometimes the ends of recursion), we mostly want to check it compiles.
890 ///
891 /// It also checks we don't get confused with an array inside the parameter array.
892 fn single_positional(value: &Option<Value>) -> Option<Result<Vec<String>, RpcError>> {
893 let (r,) = jsonrpc_params!(value, positional Vec<String>);
894 Some(Ok(r))
895 }
896
897 /// Test decoding positional arguments.
898 #[test]
899 fn positional() {
900 // Some that don't match
901 bool_str_positional(&None).unwrap().unwrap_err();
902 bool_str_positional(&Some(Value::Null))
903 .unwrap()
904 .unwrap_err();
905 bool_str_positional(&Some(Value::Bool(true)))
906 .unwrap()
907 .unwrap_err();
908 bool_str_positional(&Some(json!({"b": true, "s": "hello"})))
909 .unwrap()
910 .unwrap_err();
911 bool_str_positional(&Some(json!([true])))
912 .unwrap()
913 .unwrap_err();
914 bool_str_positional(&Some(json!([true, "hello", false])))
915 .unwrap()
916 .unwrap_err();
917 bool_str_positional(&Some(json!([true, true])))
918 .unwrap()
919 .unwrap_err();
920 // This one should be fine
921 assert_eq!(
922 (true, "hello".to_owned()),
923 bool_str_positional(&Some(json!([true, "hello"])))
924 .unwrap()
925 .unwrap()
926 );
927
928 single_positional(&None).unwrap().unwrap_err();
929 // We need two nested arrays
930 single_positional(&Some(json!(["Hello"])))
931 .unwrap()
932 .unwrap_err();
933 assert!(
934 single_positional(&Some(json!([[]])))
935 .unwrap()
936 .unwrap()
937 .is_empty()
938 );
939 assert_eq!(
940 vec!["hello", "world"],
941 single_positional(&Some(json!([["hello", "world"]])))
942 .unwrap()
943 .unwrap()
944 );
945 }
946
947 /// Similar to `positional`, but with using the macro wrap support to return a result.
948 #[test]
949 fn positional_direct() {
950 let mut guard = PanicGuard::new();
951 jsonrpc_params!(&None, wrap positional bool, String).unwrap_err();
952 jsonrpc_params!(&Some(Value::Null), wrap positional bool, String).unwrap_err();
953 jsonrpc_params!(&Some(Value::Bool(true)), wrap positional bool, String).unwrap_err();
954 jsonrpc_params!(&Some(json!({"b": true, "s": "hello"})), wrap positional bool, String)
955 .unwrap_err();
956 assert_eq!(
957 (true, "hello".to_owned()),
958 jsonrpc_params!(&Some(json!([true, "hello"])),
959 wrap positional bool, String)
960 .unwrap()
961 );
962 guard.disarm();
963 }
964
965 /// Helper function to decode two values as named arguments
966 fn bool_str_named(value: &Option<Value>) -> Option<Result<(bool, String), RpcError>> {
967 let (b, s) = jsonrpc_params!(value, named "b" => bool, "s" => String);
968 Some(Ok((b, s)))
969 }
970
971 #[derive(Deserialize, Debug, Eq, PartialEq)]
972 struct TestStruct {
973 x: i32,
974 }
975
976 /// Like above, but with only one parameter.
977 fn single_named(value: &Option<Value>) -> Option<Result<TestStruct, RpcError>> {
978 let (ts,) = jsonrpc_params!(value, named "ts" => TestStruct);
979 Some(Ok(ts))
980 }
981
982 /// Test an optional value might be missing.
983 fn optional_named(value: &Option<Value>) -> Option<Result<Option<u32>, RpcError>> {
984 let (ov,) = jsonrpc_params!(value, named "ov" => Option<u32>);
985 Some(Ok(ov))
986 }
987
988 /// Test decoding named arguments
989 #[test]
990 fn named() {
991 bool_str_named(&None).unwrap().unwrap_err();
992 bool_str_named(&Some(Value::Null)).unwrap().unwrap_err();
993 bool_str_named(&Some(Value::Bool(true)))
994 .unwrap()
995 .unwrap_err();
996 bool_str_named(&Some(json!([true, "hello"])))
997 .unwrap()
998 .unwrap_err();
999 bool_str_named(&Some(json!({"b": true, "s": 42})))
1000 .unwrap()
1001 .unwrap_err();
1002 // FIXME: This fails, as serde_json considers Value::Null to be an empty string
1003 //bool_str_named(&Some(json!({"b": true}))).unwrap_err();
1004 bool_str_named(&Some(json!({"s": "hello"})))
1005 .unwrap()
1006 .unwrap_err();
1007 assert_eq!(
1008 (true, "hello".to_owned()),
1009 bool_str_named(&Some(json!({"b": true, "s": "hello"})))
1010 .unwrap()
1011 .unwrap()
1012 );
1013 // FIXME: We currently don't know how to check against extra params
1014 assert_eq!(
1015 (true, "hello".to_owned()),
1016 bool_str_named(&Some(json!({"b": true, "s": "hello", "x": 42})))
1017 .unwrap()
1018 .unwrap()
1019 );
1020
1021 single_named(&None).unwrap().unwrap_err();
1022 single_named(&Some(json!({"ts": 42}))).unwrap().unwrap_err();
1023 single_named(&Some(json!({"ts": {"x": 42}})))
1024 .unwrap()
1025 .unwrap();
1026
1027 optional_named(&None).unwrap().unwrap_err();
1028 optional_named(&Some(json!([]))).unwrap().unwrap_err();
1029 assert_eq!(
1030 Some(42),
1031 optional_named(&Some(json!({"ov": 42}))).unwrap().unwrap()
1032 );
1033 assert_eq!(None, optional_named(&Some(json!({}))).unwrap().unwrap());
1034 }
1035
1036 /// Like `named`, but using auto-wrapping support from the macro.
1037 #[test]
1038 fn named_direct() {
1039 let mut guard = PanicGuard::new();
1040 jsonrpc_params!(&None, wrap named "b" => bool, "s" => String).unwrap_err();
1041 jsonrpc_params!(&Some(Value::Null), wrap named "b" => bool, "s" => String).unwrap_err();
1042 jsonrpc_params!(&Some(Value::Bool(true)),
1043 wrap named "b" => bool, "s" => String)
1044 .unwrap_err();
1045 assert_eq!(
1046 (true, "hello".to_owned()),
1047 jsonrpc_params!(&Some(json!({"b": true, "s": "hello"})),
1048 wrap "b" => bool, "s" => String)
1049 .unwrap()
1050 );
1051 jsonrpc_params!(&Some(json!([true, "hello"])), wrap named "b" => bool, "s" => String)
1052 .unwrap_err();
1053 guard.disarm();
1054 }
1055
1056 /// A helper function to decode two parameters.
1057 ///
1058 /// The decoding decides how to do so based on what arrived.
1059 fn bool_str(value: &Option<Value>) -> Option<Result<(bool, String), RpcError>> {
1060 let (b, s) = jsonrpc_params!(value, "b" => bool, "s" => String);
1061 Some(Ok((b, s)))
1062 }
1063
1064 /// Test decoding parameters when it decides itself how.
1065 #[test]
1066 fn decide() {
1067 bool_str(&None).unwrap().unwrap_err();
1068 bool_str(&Some(Value::Null)).unwrap().unwrap_err();
1069 bool_str(&Some(Value::Bool(true))).unwrap().unwrap_err();
1070 assert_eq!(
1071 (true, "hello".to_owned()),
1072 bool_str_named(&Some(json!({"b": true, "s": "hello"})))
1073 .unwrap()
1074 .unwrap()
1075 );
1076 assert_eq!(
1077 (true, "hello".to_owned()),
1078 bool_str_positional(&Some(json!([true, "hello"])))
1079 .unwrap()
1080 .unwrap()
1081 );
1082 }
1083
1084 /// Like `decide`, but with auto-wrapping support from the macro.
1085 #[test]
1086 fn decide_direct() {
1087 let mut guard = PanicGuard::new();
1088 jsonrpc_params!(&None, wrap "b" => bool, "s" => String).unwrap_err();
1089 jsonrpc_params!(&Some(Value::Null), wrap "b" => bool, "s" => String).unwrap_err();
1090 jsonrpc_params!(&Some(Value::Bool(true)), wrap "b" => bool, "s" => String).unwrap_err();
1091 assert_eq!(
1092 (true, "hello".to_owned()),
1093 jsonrpc_params!(&Some(json!({"b": true, "s": "hello"})),
1094 wrap "b" => bool, "s" => String)
1095 .unwrap()
1096 );
1097 assert_eq!(
1098 (true, "hello".to_owned()),
1099 jsonrpc_params!(&Some(json!([true, "hello"])),
1100 wrap "b" => bool, "s" => String)
1101 .unwrap()
1102 );
1103 guard.disarm();
1104 }
1105
1106 /// A helper for the `decide_single` test.
1107 fn decode_test_struct(value: &Option<Value>) -> Option<Result<TestStruct, RpcError>> {
1108 let (ts,) = jsonrpc_params!(value, "ts" => TestStruct);
1109 Some(Ok(ts))
1110 }
1111
1112 /// Similar to `decide`, but with a single parameter.
1113 ///
1114 /// The single parameter is special, since it can decode the parameters structure directly.
1115 /// This is to support the user having an all-encompassing parameter struct (possibly with all
1116 /// optional/default/renaming tweaks done through fine-tuning serde).
1117 #[test]
1118 fn decide_single() {
1119 decode_test_struct(&None).unwrap().unwrap_err();
1120 decode_test_struct(&Some(Value::Null)).unwrap().unwrap_err();
1121 decode_test_struct(&Some(Value::Bool(true)))
1122 .unwrap()
1123 .unwrap_err();
1124
1125 // Encoded as an array
1126 assert_eq!(
1127 TestStruct { x: 42 },
1128 decode_test_struct(&Some(json!([{"x": 42}])))
1129 .unwrap()
1130 .unwrap()
1131 );
1132 // Encoded as an object
1133 assert_eq!(
1134 TestStruct { x: 42 },
1135 decode_test_struct(&Some(json!({"ts": {"x": 42}})))
1136 .unwrap()
1137 .unwrap()
1138 );
1139 // Encoded directly as the parameters structure
1140 assert_eq!(
1141 TestStruct { x: 42 },
1142 decode_test_struct(&Some(json!({"x": 42})))
1143 .unwrap()
1144 .unwrap()
1145 );
1146 }
1147}