use rkyv::{Archive, Deserialize, Serialize};
use serde::{Deserialize as SerdeDeserialize, Serialize as SerdeSerialize};
use crate::IPC_SCHEMA_VERSION;
#[derive(Archive, Serialize, Deserialize, Debug, Clone)]
#[rkyv(derive(Debug))]
pub struct IpcRequest {
pub ipc_schema_version: u32,
pub request_id: String,
pub repo_root: String,
pub actor_id: String,
pub data_dir: String,
pub command: IpcCommand,
}
impl IpcRequest {
pub fn new(
request_id: String,
repo_root: String,
actor_id: String,
data_dir: String,
command: IpcCommand,
) -> Self {
Self {
ipc_schema_version: IPC_SCHEMA_VERSION,
request_id,
repo_root,
actor_id,
data_dir,
command,
}
}
}
#[derive(Archive, Serialize, Deserialize, Debug, Clone)]
#[rkyv(derive(Debug))]
pub struct IpcResponse {
pub ipc_schema_version: u32,
pub request_id: String,
pub ok: bool,
pub data: Option<String>,
pub error: Option<IpcErrorPayload>,
}
impl IpcResponse {
pub fn success(request_id: String, data: Option<String>) -> Self {
Self {
ipc_schema_version: IPC_SCHEMA_VERSION,
request_id,
ok: true,
data,
error: None,
}
}
pub fn error(request_id: String, code: String, message: String) -> Self {
Self {
ipc_schema_version: IPC_SCHEMA_VERSION,
request_id,
ok: false,
data: None,
error: Some(IpcErrorPayload {
code,
message,
details: None,
}),
}
}
}
#[derive(Archive, Serialize, Deserialize, Debug, Clone, SerdeSerialize, SerdeDeserialize)]
#[rkyv(derive(Debug))]
pub struct IpcErrorPayload {
pub code: String,
pub message: String,
pub details: Option<String>,
}
#[derive(Archive, Serialize, Deserialize, Debug, Clone)]
#[rkyv(derive(Debug))]
pub enum IpcCommand {
IssueCreate {
title: String,
body: String,
labels: Vec<String>,
},
IssueList {
state: Option<String>,
label: Option<String>,
},
IssueShow {
issue_id: String,
},
IssueUpdate {
issue_id: String,
title: Option<String>,
body: Option<String>,
},
IssueComment {
issue_id: String,
body: String,
},
IssueLabel {
issue_id: String,
add: Vec<String>,
remove: Vec<String>,
},
IssueAssign {
issue_id: String,
add: Vec<String>,
remove: Vec<String>,
},
IssueClose {
issue_id: String,
},
IssueReopen {
issue_id: String,
},
IssueLink {
issue_id: String,
url: String,
note: Option<String>,
},
IssueAttach {
issue_id: String,
file_path: String,
},
IssueDepAdd {
issue_id: String,
target_id: String,
dep_type: String,
},
IssueDepRemove {
issue_id: String,
target_id: String,
dep_type: String,
},
IssueDepList {
issue_id: String,
reverse: bool,
},
IssueDepTopo {
state: Option<String>,
label: Option<String>,
},
DbStats,
Export {
format: String,
since: Option<String>,
},
Rebuild,
Sync {
remote: String,
pull: bool,
push: bool,
},
SnapshotCreate,
SnapshotList,
SnapshotGc {
keep: u32,
},
DaemonStatus,
DaemonStop,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_request_creation() {
let req = IpcRequest::new(
"test-123".to_string(),
"/path/to/repo".to_string(),
"abcd1234".to_string(),
".git/grite/actors/abcd1234".to_string(),
IpcCommand::IssueList {
state: Some("open".to_string()),
label: None,
},
);
assert_eq!(req.ipc_schema_version, IPC_SCHEMA_VERSION);
assert_eq!(req.request_id, "test-123");
}
#[test]
fn test_response_success() {
let resp = IpcResponse::success(
"test-123".to_string(),
Some(r#"{"issues": []}"#.to_string()),
);
assert!(resp.ok);
assert!(resp.error.is_none());
assert!(resp.data.is_some());
}
#[test]
fn test_response_error() {
let resp = IpcResponse::error(
"test-123".to_string(),
"not_found".to_string(),
"Issue not found".to_string(),
);
assert!(!resp.ok);
assert!(resp.data.is_none());
assert!(resp.error.is_some());
assert_eq!(resp.error.as_ref().unwrap().code, "not_found");
}
#[test]
fn test_rkyv_roundtrip() {
let req = IpcRequest::new(
"test-456".to_string(),
"/repo".to_string(),
"actor123".to_string(),
".git/grite/actors/actor123".to_string(),
IpcCommand::IssueCreate {
title: "Test Issue".to_string(),
body: "Description".to_string(),
labels: vec!["bug".to_string()],
},
);
let bytes = rkyv::to_bytes::<rkyv::rancor::Error>(&req).unwrap();
let archived = rkyv::access::<ArchivedIpcRequest, rkyv::rancor::Error>(&bytes).unwrap();
assert_eq!(archived.request_id, "test-456");
assert_eq!(archived.ipc_schema_version, IPC_SCHEMA_VERSION);
}
}