1use serde::{Deserialize, Serialize};
7
8pub use aimdb_core::remote::{
10 ErrorObject, Event, HelloMessage, RecordMetadata, Request, Response, WelcomeMessage,
11};
12
13pub const PROTOCOL_VERSION: &str = "1.0";
15
16pub const CLIENT_NAME: &str = "aimdb-cli";
18
19pub trait RequestExt {
21 #[allow(clippy::new_ret_no_self)]
23 fn new(id: u64, method: impl Into<String>) -> Request;
24
25 fn with_params(id: u64, method: impl Into<String>, params: serde_json::Value) -> Request;
27}
28
29impl RequestExt for Request {
30 fn new(id: u64, method: impl Into<String>) -> Request {
31 Request {
32 id,
33 method: method.into(),
34 params: None,
35 }
36 }
37
38 fn with_params(id: u64, method: impl Into<String>, params: serde_json::Value) -> Request {
39 Request {
40 id,
41 method: method.into(),
42 params: Some(params),
43 }
44 }
45}
46
47pub trait ResponseExt {
49 fn into_result(self) -> Result<serde_json::Value, ErrorObject>;
51}
52
53impl ResponseExt for Response {
54 fn into_result(self) -> Result<serde_json::Value, ErrorObject> {
55 match self {
56 Response::Success { result, .. } => Ok(result),
57 Response::Error { error, .. } => Err(error),
58 }
59 }
60}
61
62pub fn cli_hello() -> HelloMessage {
64 HelloMessage {
65 version: PROTOCOL_VERSION.to_string(),
66 client: CLIENT_NAME.to_string(),
67 capabilities: None,
68 auth_token: None,
69 }
70}
71
72#[derive(Debug, Clone, Deserialize)]
74pub struct EventMessage {
75 pub event: Event,
76}
77
78pub fn serialize_message<T: Serialize>(msg: &T) -> Result<String, serde_json::Error> {
80 Ok(format!("{}\n", serde_json::to_string(msg)?))
81}
82
83pub fn parse_message<T: for<'de> Deserialize<'de>>(line: &str) -> Result<T, serde_json::Error> {
85 serde_json::from_str(line.trim())
86}
87
88#[cfg(test)]
89mod tests {
90 use super::*;
91
92 #[test]
93 fn test_request_serialization() {
94 let req = Request::new(1, "record.list");
95 let json = serialize_message(&req).unwrap();
96 assert!(json.contains("\"method\":\"record.list\""));
97 assert!(json.ends_with('\n'));
98 }
99
100 #[test]
101 fn test_response_parsing() {
102 let json = r#"{"id":1,"result":{"status":"ok"}}"#;
103 let resp: Response = parse_message(json).unwrap();
104 let result = resp.into_result().unwrap();
105 assert_eq!(result["status"], "ok");
106 }
107
108 #[test]
109 fn test_cli_hello() {
110 let hello = cli_hello();
111 assert_eq!(hello.version, PROTOCOL_VERSION);
112 assert_eq!(hello.client, CLIENT_NAME);
113 assert!(hello.auth_token.is_none());
114 }
115}