1use anyhow::{anyhow, Result};
2use serde::de::DeserializeOwned;
3use serde_json::Value;
4
5#[derive(Debug, Clone)]
6pub struct RpcObject(pub Value);
7
8pub type RequestId = u64;
9
10#[derive(Debug, Clone, PartialEq, Eq)]
11pub enum Call<N, R> {
13 Request(RequestId, R),
15 Notification(N),
17}
18
19impl RpcObject {
20 pub fn get_id(&self) -> Option<RequestId> {
21 self.0.get("id").and_then(Value::as_u64)
22 }
23
24 pub fn is_response(&self) -> bool {
25 self.0.get("id").is_some() && self.0.get("method").is_none()
26 }
27
28 pub fn into_rpc<N, R>(self) -> Result<Call<N, R>>
29 where
30 N: DeserializeOwned,
31 R: DeserializeOwned,
32 {
33 let id = self.get_id();
34 match id {
35 Some(id) => match serde_json::from_value::<R>(self.0) {
36 Ok(resp) => Ok(Call::Request(id, resp)),
37 Err(err) => Err(anyhow!(err)),
38 },
39 None => {
40 let result = serde_json::from_value::<N>(self.0)?;
41 Ok(Call::Notification(result))
42 }
43 }
44 }
45
46 pub fn into_response(mut self) -> Result<Result<Value, Value>, String> {
47 let _ = self
48 .get_id()
49 .ok_or_else(|| "Response requires 'id' field.".to_string())?;
50
51 if self.0.get("result").is_some() == self.0.get("error").is_some() {
52 return Err("RPC response must contain exactly one of\
53 'error' or 'result' fields."
54 .into());
55 }
56 let result = self.0.as_object_mut().and_then(|obj| obj.remove("result"));
57
58 match result {
59 Some(r) => Ok(Ok(r)),
60 None => {
61 let error = self
62 .0
63 .as_object_mut()
64 .and_then(|obj| obj.remove("error"))
65 .unwrap();
66 Ok(Err(error))
67 }
68 }
69 }
70}
71
72impl From<Value> for RpcObject {
73 fn from(v: Value) -> RpcObject {
74 RpcObject(v)
75 }
76}