reddb_server/mcp/
protocol.rs1use crate::json::{Map, Value as JsonValue};
11use reddb_wire::jsonrpc::{self, JsonRpcSerializer};
12
13pub use reddb_wire::jsonrpc::{read_payload, write_message};
14
15pub struct ServerJson;
21
22impl JsonRpcSerializer for ServerJson {
23 type Value = JsonValue;
24
25 fn null() -> JsonValue {
26 JsonValue::Null
27 }
28
29 fn string(value: &str) -> JsonValue {
30 JsonValue::String(value.to_string())
31 }
32
33 fn number(value: i64) -> JsonValue {
34 JsonValue::Number(value as f64)
35 }
36
37 fn object(entries: Vec<(&'static str, JsonValue)>) -> JsonValue {
38 let mut object = Map::new();
39 for (key, value) in entries {
40 object.insert(key.to_string(), value);
41 }
42 JsonValue::Object(object)
43 }
44
45 fn to_compact_string(value: &JsonValue) -> String {
46 value.to_string_compact()
47 }
48}
49
50pub fn build_result_message(id: Option<&JsonValue>, result: JsonValue) -> String {
52 jsonrpc::build_result_message::<ServerJson>(id, result)
53}
54
55pub fn build_error_message(id: Option<&JsonValue>, code: i64, message: &str) -> String {
57 jsonrpc::build_error_message::<ServerJson>(id, code, message)
58}
59
60pub fn build_notification(method: &str, params: JsonValue) -> String {
62 jsonrpc::build_notification::<ServerJson>(method, params)
63}
64
65#[cfg(test)]
66mod tests {
67 use super::*;
68 use crate::json::from_str;
69
70 #[test]
71 fn test_build_result_message() {
72 let id = JsonValue::Number(1.0);
73 let result = JsonValue::Bool(true);
74 let msg = build_result_message(Some(&id), result);
75 let parsed: JsonValue = from_str(&msg).unwrap();
76 assert_eq!(parsed.get("jsonrpc").and_then(|v| v.as_str()), Some("2.0"));
77 assert_eq!(parsed.get("id").and_then(|v| v.as_f64()), Some(1.0));
78 assert_eq!(msg, r#"{"id":1,"jsonrpc":"2.0","result":true}"#);
80 }
81
82 #[test]
83 fn test_build_error_message() {
84 let id = JsonValue::Number(2.0);
85 let msg = build_error_message(Some(&id), -32601, "method not found");
86 let parsed: JsonValue = from_str(&msg).unwrap();
87 assert_eq!(parsed.get("jsonrpc").and_then(|v| v.as_str()), Some("2.0"));
88 let error = parsed.get("error").unwrap();
89 assert_eq!(error.get("code").and_then(|v| v.as_f64()), Some(-32601.0));
90 assert_eq!(
91 error.get("message").and_then(|v| v.as_str()),
92 Some("method not found")
93 );
94 assert_eq!(
95 msg,
96 r#"{"error":{"code":-32601,"message":"method not found"},"id":2,"jsonrpc":"2.0"}"#
97 );
98 }
99
100 #[test]
101 fn test_build_notification() {
102 let msg = build_notification("test/event", JsonValue::Null);
103 let parsed: JsonValue = from_str(&msg).unwrap();
104 assert_eq!(
105 parsed.get("method").and_then(|v| v.as_str()),
106 Some("test/event")
107 );
108 assert!(parsed.get("id").is_none());
109 assert_eq!(
110 msg,
111 r#"{"jsonrpc":"2.0","method":"test/event","params":null}"#
112 );
113 }
114
115 #[test]
116 fn test_read_payload_basic() {
117 let body = r#"{"id":1}"#;
118 let msg = format!("Content-Length: {}\r\n\r\n{}", body.len(), body);
119 let mut reader = std::io::BufReader::new(msg.as_bytes());
120 let payload = read_payload(&mut reader).unwrap();
121 assert_eq!(payload, Some(body.to_string()));
122 }
123
124 #[test]
125 fn test_read_payload_eof() {
126 let input = b"";
127 let mut reader = std::io::BufReader::new(&input[..]);
128 let payload = read_payload(&mut reader).unwrap();
129 assert!(payload.is_none());
130 }
131}