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