1use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, Serialize, Deserialize)]
7pub struct IpcMessage {
8 pub id: String,
10 pub payload: IpcPayload,
12}
13
14#[derive(Debug, Clone, Serialize, Deserialize)]
16#[serde(tag = "type", rename_all = "snake_case")]
17pub enum IpcPayload {
18 Request(IpcRequest),
20 Response(IpcResponse),
22 Event(IpcEvent),
24}
25
26#[derive(Debug, Clone, Serialize, Deserialize)]
28pub struct IpcRequest {
29 pub method: String,
31 pub params: serde_json::Value,
33}
34
35#[derive(Debug, Clone, Serialize, Deserialize)]
37pub struct IpcResponse {
38 pub success: bool,
40 pub result: Option<serde_json::Value>,
42 pub error: Option<String>,
44}
45
46#[derive(Debug, Clone, Serialize, Deserialize)]
48pub struct IpcEvent {
49 pub event_type: String,
51 pub data: serde_json::Value,
53}
54
55impl IpcMessage {
56 #[must_use]
58 pub fn request(method: impl Into<String>, params: serde_json::Value) -> Self {
59 Self {
60 id: uuid_v4(),
61 payload: IpcPayload::Request(IpcRequest {
62 method: method.into(),
63 params,
64 }),
65 }
66 }
67
68 #[must_use]
70 pub fn success(id: impl Into<String>, result: serde_json::Value) -> Self {
71 Self {
72 id: id.into(),
73 payload: IpcPayload::Response(IpcResponse {
74 success: true,
75 result: Some(result),
76 error: None,
77 }),
78 }
79 }
80
81 #[must_use]
83 pub fn error(id: impl Into<String>, error: impl Into<String>) -> Self {
84 Self {
85 id: id.into(),
86 payload: IpcPayload::Response(IpcResponse {
87 success: false,
88 result: None,
89 error: Some(error.into()),
90 }),
91 }
92 }
93
94 #[must_use]
96 pub fn event(event_type: impl Into<String>, data: serde_json::Value) -> Self {
97 Self {
98 id: uuid_v4(),
99 payload: IpcPayload::Event(IpcEvent {
100 event_type: event_type.into(),
101 data,
102 }),
103 }
104 }
105}
106
107fn uuid_v4() -> String {
109 let bytes: [u8; 16] = rand::random();
110 format!(
111 "{:02x}{:02x}{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}",
112 bytes[0],
113 bytes[1],
114 bytes[2],
115 bytes[3],
116 bytes[4],
117 bytes[5],
118 (bytes[6] & 0x0f) | 0x40,
119 bytes[7],
120 (bytes[8] & 0x3f) | 0x80,
121 bytes[9],
122 bytes[10],
123 bytes[11],
124 bytes[12],
125 bytes[13],
126 bytes[14],
127 bytes[15]
128 )
129}
130
131#[cfg(test)]
132mod tests {
133 use super::*;
134
135 #[test]
136 fn test_request_message() {
137 let msg = IpcMessage::request("test.method", serde_json::json!({"key": "value"}));
138 assert!(!msg.id.is_empty());
139 if let IpcPayload::Request(req) = msg.payload {
140 assert_eq!(req.method, "test.method");
141 } else {
142 panic!("Expected request payload");
143 }
144 }
145
146 #[test]
147 fn test_success_response() {
148 let msg = IpcMessage::success("123", serde_json::json!({"result": true}));
149 if let IpcPayload::Response(resp) = msg.payload {
150 assert!(resp.success);
151 assert!(resp.result.is_some());
152 } else {
153 panic!("Expected response payload");
154 }
155 }
156}