1use std::borrow::Cow;
2
3use serde::{Deserialize, Deserializer, Serialize, Serializer};
4
5use crate::Id;
6
7#[derive(Debug, Clone)]
9pub struct Request<'a, P> {
10 pub method: Cow<'a, str>,
12 pub params: P,
14 pub id: Option<Id<'a>>,
16}
17
18impl<'a, P> Serialize for Request<'a, P>
19where
20 P: Serialize,
21{
22 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
23 where
24 S: Serializer,
25 {
26 OutgoingRequest::from_request(self).serialize(serializer)
27 }
28}
29
30impl<'de, 'a, P> Deserialize<'de> for Request<'a, P>
31where
32 'de: 'a,
33 P: Deserialize<'de>,
34{
35 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
36 where
37 D: Deserializer<'de>,
38 {
39 IncomingRequest::deserialize(deserializer).and_then(IncomingRequest::into_request)
40 }
41}
42
43#[derive(Serialize)]
44struct OutgoingRequest<'a, P> {
45 jsonrpc: &'a str,
46 method: &'a str,
47 params: &'a P,
48 #[serde(skip_serializing_if = "Option::is_none")]
49 id: Option<crate::Id<'a>>,
50}
51
52impl<'a, P> OutgoingRequest<'a, P> {
53 fn from_request(req: &'a crate::Request<'_, P>) -> Self {
54 Self {
55 jsonrpc: "2.0",
56 method: &req.method,
57 params: &req.params,
58 id: req.id.as_ref().map(Id::reborrow),
59 }
60 }
61}
62
63#[derive(Deserialize)]
64struct IncomingRequest<'a, P> {
65 #[serde(borrow)]
66 jsonrpc: Cow<'a, str>,
67 #[serde(borrow)]
68 method: Cow<'a, str>,
69 params: P,
70 #[serde(borrow, default, deserialize_with = "deserialize_id")]
71 id: Option<crate::Id<'a>>,
72}
73
74impl<'a, P> IncomingRequest<'a, P> {
75 fn into_request<E>(self) -> Result<crate::Request<'a, P>, E>
76 where
77 E: serde::de::Error,
78 P: serde::Deserialize<'a>,
79 {
80 if self.jsonrpc != "2.0" {
81 return Err(E::invalid_value(
82 serde::de::Unexpected::Str(&self.jsonrpc),
83 &"2.0",
84 ));
85 }
86
87 Ok(crate::Request {
88 method: self.method,
89 params: self.params,
90 id: self.id,
91 })
92 }
93}
94
95fn deserialize_id<'de, D>(deserializer: D) -> Result<Option<crate::Id<'de>>, D::Error>
100where
101 D: Deserializer<'de>,
102{
103 let opt = Option::deserialize(deserializer)?;
104
105 match opt {
106 Some(some) => Ok(some),
107 None => Ok(Some(Id::Null)),
108 }
109}
110
111#[test]
112#[cfg(test)]
113fn null_id() {
114 let request = r#"{"jsonrpc":"2.0","method":"","id":null}"#;
115 let request: crate::Request<'_, Option<()>> = serde_json::from_str(request).unwrap();
116 assert_eq!(request.id, Some(Id::Null));
117}
118
119#[test]
120#[cfg(test)]
121fn no_id() {
122 let request = r#"{"jsonrpc":"2.0","method":""}"#;
123 let request: crate::Request<'_, Option<()>> = serde_json::from_str(request).unwrap();
124 assert_eq!(request.id, None);
125}