1use crate::{common::Id, RpcBorrow, RpcSend};
2use alloy_primitives::{keccak256, B256};
3use http::Extensions;
4use serde::{
5 de::{DeserializeOwned, MapAccess},
6 ser::SerializeMap,
7 Deserialize, Serialize,
8};
9use serde_json::value::RawValue;
10use std::{borrow::Cow, marker::PhantomData, mem::MaybeUninit};
11
12#[derive(Clone, Debug)]
14pub struct RequestMeta {
15 pub method: Cow<'static, str>,
17 pub id: Id,
19 is_subscription: bool,
21 extensions: Extensions,
24}
25
26impl RequestMeta {
27 pub fn new(method: Cow<'static, str>, id: Id) -> Self {
29 Self { method, id, is_subscription: false, extensions: Extensions::new() }
30 }
31
32 pub fn is_subscription(&self) -> bool {
34 self.is_subscription || self.method == "eth_subscribe"
35 }
36
37 pub const fn set_is_subscription(&mut self) {
40 self.set_subscription_status(true);
41 }
42
43 pub const fn set_subscription_status(&mut self, sub: bool) {
46 self.is_subscription = sub;
47 }
48
49 pub const fn extensions(&self) -> &Extensions {
54 &self.extensions
55 }
56
57 pub const fn extensions_mut(&mut self) -> &mut Extensions {
62 &mut self.extensions
63 }
64}
65
66impl PartialEq for RequestMeta {
67 fn eq(&self, other: &Self) -> bool {
68 self.method == other.method
69 && self.id == other.id
70 && self.is_subscription == other.is_subscription
71 }
72}
73
74impl Eq for RequestMeta {}
75
76#[derive(Clone, Debug, PartialEq, Eq)]
86pub struct Request<Params> {
87 pub meta: RequestMeta,
89 pub params: Params,
91}
92
93impl<Params> Request<Params> {
94 pub fn new(method: impl Into<Cow<'static, str>>, id: Id, params: Params) -> Self {
96 Self { meta: RequestMeta::new(method.into(), id), params }
97 }
98
99 pub fn is_subscription(&self) -> bool {
101 self.meta.is_subscription()
102 }
103
104 pub const fn set_is_subscription(&mut self) {
107 self.meta.set_is_subscription()
108 }
109
110 pub const fn set_subscription_status(&mut self, sub: bool) {
113 self.meta.set_subscription_status(sub);
114 }
115
116 pub fn map_params<NewParams>(
118 self,
119 map: impl FnOnce(Params) -> NewParams,
120 ) -> Request<NewParams> {
121 Request { meta: self.meta, params: map(self.params) }
122 }
123
124 pub fn map_meta<F>(self, f: F) -> Self
126 where
127 F: FnOnce(RequestMeta) -> RequestMeta,
128 {
129 Self { meta: f(self.meta), params: self.params }
130 }
131}
132
133pub type PartiallySerializedRequest = Request<Box<RawValue>>;
143
144impl<Params> Request<Params>
145where
146 Params: RpcSend,
147{
148 pub fn box_params(self) -> PartiallySerializedRequest {
154 Request { meta: self.meta, params: serde_json::value::to_raw_value(&self.params).unwrap() }
155 }
156
157 pub fn serialize(self) -> serde_json::Result<SerializedRequest> {
159 let request = serde_json::value::to_raw_value(&self)?;
160 Ok(SerializedRequest { meta: self.meta, request })
161 }
162}
163
164impl<Params> Request<&Params>
165where
166 Params: ToOwned,
167 Params::Owned: RpcSend,
168{
169 pub fn into_owned_params(self) -> Request<Params::Owned> {
171 Request { meta: self.meta, params: self.params.to_owned() }
172 }
173}
174
175impl<'a, Params> Request<Params>
176where
177 Params: AsRef<RawValue> + 'a,
178{
179 pub fn try_params_as<T: DeserializeOwned>(&self) -> serde_json::Result<T> {
188 serde_json::from_str(self.params.as_ref().get())
189 }
190
191 pub fn try_borrow_params_as<T: Deserialize<'a>>(&'a self) -> serde_json::Result<T> {
197 serde_json::from_str(self.params.as_ref().get())
198 }
199}
200
201impl<Params> Serialize for Request<Params>
204where
205 Params: RpcSend,
206{
207 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
208 where
209 S: serde::Serializer,
210 {
211 let sized_params = std::mem::size_of::<Params>() != 0;
212
213 let mut map = serializer.serialize_map(Some(3 + sized_params as usize))?;
214 map.serialize_entry("method", &self.meta.method[..])?;
215
216 if sized_params {
218 map.serialize_entry("params", &self.params)?;
219 }
220
221 map.serialize_entry("id", &self.meta.id)?;
222 map.serialize_entry("jsonrpc", "2.0")?;
223 map.end()
224 }
225}
226
227impl<'de, Params> Deserialize<'de> for Request<Params>
228where
229 Params: RpcBorrow<'de>,
230{
231 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
232 where
233 D: serde::Deserializer<'de>,
234 {
235 struct Visitor<Params>(PhantomData<Params>);
236 impl<'de, Params> serde::de::Visitor<'de> for Visitor<Params>
237 where
238 Params: RpcBorrow<'de>,
239 {
240 type Value = Request<Params>;
241
242 fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
243 write!(
244 formatter,
245 "a JSON-RPC 2.0 request object with params of type {}",
246 std::any::type_name::<Params>()
247 )
248 }
249
250 fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
251 where
252 A: MapAccess<'de>,
253 {
254 let mut id = None;
255 let mut params = None;
256 let mut method = None;
257 let mut jsonrpc = None;
258
259 while let Some(key) = map.next_key()? {
260 match key {
261 "id" => {
262 if id.is_some() {
263 return Err(serde::de::Error::duplicate_field("id"));
264 }
265 id = Some(map.next_value()?);
266 }
267 "params" => {
268 if params.is_some() {
269 return Err(serde::de::Error::duplicate_field("params"));
270 }
271 params = Some(map.next_value()?);
272 }
273 "method" => {
274 if method.is_some() {
275 return Err(serde::de::Error::duplicate_field("method"));
276 }
277 method = Some(map.next_value()?);
278 }
279 "jsonrpc" => {
280 let version: String = map.next_value()?;
281 if version != "2.0" {
282 return Err(serde::de::Error::custom(format!(
283 "unsupported JSON-RPC version: {version}"
284 )));
285 }
286 jsonrpc = Some(());
287 }
288 other => {
289 return Err(serde::de::Error::unknown_field(
290 other,
291 &["id", "params", "method", "jsonrpc"],
292 ));
293 }
294 }
295 }
296 if jsonrpc.is_none() {
297 return Err(serde::de::Error::missing_field("jsonrpc"));
298 }
299 if method.is_none() {
300 return Err(serde::de::Error::missing_field("method"));
301 }
302
303 if params.is_none() {
304 if std::mem::size_of::<Params>() == 0 {
305 unsafe { params = Some(MaybeUninit::<Params>::zeroed().assume_init()) }
307 } else {
308 return Err(serde::de::Error::missing_field("params"));
309 }
310 }
311
312 Ok(Request {
313 meta: RequestMeta::new(method.unwrap(), id.unwrap_or(Id::None)),
314 params: params.unwrap(),
315 })
316 }
317 }
318
319 deserializer.deserialize_map(Visitor(PhantomData))
320 }
321}
322
323#[derive(Clone, Debug)]
330pub struct SerializedRequest {
331 meta: RequestMeta,
332 request: Box<RawValue>,
333}
334
335impl<Params> TryFrom<Request<Params>> for SerializedRequest
336where
337 Params: RpcSend,
338{
339 type Error = serde_json::Error;
340
341 fn try_from(value: Request<Params>) -> Result<Self, Self::Error> {
342 value.serialize()
343 }
344}
345
346impl SerializedRequest {
347 pub const fn meta(&self) -> &RequestMeta {
349 &self.meta
350 }
351
352 pub const fn meta_mut(&mut self) -> &mut RequestMeta {
354 &mut self.meta
355 }
356
357 pub const fn id(&self) -> &Id {
359 &self.meta.id
360 }
361
362 pub fn method(&self) -> &str {
364 &self.meta.method
365 }
366
367 pub const fn set_is_subscription(&mut self) {
370 self.meta.set_is_subscription();
371 }
372
373 pub fn is_subscription(&self) -> bool {
375 self.meta.is_subscription()
376 }
377
378 pub const fn serialized(&self) -> &RawValue {
380 &self.request
381 }
382
383 pub fn into_serialized(self) -> Box<RawValue> {
385 self.request
386 }
387
388 pub fn decompose(self) -> (RequestMeta, Box<RawValue>) {
391 (self.meta, self.request)
392 }
393
394 pub fn take_request(self) -> Box<RawValue> {
396 self.request
397 }
398
399 pub fn params(&self) -> Option<&RawValue> {
404 #[derive(Deserialize)]
405 struct Req<'a> {
406 #[serde(borrow)]
407 params: Option<&'a RawValue>,
408 }
409
410 let req: Req<'_> = serde_json::from_str(self.request.get()).unwrap();
411 req.params
412 }
413
414 pub fn params_hash(&self) -> B256 {
419 self.params().map_or_else(|| keccak256(""), |params| keccak256(params.get()))
420 }
421}
422
423impl Serialize for SerializedRequest {
424 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
425 where
426 S: serde::Serializer,
427 {
428 self.request.serialize(serializer)
429 }
430}
431
432#[cfg(test)]
433mod test {
434 use super::*;
435 use crate::RpcObject;
436
437 fn test_inner<T: RpcObject + PartialEq>(t: T) {
438 let ser = serde_json::to_string(&t).unwrap();
439 let de: T = serde_json::from_str(&ser).unwrap();
440 let reser = serde_json::to_string(&de).unwrap();
441 assert_eq!(de, t, "deser error for {}", std::any::type_name::<T>());
442 assert_eq!(ser, reser, "reser error for {}", std::any::type_name::<T>());
443 }
444
445 #[test]
446 fn test_ser_deser() {
447 test_inner(Request::<()>::new("test", 1.into(), ()));
448 test_inner(Request::<u64>::new("test", "hello".to_string().into(), 1));
449 test_inner(Request::<String>::new("test", Id::None, "test".to_string()));
450 test_inner(Request::<Vec<u64>>::new("test", u64::MAX.into(), vec![1, 2, 3]));
451 }
452}