turul_mcp_json_rpc_server/
request.rs1use serde::{Deserialize, Serialize};
2use serde_json::Value;
3use std::collections::HashMap;
4
5use crate::types::{JsonRpcVersion, RequestId};
6
7#[derive(Debug, Clone, Deserialize, Serialize)]
9#[serde(untagged)]
10pub enum RequestParams {
11 Array(Vec<Value>),
13 Object(HashMap<String, Value>),
15}
16
17impl RequestParams {
18 pub fn get(&self, key: &str) -> Option<&Value> {
20 match self {
21 RequestParams::Object(map) => map.get(key),
22 RequestParams::Array(_) => None, }
24 }
25
26 pub fn get_index(&self, index: usize) -> Option<&Value> {
28 match self {
29 RequestParams::Array(vec) => vec.get(index),
30 RequestParams::Object(_) => None, }
32 }
33
34 pub fn to_map(&self) -> HashMap<String, Value> {
36 match self {
37 RequestParams::Object(map) => map.clone(),
38 RequestParams::Array(vec) => vec
39 .iter()
40 .enumerate()
41 .map(|(i, v)| (i.to_string(), v.clone()))
42 .collect(),
43 }
44 }
45
46 pub fn is_empty(&self) -> bool {
48 match self {
49 RequestParams::Object(map) => map.is_empty(),
50 RequestParams::Array(vec) => vec.is_empty(),
51 }
52 }
53
54 pub fn to_value(&self) -> Value {
56 match self {
57 RequestParams::Object(map) => {
58 Value::Object(map.iter().map(|(k, v)| (k.clone(), v.clone())).collect())
59 }
60 RequestParams::Array(arr) => Value::Array(arr.clone()),
61 }
62 }
63}
64
65impl From<HashMap<String, Value>> for RequestParams {
66 fn from(map: HashMap<String, Value>) -> Self {
67 RequestParams::Object(map)
68 }
69}
70
71impl From<Vec<Value>> for RequestParams {
72 fn from(vec: Vec<Value>) -> Self {
73 RequestParams::Array(vec)
74 }
75}
76
77#[derive(Debug, Clone, Serialize, Deserialize)]
79pub struct JsonRpcRequest {
80 #[serde(rename = "jsonrpc")]
81 pub version: JsonRpcVersion,
82 pub id: RequestId,
83 pub method: String,
84 #[serde(skip_serializing_if = "Option::is_none")]
85 pub params: Option<RequestParams>,
86}
87
88impl JsonRpcRequest {
89 pub fn new(id: RequestId, method: String, params: Option<RequestParams>) -> Self {
90 Self {
91 version: JsonRpcVersion::V2_0,
92 id,
93 method,
94 params,
95 }
96 }
97
98 pub fn new_no_params(id: RequestId, method: String) -> Self {
100 Self::new(id, method, None)
101 }
102
103 pub fn new_with_object_params(
105 id: RequestId,
106 method: String,
107 params: HashMap<String, Value>,
108 ) -> Self {
109 Self::new(id, method, Some(RequestParams::Object(params)))
110 }
111
112 pub fn new_with_array_params(id: RequestId, method: String, params: Vec<Value>) -> Self {
114 Self::new(id, method, Some(RequestParams::Array(params)))
115 }
116
117 pub fn get_param(&self, name: &str) -> Option<&Value> {
119 self.params.as_ref()?.get(name)
120 }
121
122 pub fn get_param_index(&self, index: usize) -> Option<&Value> {
124 self.params.as_ref()?.get_index(index)
125 }
126}
127
128#[cfg(test)]
129mod tests {
130 use super::*;
131 use serde_json::{from_str, json, to_string};
132
133 #[test]
134 fn test_request_serialization() {
135 let request =
136 JsonRpcRequest::new_no_params(RequestId::Number(1), "test_method".to_string());
137
138 let json = to_string(&request).unwrap();
139 let parsed: JsonRpcRequest = from_str(&json).unwrap();
140
141 assert_eq!(parsed.id, RequestId::Number(1));
142 assert_eq!(parsed.method, "test_method");
143 assert!(parsed.params.is_none());
144 }
145
146 #[test]
147 fn test_request_with_object_params() {
148 let mut params = HashMap::new();
149 params.insert("name".to_string(), json!("test"));
150 params.insert("value".to_string(), json!(42));
151
152 let request = JsonRpcRequest::new_with_object_params(
153 RequestId::String("req1".to_string()),
154 "set_value".to_string(),
155 params,
156 );
157
158 assert_eq!(request.get_param("name"), Some(&json!("test")));
159 assert_eq!(request.get_param("value"), Some(&json!(42)));
160 assert_eq!(request.get_param("missing"), None);
161 }
162
163 #[test]
164 fn test_request_with_array_params() {
165 let params = vec![json!("test"), json!(42), json!(true)];
166
167 let request = JsonRpcRequest::new_with_array_params(
168 RequestId::Number(2),
169 "process".to_string(),
170 params,
171 );
172
173 assert_eq!(request.get_param_index(0), Some(&json!("test")));
174 assert_eq!(request.get_param_index(1), Some(&json!(42)));
175 assert_eq!(request.get_param_index(2), Some(&json!(true)));
176 assert_eq!(request.get_param_index(3), None);
177 }
178
179 #[test]
180 fn test_params_to_map() {
181 let object_params = RequestParams::Object({
182 let mut map = HashMap::new();
183 map.insert("key".to_string(), json!("value"));
184 map
185 });
186
187 let array_params = RequestParams::Array(vec![json!("first"), json!("second")]);
188
189 let object_map = object_params.to_map();
190 assert_eq!(object_map.get("key"), Some(&json!("value")));
191
192 let array_map = array_params.to_map();
193 assert_eq!(array_map.get("0"), Some(&json!("first")));
194 assert_eq!(array_map.get("1"), Some(&json!("second")));
195 }
196}