1#![deny(missing_docs)]
47
48extern crate jsonrpc_core as rpc;
49
50#[derive(Default, Debug)]
52pub struct Options {
53 pub no_print: bool,
55}
56
57#[derive(Default, Debug)]
58pub struct Rpc {
60 pub io: rpc::IoHandler,
62 pub options: Options,
64}
65
66pub enum Encoding {
68 Compact,
70 Pretty,
72}
73
74impl From<rpc::IoHandler> for Rpc {
75 fn from(io: rpc::IoHandler) -> Self {
76 Rpc {
77 io,
78 ..Default::default()
79 }
80 }
81}
82
83impl Rpc {
84 pub fn new<D>(delegate: D) -> Self
86 where
87 D: IntoIterator<Item = (String, rpc::RemoteProcedure<()>)>,
88 {
89 let mut io = rpc::IoHandler::new();
90 io.extend_with(delegate);
91 io.into()
92 }
93
94 pub fn request<T>(&self, method: &str, params: &T) -> String
96 where
97 T: serde::Serialize,
98 {
99 self.make_request(method, params, Encoding::Pretty)
100 }
101
102 pub fn make_request<T>(&self, method: &str, params: &T, encoding: Encoding) -> String
104 where
105 T: serde::Serialize,
106 {
107 use self::rpc::types::response;
108
109 let request = format!(
110 "{{ \"jsonrpc\":\"2.0\", \"id\": 1, \"method\": \"{}\", \"params\": {} }}",
111 method,
112 serde_json::to_string_pretty(params).expect("Serialization should be infallible."),
113 );
114
115 let response = self
116 .io
117 .handle_request_sync(&request)
118 .expect("We are sending a method call not notification.");
119
120 let extracted = match rpc::serde_from_str(&response).expect("We will always get a single output.") {
122 response::Output::Success(response::Success { result, .. }) => match encoding {
123 Encoding::Compact => serde_json::to_string(&result),
124 Encoding::Pretty => serde_json::to_string_pretty(&result),
125 },
126 response::Output::Failure(response::Failure { error, .. }) => match encoding {
127 Encoding::Compact => serde_json::to_string(&error),
128 Encoding::Pretty => serde_json::to_string_pretty(&error),
129 },
130 }
131 .expect("Serialization is infallible; qed");
132
133 println!("\n{}\n --> {}\n", request, extracted);
134
135 extracted
136 }
137}
138
139#[cfg(test)]
140mod tests {
141 use super::*;
142
143 #[test]
144 fn should_test_request_is_pretty() {
145 let rpc = {
147 let mut io = rpc::IoHandler::new();
148 io.add_sync_method("test_method", |_| Ok(rpc::Value::Array(vec![5.into(), 10.into()])));
149 Rpc::from(io)
150 };
151
152 assert_eq!(rpc.request("test_method", &[5u64]), "[\n 5,\n 10\n]");
154 }
155
156 #[test]
157 fn should_test_make_request_compact() {
158 let rpc = {
160 let mut io = rpc::IoHandler::new();
161 io.add_sync_method("test_method", |_| Ok(rpc::Value::Array(vec![5.into(), 10.into()])));
162 Rpc::from(io)
163 };
164
165 assert_eq!(rpc.make_request("test_method", &[5u64], Encoding::Compact), "[5,10]");
167 }
168}