1use serde::{Deserialize, Deserializer, Serialize, de::Error};
2use serde_json::{Value, json, to_value};
3
4use super::{ErrorCode, Id};
5
6#[derive(Debug, Clone, PartialEq, Eq, Hash)]
15pub enum Response {
16 Ok(Id, Value),
19 Err(Id, ErrorCode, String, Value),
22}
23
24impl Serialize for Response {
25 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
26 where
27 S: serde::Serializer,
28 {
29 #[derive(Serialize)]
30 struct Res<'a> {
31 id: &'a Id,
32 result: Option<&'a Value>,
33 error: Option<Value>,
34 }
35 if let Response::Ok(id, value) = self {
36 Res { id, result: Some(value), error: None }.serialize(serializer)
37 } else if let Response::Err(id, code, message, value) = self {
38 Res {
39 id,
40 result: None,
41 error: Some(json!({
42 "code": code, "message": message, "data": value
43 })),
44 }
45 .serialize(serializer)
46 } else {
47 unreachable!()
48 }
49 }
50}
51
52impl<'de> Deserialize<'de> for Response {
53 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
54 where
55 D: Deserializer<'de>,
56 {
57 #[derive(Deserialize)]
58 struct Err {
59 code: i32,
60 message: String,
61 #[serde(default = "serde_json::Value::default")]
62 data: Value,
63 }
64
65 #[derive(Deserialize)]
66 struct Res {
67 id: Id,
68 result: Option<Value>,
69 error: Option<Err>,
70 }
71
72 let res = Res::deserialize(deserializer)?;
73 if let Some(result) = res.result {
74 if res.error.is_some() {
75 Err(Error::duplicate_field("error"))?
76 }
77 Ok(Response::Ok(res.id, result))
78 } else if let Some(error) = res.error {
79 if res.result.is_some() {
80 Err(Error::duplicate_field("result"))?
81 }
82 Ok(Response::Err(res.id, error.code.into(), error.message, error.data))
83 } else {
84 Err(Error::missing_field("result"))?
85 }
86 }
87}
88
89impl Response {
90 pub fn new_ok<T>(id: Id, result: T) -> Response
91 where
92 T: Serialize,
93 {
94 Response::Ok(id, to_value(result).unwrap())
95 }
96
97 pub fn new_err<T>(id: Id, error_code: ErrorCode, message: String, value: T) -> Response
98 where
99 T: Serialize,
100 {
101 Response::Err(id, error_code, message, to_value(value).unwrap())
102 }
103}
104
105#[cfg(test)]
106mod tests {
107 use serde_json::{from_str, json};
108
109 use super::*;
110
111 #[test]
112 fn test_response_deserialize() {
113 assert_eq!(from_str::<Response>(r#"{"id":3, "result":7}"#).unwrap(), Response::Ok(3.into(), json!(7)));
114 assert_eq!(
115 from_str::<Response>(r#"{"id":4, "result":["a", "b"]}"#).unwrap(),
116 Response::Ok(4.into(), json!(["a", "b"]))
117 );
118 assert_eq!(
119 from_str::<Response>(r#"{"id":"a", "error":{"code": -32700, "message": "Parse error"}}"#).unwrap(),
120 Response::Err("a".into(), ErrorCode::ParseError, "Parse error".into(), Value::Null)
121 );
122 assert_eq!(
123 from_str::<Response>(
124 r#"{"id":"foo", "error":{"code": -32600, "message": "Invalid Request", "data": ["foo"]}}"#
125 )
126 .unwrap(),
127 Response::Err("foo".into(), ErrorCode::InvalidRequest, "Invalid Request".into(), json!(["foo"]))
128 );
129 }
130
131 #[test]
132 fn test_response_deserialize_error() {
133 assert!(from_str::<Response>(r#"{"id":3}"#).is_err());
135
136 assert!(from_str::<Response>(r#"{"id":3, "error":{}}"#).is_err());
138
139 assert!(from_str::<Response>(r#"{"id":3, "error":{"code":0}}"#).is_err());
141
142 assert!(from_str::<Response>(r#"{"id":3, "error":{"message":""}}"#).is_err());
144
145 assert!(from_str::<Response>(r#"{"id":3, "error":{"code":0, "message": ""}, "result":7}"#).is_err());
147 assert!(from_str::<Response>(r#"{"id":3, "result":7, "error":{"code":0, "message": ""}}"#).is_err());
148 }
149}