ezjsonrpc/
lib.rs

1#![recursion_limit = "2048"]
2
3#[macro_use]
4extern crate serde_derive;
5
6pub use ezjsonrpc_macros::*;
7
8use std::borrow::{Borrow, Cow};
9
10use futures::{
11    future::{ok as future_ok, Either as EitherFuture},
12    Future
13};
14
15use proc_macro_hack::proc_macro_hack;
16use serde::{Deserialize, Deserializer, Serialize, Serializer};
17use serde_json::Value;
18
19#[proc_macro_hack]
20pub use ezjsonrpc_macros::methods;
21
22#[derive(Default, Debug)]
23pub struct V2;
24
25impl Serialize for V2 {
26    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
27    where S: Serializer {
28        "2.0".serialize(serializer)
29    }
30}
31
32impl<'de> Deserialize<'de> for V2 {
33    fn deserialize<D>(deserializer: D) -> Result<V2, D::Error>
34    where D: Deserializer<'de> {
35        let s: std::borrow::Cow<str> = Deserialize::deserialize(deserializer)?;
36        if s == "2.0" {
37            Ok(V2)
38        } else {
39            Err(serde::de::Error::custom("Could not deserialize V2"))
40        }
41    }
42}
43
44#[derive(Debug, Clone)]
45pub enum Id {
46    Num(i64),
47    Str(Cow<'static, str>),
48    Null
49}
50
51impl From<i64> for Id {
52    fn from(t: i64) -> Self { Id::Num(t) }
53}
54
55impl From<String> for Id {
56    fn from(t: String) -> Self { Id::Str(t.into()) }
57}
58
59impl From<&'static str> for Id {
60    fn from(t: &'static str) -> Self { Id::Str(t.into()) }
61}
62
63impl Default for Id {
64    fn default() -> Id { Id::Null }
65}
66
67impl Serialize for Id {
68    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
69    where S: Serializer {
70        match *self {
71            Id::Num(ref num) => num.serialize(serializer),
72            Id::Str(ref s) => s.serialize(serializer),
73            Id::Null => serializer.serialize_none()
74        }
75    }
76}
77
78impl<'de> Deserialize<'de> for Id {
79    fn deserialize<D>(deserializer: D) -> Result<Id, D::Error>
80    where D: Deserializer<'de> {
81        #[derive(Serialize, Deserialize)]
82        #[serde(untagged)]
83        pub enum PresentId {
84            Num(i64),
85            Str(Cow<'static, str>)
86        }
87
88        #[derive(Serialize, Deserialize)]
89        pub struct WrappedPresentId(Option<PresentId>);
90
91        let out = match WrappedPresentId::deserialize(deserializer)? {
92            WrappedPresentId(Some(PresentId::Num(num))) => Id::Num(num),
93            WrappedPresentId(Some(PresentId::Str(s))) => Id::Str(s),
94            WrappedPresentId(None) => Id::Null
95        };
96
97        Ok(out)
98    }
99}
100
101#[derive(Serialize, Deserialize, Debug)]
102#[serde(untagged)]
103pub enum RequestObject {
104    Request { jsonrpc: V2, method: Cow<'static, str>, params: Option<Value>, id: Id },
105    Notification { jsonrpc: V2, method: Cow<'static, str>, params: Option<Value> }
106}
107
108impl RequestObject {
109    pub fn with_id<I: Into<Id>>(self, id: I) -> Self {
110        match self {
111            RequestObject::Request { jsonrpc, method, params, .. } => {
112                RequestObject::Request { jsonrpc, method, params, id: id.into() }
113            }
114            RequestObject::Notification { jsonrpc, method, params } => {
115                RequestObject::Request { jsonrpc, method, params, id: id.into() }
116            }
117        }
118    }
119
120    pub fn with_method<I: Into<Cow<'static, str>>>(self, method: I) -> Self {
121        match self {
122            RequestObject::Request { jsonrpc, params, id, .. } => {
123                RequestObject::Request { jsonrpc, method: method.into(), params, id }
124            }
125            RequestObject::Notification { jsonrpc, params, .. } => {
126                RequestObject::Notification { jsonrpc, method: method.into(), params }
127            }
128        }
129    }
130
131    pub fn with_params<I: Into<Value>>(self, params: I) -> Self {
132        match self {
133            RequestObject::Request { jsonrpc, method, id, .. } => {
134                RequestObject::Request { jsonrpc, method, params: Some(params.into()), id }
135            }
136            RequestObject::Notification { jsonrpc, method, .. } => {
137                RequestObject::Notification { jsonrpc, method, params: Some(params.into()) }
138            }
139        }
140    }
141
142    pub fn request() -> Self {
143        RequestObject::Request { jsonrpc: V2, method: "".into(), params: None, id: Id::Null }
144    }
145
146    pub fn notification() -> Self {
147        RequestObject::Notification { jsonrpc: V2, method: "".into(), params: None }
148    }
149}
150
151#[derive(Serialize, Deserialize, Default, Debug)]
152pub struct Error {
153    pub code: i64,
154    pub message: String,
155    pub data: Option<Value>
156}
157
158impl Error {
159    pub fn invalid_params() -> Self {
160        Error { code: -32602, message: "Invalid params".into(), data: None }
161    }
162
163    pub fn method_not_found() -> Self {
164        Error { code: -32601, message: "Method not found".into(), data: None }
165    }
166
167    pub fn parse_error() -> Self {
168        Error { code: -32700, message: "Parse error".into(), data: None }
169    }
170
171    pub fn invalid_request() -> Self {
172        Error { code: -32600, message: "Invalid Request".into(), data: None }
173    }
174}
175
176impl<T: std::fmt::Display> From<T> for Error {
177    fn from(t: T) -> Self { Error { message: format!("{}", t), ..Error::default() } }
178}
179
180#[derive(Serialize, Deserialize, Debug)]
181#[serde(untagged)]
182pub enum Response {
183    Result { jsonrpc: V2, result: Value, id: Id },
184    Error { jsonrpc: V2, error: Error, id: Id },
185    Empty
186}
187
188impl Response {
189    fn result(result: Value, opt_id: Option<Id>) -> Self {
190        opt_id
191            .map(|id| Response::Result { jsonrpc: V2, result, id })
192            .unwrap_or_else(|| Response::Empty)
193    }
194
195    fn error(error: Error, opt_id: Option<Id>) -> Self {
196        opt_id
197            .map(|id| Response::Error { jsonrpc: V2, error, id })
198            .unwrap_or_else(|| Response::Empty)
199    }
200}
201
202#[derive(Deserialize)]
203#[serde(untagged)]
204pub enum OneOrManyValues {
205    Many(Vec<Value>),
206    One(Value)
207}
208
209#[derive(Serialize)]
210#[serde(untagged)]
211pub enum ResponseObjects {
212    One(Response),
213    Many(Vec<Response>),
214    None
215}
216
217impl From<Response> for ResponseObjects {
218    fn from(t: Response) -> Self {
219        match t {
220            Response::Empty => ResponseObjects::None,
221            t => ResponseObjects::One(t)
222        }
223    }
224}
225
226impl From<Vec<Response>> for ResponseObjects {
227    fn from(t: Vec<Response>) -> Self {
228        let t = t
229            .into_iter()
230            .filter_map(|r| match r {
231                Response::Empty => None,
232                t => Some(t)
233            })
234            .collect::<Vec<_>>();
235        if t.is_empty() {
236            return ResponseObjects::None;
237        }
238        ResponseObjects::Many(t)
239    }
240}
241
242pub trait Service {
243    fn call(&self, req: RequestObject) -> Box<Future<Item = ResponseObjects, Error = ()> + Send>;
244    fn batch(
245        &self,
246        requests: Vec<RequestObject>
247    ) -> Box<Future<Item = ResponseObjects, Error = ()> + Send>;
248    fn request_from_bytes(
249        &self,
250        bytes: &[u8]
251    ) -> Box<Future<Item = ResponseObjects, Error = ()> + Send>;
252}
253
254type Method<T> = fn(&T, Option<Value>) -> Box<Future<Item = Value, Error = Error> + Send>;
255type MethodMatcher<T> = fn(&str) -> Option<Method<T>>;
256
257pub struct Server<T, S> {
258    state: S,
259    method_matcher: MethodMatcher<T>
260}
261
262impl<T, S> Server<T, S>
263where S: Borrow<T>
264{
265    fn empty_matcher(_: &str) -> Option<Method<T>> { None }
266
267    pub fn new(state: S) -> Self { Server { state, method_matcher: Self::empty_matcher } }
268
269    pub fn with_methods(self, method_matcher: MethodMatcher<T>) -> Self {
270        let Server { state, .. } = self;
271
272        Server { state, method_matcher }
273    }
274
275    fn inner_call(&self, req: RequestObject) -> impl Future<Item = Response, Error = ()> {
276        let (opt_id, method, params) = match req {
277            RequestObject::Notification { method, params, .. } => (None, method, params),
278            RequestObject::Request { method, params, id, .. } => (Some(id), method, params)
279        };
280
281        if let Some(method) = (self.method_matcher)(method.as_ref()) {
282            let rt = method(self.state.borrow(), params).then(|fut| match fut {
283                Ok(val) => future_ok(Response::result(val, opt_id)),
284                Err(e) => future_ok(Response::error(e, opt_id))
285            });
286            EitherFuture::A(rt)
287        } else {
288            let rt = future_ok(Response::error(Error::method_not_found(), opt_id));
289            EitherFuture::B(rt)
290        }
291    }
292
293    fn inner_batch(
294        &self,
295        requests: Vec<RequestObject>
296    ) -> impl Future<Item = Vec<Response>, Error = ()>
297    {
298        use futures::stream::Stream;
299        futures::stream::futures_unordered(requests.into_iter().map(|r| self.inner_call(r)))
300            .collect()
301    }
302}
303
304impl<T: 'static, S: 'static> Service for Server<T, S>
305where S: Borrow<T>
306{
307    fn call(&self, req: RequestObject) -> Box<Future<Item = ResponseObjects, Error = ()> + Send> {
308        Box::new(self.inner_call(req).map(ResponseObjects::from))
309    }
310
311    fn batch(
312        &self,
313        requests: Vec<RequestObject>
314    ) -> Box<Future<Item = ResponseObjects, Error = ()> + Send>
315    {
316        Box::new(self.inner_batch(requests).map(ResponseObjects::from))
317    }
318
319    fn request_from_bytes(
320        &self,
321        bytes: &[u8]
322    ) -> Box<Future<Item = ResponseObjects, Error = ()> + Send>
323    {
324        if let Ok(mr) = serde_json::from_slice::<OneOrManyValues>(bytes) {
325            match mr {
326                OneOrManyValues::One(val) => {
327                    return Box::new(match serde_json::from_value::<RequestObject>(val) {
328                        Ok(rn) => EitherFuture::A(self.call(rn)),
329                        Err(_) => EitherFuture::B(future_ok(
330                            Response::error(Error::invalid_request(), Some(Id::Null)).into()
331                        ))
332                    });
333                }
334                OneOrManyValues::Many(vals) => {
335                    if vals.is_empty() {
336                        return Box::new(future_ok(
337                            Response::error(Error::invalid_request(), Some(Id::Null)).into()
338                        ));
339                    }
340
341                    let (okays, errs) = vals
342                        .into_iter()
343                        .map(serde_json::from_value::<RequestObject>)
344                        .partition::<Vec<Result<RequestObject, serde_json::Error>>, _>(|x| {
345                            x.is_ok()
346                        });
347
348                    let errs = errs
349                        .into_iter()
350                        .map(|_| Response::error(Error::invalid_request(), Some(Id::Null)))
351                        .collect::<Vec<_>>();
352
353                    return Box::new(
354                        self.inner_batch(okays.into_iter().flat_map(|x| x).collect()).map(
355                            |mut rs| {
356                                rs.extend(errs);
357                                rs.into()
358                            }
359                        )
360                    );
361                }
362            }
363        }
364
365        Box::new(future_ok(Response::error(Error::parse_error(), Some(Id::Null)).into()))
366    }
367}
368
369pub mod utils {
370
371    use super::Error;
372    use futures::{Future, IntoFuture};
373
374    pub fn finish_callable<I, S, E>(
375        i: I
376    ) -> Box<Future<Item = serde_json::Value, Error = Error> + Send>
377    where
378        I: IntoFuture<Item = S, Error = E> + 'static + Send,
379        I::Future: 'static + Send,
380        S: serde::Serialize,
381        E: Into<Error> {
382        let rt = i.into_future().map_err(|e| e.into()).and_then(|r| {
383            serde_json::to_value(r).into_future().map_err(|e| Error {
384                code: 1,
385                message: e.to_string(),
386                data: None
387            })
388        });
389        Box::new(rt)
390    }
391}
392
393pub mod exp {
394    pub use futures;
395    pub use serde;
396    pub use serde_json;
397}