use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Request {
pub id: String,
pub method: Method,
#[serde(default)]
pub params: serde_json::Value,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum Method {
Status,
RunList,
RunShow,
RunApprove,
RunCancel,
WorkflowStart,
WorkflowChain,
Sweep,
Subscribe,
Stats,
Shutdown,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum Response {
Success {
id: String,
result: serde_json::Value,
},
Error { id: String, error: String },
}
impl Response {
pub fn success(id: String, result: impl Serialize) -> Self {
Self::Success {
id,
result: serde_json::to_value(result).unwrap_or(serde_json::Value::Null),
}
}
pub fn error(id: String, error: impl Into<String>) -> Self {
Self::Error {
id,
error: error.into(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_request_serialization() {
let req = Request {
id: "abc-123".into(),
method: Method::Status,
params: serde_json::Value::Object(Default::default()),
};
let json = serde_json::to_string(&req).unwrap();
assert!(json.contains("\"method\":\"status\""));
assert!(json.contains("\"id\":\"abc-123\""));
let parsed: Request = serde_json::from_str(&json).unwrap();
assert_eq!(parsed.method, Method::Status);
assert_eq!(parsed.id, "abc-123");
}
#[test]
fn test_response_success() {
let resp = Response::success("abc-123".into(), serde_json::json!({"running": 2}));
let json = serde_json::to_string(&resp).unwrap();
assert!(json.contains("\"type\":\"success\""));
assert!(json.contains("\"running\":2"));
let parsed: Response = serde_json::from_str(&json).unwrap();
match parsed {
Response::Success { id, result } => {
assert_eq!(id, "abc-123");
assert_eq!(result["running"], 2);
}
_ => panic!("expected Success"),
}
}
#[test]
fn test_response_error() {
let resp = Response::error("abc-123".into(), "not found");
let json = serde_json::to_string(&resp).unwrap();
assert!(json.contains("\"type\":\"error\""));
assert!(json.contains("\"error\":\"not found\""));
}
#[test]
fn test_all_methods_serialize() {
let methods = [
(Method::Status, "status"),
(Method::RunList, "run_list"),
(Method::RunShow, "run_show"),
(Method::RunApprove, "run_approve"),
(Method::RunCancel, "run_cancel"),
(Method::WorkflowStart, "workflow_start"),
(Method::WorkflowChain, "workflow_chain"),
(Method::Sweep, "sweep"),
(Method::Stats, "stats"),
(Method::Subscribe, "subscribe"),
(Method::Shutdown, "shutdown"),
];
for (method, expected) in methods {
let json = serde_json::to_string(&method).unwrap();
assert_eq!(json, format!("\"{}\"", expected), "Method {:?}", method);
}
}
}