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 pub fn headers(&self) -> Option<&http::HeaderMap> {
67 self.extensions.get::<http::HeaderMap>()
68 }
69
70 pub fn headers_mut(&mut self) -> &mut http::HeaderMap {
73 self.extensions.get_or_insert_default::<http::HeaderMap>()
74 }
75}
76
77impl PartialEq for RequestMeta {
78 fn eq(&self, other: &Self) -> bool {
79 self.method == other.method
80 && self.id == other.id
81 && self.is_subscription == other.is_subscription
82 }
83}
84
85impl Eq for RequestMeta {}
86
87#[derive(Clone, Debug, PartialEq, Eq)]
97pub struct Request<Params> {
98 pub meta: RequestMeta,
100 pub params: Params,
102}
103
104impl<Params> Request<Params> {
105 pub fn new(method: impl Into<Cow<'static, str>>, id: Id, params: Params) -> Self {
107 Self { meta: RequestMeta::new(method.into(), id), params }
108 }
109
110 pub fn is_subscription(&self) -> bool {
112 self.meta.is_subscription()
113 }
114
115 pub const fn set_is_subscription(&mut self) {
118 self.meta.set_is_subscription()
119 }
120
121 pub const fn set_subscription_status(&mut self, sub: bool) {
124 self.meta.set_subscription_status(sub);
125 }
126
127 pub fn map_params<NewParams>(
129 self,
130 map: impl FnOnce(Params) -> NewParams,
131 ) -> Request<NewParams> {
132 Request { meta: self.meta, params: map(self.params) }
133 }
134
135 pub fn map_meta<F>(self, f: F) -> Self
137 where
138 F: FnOnce(RequestMeta) -> RequestMeta,
139 {
140 Self { meta: f(self.meta), params: self.params }
141 }
142}
143
144pub type PartiallySerializedRequest = Request<Box<RawValue>>;
154
155impl<Params> Request<Params>
156where
157 Params: RpcSend,
158{
159 pub fn box_params(self) -> PartiallySerializedRequest {
165 Request { meta: self.meta, params: serde_json::value::to_raw_value(&self.params).unwrap() }
166 }
167
168 pub fn serialize(self) -> serde_json::Result<SerializedRequest> {
170 let request = serde_json::value::to_raw_value(&self)?;
171 Ok(SerializedRequest { meta: self.meta, request })
172 }
173}
174
175impl<Params> Request<&Params>
176where
177 Params: ToOwned,
178 Params::Owned: RpcSend,
179{
180 pub fn into_owned_params(self) -> Request<Params::Owned> {
182 Request { meta: self.meta, params: self.params.to_owned() }
183 }
184}
185
186impl<'a, Params> Request<Params>
187where
188 Params: AsRef<RawValue> + 'a,
189{
190 pub fn try_params_as<T: DeserializeOwned>(&self) -> serde_json::Result<T> {
199 serde_json::from_str(self.params.as_ref().get())
200 }
201
202 pub fn try_borrow_params_as<T: Deserialize<'a>>(&'a self) -> serde_json::Result<T> {
208 serde_json::from_str(self.params.as_ref().get())
209 }
210}
211
212impl<Params> Serialize for Request<Params>
215where
216 Params: RpcSend,
217{
218 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
219 where
220 S: serde::Serializer,
221 {
222 let sized_params = std::mem::size_of::<Params>() != 0;
223
224 let mut map = serializer.serialize_map(Some(3 + sized_params as usize))?;
225 map.serialize_entry("method", &self.meta.method[..])?;
226
227 if sized_params {
229 map.serialize_entry("params", &self.params)?;
230 }
231
232 map.serialize_entry("id", &self.meta.id)?;
233 map.serialize_entry("jsonrpc", "2.0")?;
234 map.end()
235 }
236}
237
238impl<'de, Params> Deserialize<'de> for Request<Params>
239where
240 Params: RpcBorrow<'de>,
241{
242 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
243 where
244 D: serde::Deserializer<'de>,
245 {
246 struct Visitor<Params>(PhantomData<Params>);
247 impl<'de, Params> serde::de::Visitor<'de> for Visitor<Params>
248 where
249 Params: RpcBorrow<'de>,
250 {
251 type Value = Request<Params>;
252
253 fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
254 write!(
255 formatter,
256 "a JSON-RPC 2.0 request object with params of type {}",
257 std::any::type_name::<Params>()
258 )
259 }
260
261 fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
262 where
263 A: MapAccess<'de>,
264 {
265 let mut id = None;
266 let mut params = None;
267 let mut method = None;
268 let mut jsonrpc = None;
269
270 while let Some(key) = map.next_key()? {
271 match key {
272 "id" => {
273 if id.is_some() {
274 return Err(serde::de::Error::duplicate_field("id"));
275 }
276 id = Some(map.next_value()?);
277 }
278 "params" => {
279 if params.is_some() {
280 return Err(serde::de::Error::duplicate_field("params"));
281 }
282 params = Some(map.next_value()?);
283 }
284 "method" => {
285 if method.is_some() {
286 return Err(serde::de::Error::duplicate_field("method"));
287 }
288 method = Some(map.next_value()?);
289 }
290 "jsonrpc" => {
291 let version: String = map.next_value()?;
292 if version != "2.0" {
293 return Err(serde::de::Error::custom(format!(
294 "unsupported JSON-RPC version: {version}"
295 )));
296 }
297 jsonrpc = Some(());
298 }
299 other => {
300 return Err(serde::de::Error::unknown_field(
301 other,
302 &["id", "params", "method", "jsonrpc"],
303 ));
304 }
305 }
306 }
307 if jsonrpc.is_none() {
308 return Err(serde::de::Error::missing_field("jsonrpc"));
309 }
310 if method.is_none() {
311 return Err(serde::de::Error::missing_field("method"));
312 }
313
314 if params.is_none() {
315 if std::mem::size_of::<Params>() == 0 {
316 unsafe { params = Some(MaybeUninit::<Params>::zeroed().assume_init()) }
318 } else {
319 return Err(serde::de::Error::missing_field("params"));
320 }
321 }
322
323 Ok(Request {
324 meta: RequestMeta::new(method.unwrap(), id.unwrap_or(Id::None)),
325 params: params.unwrap(),
326 })
327 }
328 }
329
330 deserializer.deserialize_map(Visitor(PhantomData))
331 }
332}
333
334#[derive(Clone, Debug)]
341pub struct SerializedRequest {
342 meta: RequestMeta,
343 request: Box<RawValue>,
344}
345
346impl<Params> TryFrom<Request<Params>> for SerializedRequest
347where
348 Params: RpcSend,
349{
350 type Error = serde_json::Error;
351
352 fn try_from(value: Request<Params>) -> Result<Self, Self::Error> {
353 value.serialize()
354 }
355}
356
357impl SerializedRequest {
358 pub const fn meta(&self) -> &RequestMeta {
360 &self.meta
361 }
362
363 pub const fn meta_mut(&mut self) -> &mut RequestMeta {
365 &mut self.meta
366 }
367
368 pub fn headers(&self) -> Option<&http::HeaderMap> {
370 self.meta.headers()
371 }
372
373 pub fn headers_mut(&mut self) -> &mut http::HeaderMap {
376 self.meta.headers_mut()
377 }
378
379 pub const fn id(&self) -> &Id {
381 &self.meta.id
382 }
383
384 pub fn method(&self) -> &str {
386 &self.meta.method
387 }
388
389 pub const fn set_is_subscription(&mut self) {
392 self.meta.set_is_subscription();
393 }
394
395 pub fn is_subscription(&self) -> bool {
397 self.meta.is_subscription()
398 }
399
400 pub const fn serialized(&self) -> &RawValue {
402 &self.request
403 }
404
405 pub fn into_serialized(self) -> Box<RawValue> {
407 self.request
408 }
409
410 pub fn decompose(self) -> (RequestMeta, Box<RawValue>) {
413 (self.meta, self.request)
414 }
415
416 pub fn take_request(self) -> Box<RawValue> {
418 self.request
419 }
420
421 pub fn params(&self) -> Option<&RawValue> {
426 #[derive(Deserialize)]
427 struct Req<'a> {
428 #[serde(borrow)]
429 params: Option<&'a RawValue>,
430 }
431
432 let req: Req<'_> = serde_json::from_str(self.request.get()).unwrap();
433 req.params
434 }
435
436 pub fn params_hash(&self) -> B256 {
441 self.params().map_or_else(|| keccak256(""), |params| keccak256(params.get()))
442 }
443}
444
445impl Serialize for SerializedRequest {
446 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
447 where
448 S: serde::Serializer,
449 {
450 self.request.serialize(serializer)
451 }
452}
453
454#[cfg(test)]
455mod test {
456 use super::*;
457 use crate::RpcObject;
458
459 fn test_inner<T: RpcObject + PartialEq>(t: T) {
460 let ser = serde_json::to_string(&t).unwrap();
461 let de: T = serde_json::from_str(&ser).unwrap();
462 let reser = serde_json::to_string(&de).unwrap();
463 assert_eq!(de, t, "deser error for {}", std::any::type_name::<T>());
464 assert_eq!(ser, reser, "reser error for {}", std::any::type_name::<T>());
465 }
466
467 #[test]
468 fn test_ser_deser() {
469 test_inner(Request::<()>::new("test", 1.into(), ()));
470 test_inner(Request::<u64>::new("test", "hello".to_string().into(), 1));
471 test_inner(Request::<String>::new("test", Id::None, "test".to_string()));
472 test_inner(Request::<Vec<u64>>::new("test", u64::MAX.into(), vec![1, 2, 3]));
473 }
474}