1#![deny(missing_docs)]
187
188const SERIALZATION_ERROR: i64 = -32000;
189
190pub use easy_jsonrpc_proc_macro::rpc;
191
192#[doc(hidden)]
194pub use jsonrpc_core::types::{
195 self, Error, ErrorCode, Failure, Id, MethodCall, Notification, Output, Success, Version,
196};
197#[doc(hidden)]
198use serde::de::Deserialize;
199#[doc(hidden)]
200pub use serde_json::{self, Value};
201
202use rand;
203use serde::ser::Serialize;
204use serde_json::json;
205use std::{collections::BTreeMap, marker::PhantomData};
206
207pub trait Handler {
209 fn handle(&self, method: &str, params: Params) -> Result<Value, jsonrpc_core::Error>;
212
213 fn handle_request(&self, raw_request: Value) -> MaybeReply {
215 let request: jsonrpc_core::Request = match serde_json::from_value(raw_request) {
216 Ok(request) => request,
217 Err(_) => {
218 return MaybeReply::Reply(serde_json::json!({
219 "jsonrpc": "2.0",
220 "error": {
221 "code": -32700,
222 "message": "Parse error"
223 },
224 "id": null
225 }));
226 }
227 };
228 let response = match handle_parsed_request(self, request) {
229 Some(ret) => ret,
230 None => return MaybeReply::DontReply,
231 };
232 MaybeReply::Reply(serde_json::to_value(response).unwrap_or_else(|e| {
233 serde_json::json!({
234 "jsonrpc": "2.0",
235 "error": {
236 "code": SERIALZATION_ERROR,
237 "message": "Serialization error",
238 "data": format!("{}", e),
239 },
240 "id": null
241 })
242 }))
243 }
244}
245
246#[derive(Clone, PartialEq, Debug)]
248pub enum MaybeReply {
249 Reply(Value),
251 DontReply,
253}
254
255impl MaybeReply {
256 pub fn as_option(self) -> Option<Value> {
258 match self {
259 MaybeReply::Reply(val) => Some(val),
260 MaybeReply::DontReply => None,
261 }
262 }
263}
264
265fn handle_call<S: ?Sized + Handler>(slef: &S, call: jsonrpc_core::Call) -> Option<Output> {
270 let (method, params, maybe_id, version): (
271 String,
272 jsonrpc_core::Params,
273 Option<Id>,
274 Option<Version>,
275 ) = match call {
276 jsonrpc_core::Call::Invalid { id } => {
277 return Some(Output::invalid_request(id, None));
278 }
279 jsonrpc_core::Call::MethodCall(MethodCall {
280 method,
281 params,
282 id,
283 jsonrpc,
284 }) => (method, params, Some(id), jsonrpc),
285 jsonrpc_core::Call::Notification(Notification {
286 method,
287 params,
288 jsonrpc,
289 }) => (method, params, None, jsonrpc),
290 };
291 let args = Params::from_rc_params(params);
292 let ret = slef.handle(&method, args);
293 let id = maybe_id?;
294 Some(match ret {
295 Ok(ok) => Output::Success(Success {
296 jsonrpc: version,
297 result: ok,
298 id,
299 }),
300 Err(err) => Output::Failure(Failure {
301 jsonrpc: version,
302 error: err,
303 id,
304 }),
305 })
306}
307
308fn handle_parsed_request<S: ?Sized + Handler>(
311 slef: &S,
312 request: jsonrpc_core::Request,
313) -> Option<jsonrpc_core::Response> {
314 match request {
315 jsonrpc_core::Request::Single(call) => {
316 handle_call(slef, call).map(jsonrpc_core::Response::Single)
317 }
318 jsonrpc_core::Request::Batch(mut calls) => {
319 let outputs = calls
320 .drain(..)
321 .filter_map(|call| handle_call(slef, call))
322 .collect::<Vec<_>>();
323 if outputs.is_empty() {
324 None
325 } else {
326 Some(jsonrpc_core::Response::Batch(outputs))
327 }
328 }
329 }
330}
331
332#[doc(hidden)]
333#[derive(
334 Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, serde::Serialize, serde::Deserialize,
335)]
336pub enum InvalidArgs {
337 WrongNumberOfArgs { expected: usize, actual: usize },
338 ExtraNamedParameter { name: String },
339 MissingNamedParameter { name: &'static str },
340 InvalidArgStructure { name: &'static str, index: usize },
341}
342
343impl Into<Error> for InvalidArgs {
344 fn into(self) -> Error {
345 match self {
346 InvalidArgs::WrongNumberOfArgs { expected, actual } => Error::invalid_params(format!(
347 "WrongNumberOfArgs. Expected {}. Actual {}",
348 expected, actual
349 )),
350 InvalidArgs::ExtraNamedParameter { name } => {
351 Error::invalid_params(format!("ExtraNamedParameter {}", name))
352 }
353 InvalidArgs::MissingNamedParameter { name } => {
354 Error::invalid_params(format!("MissingNamedParameter {}", name))
355 }
356 InvalidArgs::InvalidArgStructure { name, index } => Error::invalid_params(format!(
357 "InvalidArgStructure {} at position {}.",
358 name, index
359 )),
360 }
361 }
362}
363
364#[derive(Debug)]
369pub enum Params {
370 Positional(Vec<Value>),
373 Named(serde_json::Map<String, Value>),
375}
376
377impl Params {
378 fn from_rc_params(params: jsonrpc_core::Params) -> Self {
379 match params {
380 jsonrpc_core::Params::Array(arr) => Params::Positional(arr),
381 jsonrpc_core::Params::Map(map) => Params::Named(map),
382 jsonrpc_core::Params::None => Params::Positional(vec![]),
383 }
384 }
385
386 pub fn get_rpc_args(self, names: &[&'static str]) -> Result<Vec<Value>, InvalidArgs> {
394 debug_assert!(
395 {
396 fn contains_duplicates(list: &[&str]) -> bool {
397 (1..list.len()).any(|i| list[i..].contains(&list[i - 1]))
398 }
399 !contains_duplicates(names)
400 },
401 "get_rpc_args recieved duplicate argument names"
402 );
403 let ar: Vec<Value> = match self {
404 Params::Positional(ar) => ar,
405 Params::Named(mut ma) => {
406 let mut ar: Vec<Value> = Vec::with_capacity(names.len());
407 for name in names.iter() {
408 ar.push(
409 ma.remove(*name)
410 .ok_or(InvalidArgs::MissingNamedParameter { name })?,
411 );
412 }
413 debug_assert_eq!(ar.len(), names.len());
414 match ma.keys().next() {
415 Some(key) => {
416 return Err(InvalidArgs::ExtraNamedParameter { name: key.clone() })
417 }
418 None => ar,
419 }
420 }
421 };
422 if ar.len() != names.len() {
423 Err(InvalidArgs::WrongNumberOfArgs {
424 expected: names.len(),
425 actual: ar.len(),
426 })
427 } else {
428 Ok(ar)
429 }
430 }
431}
432
433#[derive(Debug)]
438pub struct BoundMethod<'a, T>
439where
440 T: Deserialize<'static>,
441{
442 method: &'a str,
443 args: Vec<Value>,
444 _spook: PhantomData<*const T>,
445}
446
447impl<'a, T> BoundMethod<'a, T>
448where
449 T: Deserialize<'static>,
450{
451 pub fn new(method: &'a str, args: Vec<Value>) -> BoundMethod<T> {
455 BoundMethod {
456 method,
457 args,
458 _spook: PhantomData,
459 }
460 }
461
462 pub fn call(&'a self) -> (Call<'a>, Tracker<T>)
464 where
465 T: Deserialize<'static>,
466 {
467 let Self { method, args, .. } = self;
468 let id = rand::random::<u64>();
469 (
470 Call {
471 method,
472 args,
473 id: Some(id),
474 },
475 Tracker {
476 id,
477 _spook: PhantomData,
478 },
479 )
480 }
481
482 pub fn notification(&'a self) -> Call<'a> {
485 let Self { method, args, .. } = self;
486 Call {
487 method,
488 args,
489 id: None,
490 }
491 }
492}
493
494pub struct Call<'a> {
500 method: &'a str,
501 args: &'a [Value],
502 id: Option<u64>,
503}
504
505impl<'a> Call<'a> {
506 pub fn as_request(&self) -> Value {
508 let Self { method, id, args } = self;
509 match id {
510 Some(id) => json!({
511 "jsonrpc": "2.0",
512 "method": method,
513 "params": args,
514 "id": id,
515 }),
516 None => json!({
517 "jsonrpc": "2.0",
518 "method": method,
519 "params": args,
520 }),
521 }
522 }
523
524 pub fn batch_request(calls: &[Self]) -> Value {
526 debug_assert!({
527 fn contains_duplicates(list: &[u64]) -> bool {
528 (1..list.len()).any(|i| list[i..].contains(&list[i - 1]))
529 }
530 let ids = calls.iter().filter_map(|call| call.id).collect::<Vec<_>>();
531 !contains_duplicates(ids.as_slice())
532 });
533 Value::Array(calls.iter().map(Call::as_request).collect())
534 }
535}
536
537#[doc(hidden)]
539pub fn try_serialize<T: Serialize>(t: &T) -> Result<Value, Error> {
540 serde_json::to_value(t).map_err(|e| Error {
544 code: ErrorCode::ServerError(SERIALZATION_ERROR),
545 message: "Serialization error".to_owned(),
546 data: Some(Value::String(format!("{}", e))),
547 })
548}
549
550#[derive(Clone, PartialEq, Debug)]
552pub enum ResponseFail {
553 ResultNotFound,
555 InvalidResponse,
557 RpcError(Error),
559}
560
561#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
565pub struct ArgSerializeError;
566
567#[derive(Clone, PartialEq, Debug)]
569pub enum InvalidResponse {
570 DeserailizeFailure,
572 ContainsNonNumericId,
575}
576
577pub struct Response {
580 pub outputs: BTreeMap<u64, Result<Value, Error>>,
582}
583
584impl Response {
585 pub fn from_json_response(raw_jsonrpc_response: Value) -> Result<Self, InvalidResponse> {
587 let response: jsonrpc_core::Response = serde_json::from_value(raw_jsonrpc_response)
588 .map_err(|_| InvalidResponse::DeserailizeFailure)?;
589 let mut calls: Vec<Output> = match response {
590 jsonrpc_core::Response::Single(out) => vec![out],
591 jsonrpc_core::Response::Batch(outs) => outs,
592 };
593 debug_assert!({
594 fn contains_duplicates(list: &[u64]) -> bool {
595 (1..list.len()).any(|i| list[i..].contains(&list[i - 1]))
596 }
597 let ids = calls
598 .iter()
599 .filter_map(|out| match out {
600 Output::Success(Success {
601 id: Id::Num(id), ..
602 })
603 | Output::Failure(Failure {
604 id: Id::Num(id), ..
605 }) => Some(*id),
606 _ => None,
607 })
608 .collect::<Vec<_>>();
609 !contains_duplicates(ids.as_slice())
610 });
611 let outputs = calls
612 .drain(..)
613 .map(
614 |out| -> Result<(u64, Result<Value, Error>), InvalidResponse> {
615 match out {
616 Output::Success(Success {
617 result,
618 id: Id::Num(id),
619 ..
620 }) => Ok((id, Ok(result))),
621 Output::Failure(Failure {
622 error,
623 id: Id::Num(id),
624 ..
625 }) => Ok((id, Err(error))),
626 _ => Err(InvalidResponse::ContainsNonNumericId),
627 }
628 },
629 )
630 .collect::<Result<BTreeMap<u64, Result<Value, Error>>, InvalidResponse>>()?;
631 Ok(Self { outputs })
632 }
633
634 pub fn remove(&mut self, id: u64) -> Option<Result<Value, Error>> {
636 self.outputs.remove(&id)
637 }
638}
639
640pub struct Tracker<T>
643where
644 T: Deserialize<'static>,
645{
646 id: u64,
647 _spook: PhantomData<*const T>,
648}
649
650impl<T> Tracker<T>
651where
652 T: Deserialize<'static>,
653{
654 pub fn get_return(&self, response: &mut Response) -> Result<T, ResponseFail> {
658 let result = response
659 .remove(self.id)
660 .ok_or(ResponseFail::ResultNotFound)?;
661 let raw_return = result.map_err(ResponseFail::RpcError)?;
662 <T>::deserialize(raw_return).map_err(|_| ResponseFail::InvalidResponse)
663 }
664}
665
666#[cfg(test)]
667mod test {
668 mod easy_jsonrpc {
669 pub use crate::*;
670 }
671 use super::{Handler, InvalidArgs, MaybeReply, Params};
672 use jsonrpc_core;
673 use serde_json::{json, Value};
674
675 #[easy_jsonrpc::rpc]
676 pub trait Adder {
677 fn checked_add(&self, a: isize, b: isize) -> Option<isize>;
678 fn wrapping_add(&self, a: isize, b: isize) -> isize;
679 fn greet(&self) -> String;
680 fn swallow(&self);
681 fn repeat_list(&self, lst: Vec<usize>) -> Vec<usize>;
682 fn fail(&self) -> Result<isize, String>;
683 fn succeed(&self) -> Result<isize, String>;
684 fn echo_ref(&self, a: &isize) -> isize;
685 }
686
687 struct AdderImpl;
688 impl Adder for AdderImpl {
689 fn checked_add(&self, a: isize, b: isize) -> Option<isize> {
690 a.checked_add(b)
691 }
692
693 fn wrapping_add(&self, a: isize, b: isize) -> isize {
694 a.wrapping_add(b)
695 }
696
697 fn greet(&self) -> String {
698 "hello".into()
699 }
700
701 fn swallow(&self) {}
702
703 fn repeat_list(&self, lst: Vec<usize>) -> Vec<usize> {
704 let mut ret = lst.clone();
705 ret.extend(lst);
706 ret
707 }
708
709 fn fail(&self) -> Result<isize, String> {
710 Err("tada!".into())
711 }
712
713 fn succeed(&self) -> Result<isize, String> {
714 Ok(1)
715 }
716
717 fn echo_ref(&self, a: &isize) -> isize {
718 *a
719 }
720 }
721
722 fn assert_adder_response(request: Value, response: Value) {
723 assert_eq!(
724 (&AdderImpl {} as &dyn Adder)
725 .handle_request(request)
726 .as_option()
727 .unwrap(),
728 response
729 );
730 }
731
732 fn error_code(request: Value) -> jsonrpc_core::ErrorCode {
733 let raw_response = (&AdderImpl {} as &dyn Adder)
734 .handle_request(request)
735 .as_option()
736 .unwrap();
737 let response: jsonrpc_core::Response = serde_json::from_value(raw_response).unwrap();
738 match response {
739 jsonrpc_core::Response::Single(jsonrpc_core::Output::Failure(
740 jsonrpc_core::Failure { error, .. },
741 )) => error.code,
742 _ => panic!(),
743 }
744 }
745
746 #[test]
747 fn batch() {
748 assert_adder_response(
749 json!([
750 {
751 "jsonrpc": "2.0",
752 "method": "wrapping_add",
753 "params": [1, 1],
754 "id": 1
755 },
756 {
757 "jsonrpc": "2.0",
758 "method": "wrapping_add",
759 "params": [1, 2],
760 "id": 2
761 },
762 {
763 "jsonrpc": "2.0",
764 "method": "wrapping_add",
765 "params": [1, 3],
766 "id": null
767 },
768 {
769 "jsonrpc": "2.0",
770 "method": "wrapping_add",
771 "params": [1, 4],
772 },
773 ]),
774 json!([
775 {
776 "jsonrpc": "2.0",
777 "result": 2,
778 "id": 1
779 },
780 {
781 "jsonrpc": "2.0",
782 "result": 3,
783 "id": 2
784 },
785 {
786 "jsonrpc": "2.0",
787 "result": 4,
788 "id": null
789 }
790 ]),
791 );
792 }
793
794 #[test]
795 fn positional_args() {
796 assert_adder_response(
797 json!({
798 "jsonrpc": "2.0",
799 "method": "wrapping_add",
800 "params": [1, 1],
801 "id": 1
802 }),
803 json!({
804 "jsonrpc": "2.0",
805 "result": 2,
806 "id": 1
807 }),
808 );
809 }
810
811 #[test]
812 fn string_id() {
813 assert_adder_response(
814 json!({
815 "jsonrpc": "2.0",
816 "method": "wrapping_add",
817 "params": [1, 1],
818 "id": "jfjfks sasdfk"
819 }),
820 json!({
821 "jsonrpc": "2.0",
822 "result": 2,
823 "id": "jfjfks sasdfk"
824 }),
825 );
826 assert_adder_response(
827 json!({
828 "jsonrpc": "2.0",
829 "method": "wrapping_add",
830 "params": [1, 1],
831 "id": ""
832 }),
833 json!({
834 "jsonrpc": "2.0",
835 "result": 2,
836 "id": ""
837 }),
838 );
839 }
840
841 #[test]
842 fn named_args() {
843 assert_adder_response(
844 json!({
845 "jsonrpc": "2.0",
846 "method": "wrapping_add",
847 "params": {
848 "a": 1,
849 "b": 1
850 },
851 "id": 1
852 }),
853 json!({
854 "jsonrpc": "2.0",
855 "result": 2,
856 "id": 1
857 }),
858 );
859 }
860
861 #[test]
862 fn null_args() {
863 let response = json!({
864 "jsonrpc": "2.0",
865 "result": "hello",
866 "id": 1
867 });
868 assert_adder_response(
869 json!({
870 "jsonrpc": "2.0",
871 "method": "greet",
872 "params": {},
873 "id": 1
874 }),
875 response.clone(),
876 );
877 assert_adder_response(
878 json!({
879 "jsonrpc": "2.0",
880 "method": "greet",
881 "params": [],
882 "id": 1
883 }),
884 response.clone(),
885 );
886 assert_adder_response(
887 json!({
888 "jsonrpc": "2.0",
889 "method": "greet",
890 "params": null,
891 "id": 1
892 }),
893 response.clone(),
894 );
895 assert_adder_response(
896 json!({
897 "jsonrpc": "2.0",
898 "method": "greet",
899 "id": 1
900 }),
901 response.clone(),
902 );
903 }
904
905 #[test]
906 fn null_return() {
907 assert_adder_response(
908 json!({
909 "jsonrpc": "2.0",
910 "method": "swallow",
911 "params": [],
912 "id": 1
913 }),
914 json!({
915 "jsonrpc": "2.0",
916 "result": null,
917 "id": 1
918 }),
919 );
920 }
921
922 #[test]
923 fn incorrect_method_name() {
924 assert_eq!(
925 error_code(json!({
926 "jsonrpc": "2.0",
927 "method": "nonexist",
928 "params": [],
929 "id": 1
930 })),
931 jsonrpc_core::ErrorCode::MethodNotFound,
932 );
933 }
934
935 #[test]
936 fn incorrect_args() {
937 assert_eq!(
938 error_code(json!({
939 "jsonrpc": "2.0",
940 "method": "wrapping_add",
941 "params": [],
942 "id": 1
943 })),
944 jsonrpc_core::ErrorCode::InvalidParams,
945 );
946 assert_eq!(
947 error_code(json!({
948 "jsonrpc": "2.0",
949 "method": "wrapping_add",
950 "params": {
951 "notanarg": 1,
952 "notarg": 1
953 },
954 "id": 1
955 })),
956 jsonrpc_core::ErrorCode::InvalidParams,
957 );
958 assert_eq!(
959 error_code(json!({
960 "jsonrpc": "2.0",
961 "method": "wrapping_add",
962 "params": [[], []],
963 "id": 1
964 })),
965 jsonrpc_core::ErrorCode::InvalidParams,
966 );
967 }
968
969 #[test]
970 fn complex_type() {
971 assert_adder_response(
972 json!({
973 "jsonrpc": "2.0",
974 "method": "repeat_list",
975 "params": [[1, 2, 3]],
976 "id": 1
977 }),
978 json!({
979 "jsonrpc": "2.0",
980 "result": [1, 2, 3, 1, 2, 3],
981 "id": 1
982 }),
983 );
984 assert_eq!(
985 error_code(json!({
986 "jsonrpc": "2.0",
987 "method": "repeat_list",
988 "params": [[1], [12]],
989 "id": 1
990 }),),
991 jsonrpc_core::ErrorCode::InvalidParams,
992 );
993 assert_adder_response(
994 json!({
995 "jsonrpc": "2.0",
996 "method": "fail",
997 "params": [],
998 "id": 1
999 }),
1000 json!({
1001 "jsonrpc": "2.0",
1002 "result": {
1003 "Err": "tada!"
1004 },
1005 "id": 1
1006 }),
1007 );
1008 assert_adder_response(
1009 json!({
1010 "jsonrpc": "2.0",
1011 "method": "succeed",
1012 "params": [],
1013 "id": 1
1014 }),
1015 json!({
1016 "jsonrpc": "2.0",
1017 "result": {
1018 "Ok": 1
1019 },
1020 "id": 1
1021 }),
1022 );
1023 }
1024
1025 #[test]
1026 fn notification() {
1027 let request = json!({
1028 "jsonrpc": "2.0",
1029 "method": "succeed",
1030 "params": []
1031 });
1032 assert_eq!(
1033 (&AdderImpl {} as &dyn Adder).handle_request(request),
1034 MaybeReply::DontReply
1035 );
1036 }
1037
1038 #[test]
1039 fn adder_client_non_macro() {
1040 #[easy_jsonrpc::rpc]
1041 trait Adder {
1042 fn checked_add(&self, a: usize, b: usize) -> Option<usize> {
1043 a.checked_add(b)
1044 }
1045 }
1046
1047 #[allow(non_camel_case_types)]
1048 pub enum adder_client {}
1049 impl adder_client {
1050 fn checked_add(
1051 arg0: usize,
1052 arg1: usize,
1053 ) -> Result<
1054 easy_jsonrpc::BoundMethod<'static, Option<usize>>,
1055 easy_jsonrpc::ArgSerializeError,
1056 > {
1057 Ok(easy_jsonrpc::BoundMethod::new(
1058 "checked_add",
1059 vec![
1060 serde_json::to_value(arg0).map_err(|_| easy_jsonrpc::ArgSerializeError)?,
1061 serde_json::to_value(arg1).map_err(|_| easy_jsonrpc::ArgSerializeError)?,
1062 ],
1063 ))
1064 }
1065 }
1066
1067 impl Adder for () {}
1068 let handler = &() as &dyn Adder;
1069
1070 let bind = adder_client::checked_add(1, 2).unwrap();
1071 let (call, tracker) = bind.call();
1072 let raw_response = handler
1073 .handle_request(call.as_request())
1074 .as_option()
1075 .unwrap();
1076 let mut response = easy_jsonrpc::Response::from_json_response(raw_response).unwrap();
1077 let result: Option<usize> = tracker.get_return(&mut response).unwrap();
1078 assert_eq!(result, Some(3));
1079
1080 assert_eq!(
1081 handler.handle_request(
1082 adder_client::checked_add(1, 2)
1083 .unwrap()
1084 .notification()
1085 .as_request()
1086 ),
1087 MaybeReply::DontReply
1088 );
1089 }
1090
1091 #[test]
1092 fn adder_client_with_macro() {
1093 #[easy_jsonrpc::rpc]
1094 trait Adder {
1095 fn checked_add(&self, a: usize, b: usize) -> Option<usize> {
1096 a.checked_add(b)
1097 }
1098 }
1099
1100 impl Adder for () {}
1101 let handler = &() as &dyn Adder;
1102
1103 let bind = adder::checked_add(1, 2).unwrap();
1104 let (call, tracker) = bind.call();
1105 let raw_response = handler
1106 .handle_request(call.as_request())
1107 .as_option()
1108 .unwrap();
1109 let mut response = easy_jsonrpc::Response::from_json_response(raw_response).unwrap();
1110 let result: Option<usize> = tracker.get_return(&mut response).unwrap();
1111 assert_eq!(result, Some(3));
1112
1113 let call = adder::checked_add(1, 2).unwrap();
1114 assert_eq!(
1115 handler.handle_request(call.notification().as_request()),
1116 MaybeReply::DontReply
1117 );
1118 }
1119
1120 #[test]
1121 fn client_with_reference_args() {
1122 let handler = &AdderImpl {} as &dyn Adder;
1123
1124 let bind = adder::echo_ref(&2).unwrap();
1125 let (call, tracker) = bind.call();
1126 let raw_response = handler
1127 .handle_request(call.as_request())
1128 .as_option()
1129 .unwrap();
1130 let mut response = easy_jsonrpc::Response::from_json_response(raw_response).unwrap();
1131 assert_eq!(tracker.get_return(&mut response).unwrap(), 2);
1132
1133 let call = adder::echo_ref(&2).unwrap();
1134 assert_eq!(
1135 handler.handle_request(call.notification().as_request()),
1136 MaybeReply::DontReply
1137 );
1138 }
1139
1140 #[test]
1141 fn response_double_get() {
1142 let handler = &AdderImpl as &dyn Adder;
1143 use easy_jsonrpc::Call;
1144 let bind0 = adder::checked_add(0, 0).unwrap();
1145 let (call0, tracker0) = bind0.call();
1146 let bind1 = adder::checked_add(1, 0).unwrap();
1147 let (call1, tracker1) = bind1.call();
1148 let bind2 = adder::wrapping_add(1, 1).unwrap();
1149 let (call2, tracker2) = bind2.call();
1150 let json_request = Call::batch_request(&[call0, call1, call2]);
1151 let json_response = handler.handle_request(json_request).as_option().unwrap();
1152 let mut response = easy_jsonrpc::Response::from_json_response(json_response).unwrap();
1153 assert_eq!(tracker0.get_return(&mut response).unwrap(), Some(0));
1154 assert_eq!(tracker2.get_return(&mut response).unwrap(), 2);
1155
1156 assert_eq!(tracker1.get_return(&mut response), Ok(Some(1)));
1158 assert_eq!(
1159 tracker1.get_return(&mut response),
1160 Err(easy_jsonrpc::ResponseFail::ResultNotFound)
1161 );
1162 }
1163
1164 #[test]
1165 fn local_types() {
1166 #[derive(serde::Serialize, serde::Deserialize)]
1167 pub struct Foo;
1168
1169 #[easy_jsonrpc::rpc]
1170 trait Bar {
1171 fn frob(&self) -> Foo;
1172 fn borf(&self, foo: Foo);
1173 }
1174 }
1175
1176 #[test]
1178 fn wrong_num_arg_err() {
1179 assert_adder_response(
1180 json!({
1181 "jsonrpc": "2.0",
1182 "method": "checked_add",
1183 "params": [1],
1184 "id": 1
1185 }),
1186 json!({
1187 "error": {
1188 "code": -32602,
1189 "message": "WrongNumberOfArgs. Expected 2. Actual 1"
1190 },
1191 "id": 1,
1192 "jsonrpc": "2.0"
1193 }),
1194 );
1195
1196 let res = Params::from_rc_params(jsonrpc_core::Params::Array(vec![
1197 json!(1),
1198 json!(2),
1199 json!(3),
1200 ]))
1201 .get_rpc_args(&["arg_one", "arg_two"]);
1202 assert_eq!(
1203 res,
1204 Err(InvalidArgs::WrongNumberOfArgs {
1205 expected: 2,
1206 actual: 3
1207 })
1208 );
1209 }
1210}