use serde::{Deserialize, Serialize};
#[derive(Debug, Deserialize)]
pub struct Request {
pub command: String,
#[serde(default)]
pub params: Option<serde_json::Value>,
}
#[derive(Debug, Serialize)]
pub struct Response {
pub status: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub data: Option<serde_json::Value>,
#[serde(skip_serializing_if = "Option::is_none")]
pub message: Option<String>,
}
impl Response {
pub fn ok(data: serde_json::Value) -> Self {
Self {
status: "ok".to_string(),
data: Some(data),
message: None,
}
}
pub fn error(message: impl Into<String>) -> Self {
Self {
status: "error".to_string(),
data: None,
message: Some(message.into()),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_deserialize_request() {
let json = r#"{"command": "show_status"}"#;
let req: Request = serde_json::from_str(json).unwrap();
assert_eq!(req.command, "show_status");
}
#[test]
fn test_serialize_ok_response() {
let resp = Response::ok(serde_json::json!({"state": "running"}));
let json = serde_json::to_string(&resp).unwrap();
assert!(json.contains("\"status\":\"ok\""));
assert!(json.contains("\"state\":\"running\""));
assert!(!json.contains("\"message\""));
}
#[test]
fn test_serialize_error_response() {
let resp = Response::error("unknown command: foo");
let json = serde_json::to_string(&resp).unwrap();
assert!(json.contains("\"status\":\"error\""));
assert!(json.contains("unknown command: foo"));
assert!(!json.contains("\"data\""));
}
#[test]
fn test_deserialize_unknown_fields_ignored() {
let json = r#"{"command": "show_peers", "extra": true}"#;
let req: Request = serde_json::from_str(json).unwrap();
assert_eq!(req.command, "show_peers");
}
#[test]
fn test_deserialize_request_with_params() {
let json = r#"{"command": "connect", "params": {"npub": "npub1abc", "address": "1.2.3.4:2121", "transport": "udp"}}"#;
let req: Request = serde_json::from_str(json).unwrap();
assert_eq!(req.command, "connect");
let params = req.params.unwrap();
assert_eq!(params["npub"], "npub1abc");
assert_eq!(params["transport"], "udp");
}
#[test]
fn test_deserialize_request_without_params() {
let json = r#"{"command": "show_status"}"#;
let req: Request = serde_json::from_str(json).unwrap();
assert_eq!(req.command, "show_status");
assert!(req.params.is_none());
}
#[test]
fn test_deserialize_malformed_request() {
let json = r#"{"not_command": "foo"}"#;
let result: Result<Request, _> = serde_json::from_str(json);
assert!(result.is_err());
}
}