1use std::borrow::Cow;
31
32use crate::{
33 Params,
34 params::{Id, TwoPointZero},
35};
36use http::Extensions;
37use serde::{Deserialize, Serialize};
38use serde_json::value::RawValue;
39
40#[derive(Serialize, Deserialize, Debug, Clone)]
42pub struct Request<'a> {
43 pub jsonrpc: TwoPointZero,
45 #[serde(borrow)]
47 pub id: Id<'a>,
48 #[serde(borrow)]
50 pub method: Cow<'a, str>,
51 #[serde(borrow)]
53 #[serde(skip_serializing_if = "Option::is_none")]
54 pub params: Option<Cow<'a, RawValue>>,
55 #[serde(skip)]
57 pub extensions: Extensions,
58}
59
60impl<'a> Request<'a> {
61 pub fn borrowed(method: &'a str, params: Option<&'a RawValue>, id: Id<'a>) -> Self {
63 Self {
64 jsonrpc: TwoPointZero,
65 id,
66 method: Cow::Borrowed(method),
67 params: params.map(Cow::Borrowed),
68 extensions: Extensions::new(),
69 }
70 }
71
72 pub fn owned(method: String, params: Option<Box<RawValue>>, id: Id<'a>) -> Self {
74 Self {
75 jsonrpc: TwoPointZero,
76 id,
77 method: Cow::Owned(method),
78 params: params.map(Cow::Owned),
79 extensions: Extensions::new(),
80 }
81 }
82
83 pub fn id(&self) -> Id<'a> {
85 self.id.clone()
86 }
87
88 pub fn method_name(&self) -> &str {
90 &self.method
91 }
92
93 pub fn params(&self) -> Params<'_> {
95 Params::new(self.params.as_ref().map(|p| RawValue::get(p)))
96 }
97
98 pub fn extensions(&self) -> &Extensions {
100 &self.extensions
101 }
102
103 pub fn extensions_mut(&mut self) -> &mut Extensions {
105 &mut self.extensions
106 }
107}
108
109#[derive(Deserialize, Debug, PartialEq, Eq, Clone)]
111pub struct InvalidRequest<'a> {
112 #[serde(borrow)]
114 pub id: Id<'a>,
115}
116
117#[derive(Serialize, Deserialize, Debug, Clone)]
120pub struct Notification<'a, T> {
121 pub jsonrpc: TwoPointZero,
123 #[serde(borrow)]
125 pub method: Cow<'a, str>,
126 pub params: T,
128 #[serde(skip)]
130 pub extensions: Extensions,
131}
132
133impl<'a, T> Notification<'a, T> {
134 pub fn new(method: Cow<'a, str>, params: T) -> Self {
136 Self { jsonrpc: TwoPointZero, method, params, extensions: Extensions::new() }
137 }
138
139 pub fn method_name(&self) -> &str {
141 &self.method
142 }
143
144 pub fn extensions(&self) -> &Extensions {
146 &self.extensions
147 }
148
149 pub fn params(&self) -> &T {
151 &self.params
152 }
153
154 pub fn extensions_mut(&mut self) -> &mut Extensions {
156 &mut self.extensions
157 }
158}
159
160#[cfg(test)]
161mod test {
162 use super::{Id, InvalidRequest, Notification, Request, TwoPointZero};
163 use serde_json::value::RawValue;
164
165 fn assert_request<'a>(request: Request<'a>, id: Id<'a>, method: &str, params: Option<&str>) {
166 assert_eq!(request.jsonrpc, TwoPointZero);
167 assert_eq!(request.id, id);
168 assert_eq!(request.method, method);
169 assert_eq!(request.params.as_ref().map(|p| RawValue::get(p)), params);
170 }
171
172 #[test]
174 fn deserialize_call() {
175 let method = "subtract";
176 let params = "[42, 23]";
177
178 let test_vector = vec![
179 (
181 r#"{"jsonrpc":"2.0", "method":"subtract", "params":[42, 23], "id":1}"#,
182 Id::Number(1),
183 Some(params),
184 method,
185 ),
186 (r#"{"jsonrpc":"2.0", "method":"subtract", "id":null}"#, Id::Null, None, method),
188 (r#"{"jsonrpc":"2.0", "method":"\"m", "id":null}"#, Id::Null, None, "\"m"),
190 ];
191
192 for (ser, id, params, method) in test_vector.into_iter() {
193 let request = serde_json::from_str(ser).unwrap();
194 assert_request(request, id, method, params);
195 }
196 }
197
198 #[test]
199 fn deserialize_call_escaped_method_name() {
200 let ser = r#"{"jsonrpc":"2.0","id":1,"method":"\"m\""}"#;
201 let req: Request = serde_json::from_str(ser).unwrap();
202 assert_request(req, Id::Number(1), "\"m\"", None);
203 }
204
205 #[test]
206 fn deserialize_valid_notif_works() {
207 let ser = r#"{"jsonrpc":"2.0","method":"say_hello","params":[]}"#;
208 let dsr: Notification<&RawValue> = serde_json::from_str(ser).unwrap();
209 assert_eq!(dsr.method, "say_hello");
210 assert_eq!(dsr.jsonrpc, TwoPointZero);
211 }
212
213 #[test]
214 fn deserialize_valid_notif_escaped_method() {
215 let ser = r#"{"jsonrpc":"2.0","method":"\"m\"","params":[]}"#;
216 let dsr: Notification<&RawValue> = serde_json::from_str(ser).unwrap();
217 assert_eq!(dsr.method, "\"m\"");
218 assert_eq!(dsr.jsonrpc, TwoPointZero);
219 }
220
221 #[test]
222 fn deserialize_call_bad_id_should_fail() {
223 let ser = r#"{"jsonrpc":"2.0","method":"say_hello","params":[],"id":{}}"#;
224 assert!(serde_json::from_str::<Request>(ser).is_err());
225 }
226
227 #[test]
228 fn deserialize_invalid_request() {
229 let s = r#"{"id":120,"method":"my_method","params":["foo", "bar"],"extra_field":[]}"#;
230 let deserialized: InvalidRequest = serde_json::from_str(s).unwrap();
231 assert_eq!(deserialized, InvalidRequest { id: Id::Number(120) });
232 }
233
234 #[test]
236 fn serialize_call() {
237 let method = "subtract";
238 let id = Id::Number(1); let params = Some(serde_json::value::to_raw_value(&[42, 23]).unwrap());
240
241 let test_vector: &[(&'static str, Option<_>, Option<_>, &'static str)] = &[
242 (
244 r#"{"jsonrpc":"2.0","id":1,"method":"subtract","params":[42,23]}"#,
245 Some(id.clone()),
246 params.clone(),
247 method,
248 ),
249 (r#"{"jsonrpc":"2.0","id":1,"method":"\"m"}"#, Some(id.clone()), None, "\"m"),
251 (r#"{"jsonrpc":"2.0","id":null,"method":"subtract","params":[42,23]}"#, None, params, method),
253 (r#"{"jsonrpc":"2.0","id":1,"method":"subtract"}"#, Some(id), None, method),
255 (r#"{"jsonrpc":"2.0","id":null,"method":"subtract"}"#, None, None, method),
257 ];
258
259 for (ser, id, params, method) in test_vector.iter().cloned() {
260 let request =
261 serde_json::to_string(&Request::borrowed(method, params.as_deref(), id.unwrap_or(Id::Null))).unwrap();
262
263 assert_eq!(&request, ser);
264 }
265 }
266}