rpc_router/rpc_message/
request.rs1use crate::support::get_json_type;
2use crate::{RpcId, RpcRequestParsingError};
3use serde::ser::SerializeStruct;
4use serde::{Deserialize, Serializer};
5use serde_json::Value;
6
7#[derive(Deserialize, Clone, Debug)]
9pub struct RpcRequest {
10 pub id: RpcId,
11 pub method: String,
12 pub params: Option<Value>,
13}
14
15impl RpcRequest {
16 pub fn new(id: impl Into<RpcId>, method: impl Into<String>, params: Option<Value>) -> Self {
17 RpcRequest {
18 id: id.into(),
19 method: method.into(),
20 params,
21 }
22 }
23}
24
25impl RpcRequest {
27 pub fn from_value(value: Value) -> Result<RpcRequest, RpcRequestParsingError> {
28 RpcRequest::from_value_with_checks(value, RpcRequestCheckFlags::ALL)
29 }
30
31 pub fn from_value_with_checks(
35 value: Value,
36 checks: RpcRequestCheckFlags,
37 ) -> Result<RpcRequest, RpcRequestParsingError> {
38 let value_type = get_json_type(&value);
42
43 let Value::Object(mut obj) = value else {
44 return Err(RpcRequestParsingError::RequestInvalidType {
45 actual_type: value_type.to_string(),
46 });
47 };
48
49 if checks.contains(RpcRequestCheckFlags::VERSION) {
51 match obj.remove("jsonrpc") {
53 Some(version) => {
54 if version.as_str().unwrap_or_default() != "2.0" {
55 let (id_val, method) = extract_id_value_and_method(obj);
56 return Err(RpcRequestParsingError::VersionInvalid {
57 id: id_val,
58 method,
59 version,
60 });
61 }
62 }
63 None => {
64 let (id_val, method) = extract_id_value_and_method(obj);
65 return Err(RpcRequestParsingError::VersionMissing { id: id_val, method });
66 }
67 }
68 }
69
70 let rpc_id_value: Option<Value> = obj.remove("id");
72
73 let method = match obj.remove("method") {
75 None => {
76 return Err(RpcRequestParsingError::MethodMissing { id: rpc_id_value });
77 }
78 Some(method_val) => match method_val {
79 Value::String(method_name) => method_name,
80 other => {
81 return Err(RpcRequestParsingError::MethodInvalidType {
82 id: rpc_id_value,
83 method: other,
84 });
85 }
86 },
87 };
88
89 let check_id = checks.contains(RpcRequestCheckFlags::ID);
92 let id = match rpc_id_value {
93 None => {
94 if check_id {
95 return Err(RpcRequestParsingError::IdMissing { method: Some(method) });
96 } else {
97 RpcId::Null
98 }
99 }
100 Some(id_value) => match RpcId::from_value(id_value) {
101 Ok(rpc_id) => rpc_id,
102 Err(err) => {
103 if check_id {
104 return Err(err);
105 } else {
106 RpcId::Null
107 }
108 }
109 },
110 };
111
112 let params = obj.get_mut("params").map(Value::take);
114
115 Ok(RpcRequest { id, method, params })
116 }
117}
118
119impl serde::Serialize for RpcRequest {
122 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
123 where
124 S: Serializer,
125 {
126 let mut field_count = 3;
128 if self.params.is_some() {
129 field_count += 1;
130 }
131
132 let mut state = serializer.serialize_struct("RpcRequest", field_count)?;
133
134 state.serialize_field("jsonrpc", "2.0")?;
136
137 state.serialize_field("id", &self.id)?;
138 state.serialize_field("method", &self.method)?;
139
140 if let Some(params) = &self.params {
142 state.serialize_field("params", params)?;
143 }
144
145 state.end()
146 }
147}
148
149bitflags::bitflags! {
152 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
154 pub struct RpcRequestCheckFlags: u32 {
155 const VERSION = 0b00000001;
157 const ID = 0b00000010;
160
161 const ALL = Self::VERSION.bits() | Self::ID.bits();
163 }
164}
165
166fn extract_id_value_and_method(mut obj: serde_json::Map<String, Value>) -> (Option<Value>, Option<String>) {
170 let id = obj.remove("id");
171 let method = obj.remove("method").and_then(|v| v.as_str().map(|s| s.to_string()));
173 (id, method)
174}
175
176impl TryFrom<Value> for RpcRequest {
179 type Error = RpcRequestParsingError;
180 fn try_from(value: Value) -> Result<RpcRequest, RpcRequestParsingError> {
181 RpcRequest::from_value(value)
182 }
183}
184
185