mur_common/
zfs_protocol.rs1use serde::{Deserialize, Serialize};
2use std::path::PathBuf;
3
4#[derive(Debug, Clone, Serialize, Deserialize)]
6#[serde(tag = "op", rename_all = "snake_case")]
7pub enum ZfsRequest {
8 CreateTrack { base: PathBuf, name: String },
9 Snapshot { track: PathBuf, label: String },
10 DiffFiles { track: PathBuf, since: String },
11 Promote { track: PathBuf, target: PathBuf },
12 Destroy { track: PathBuf },
13}
14
15#[derive(Debug, Clone, Serialize, Deserialize)]
17#[serde(tag = "status", rename_all = "snake_case")]
18pub enum ZfsResponse {
19 Track { path: PathBuf },
21 Snap { snap_id: String },
23 Files { paths: Vec<PathBuf> },
25 Ok,
27 Error { message: String },
29}
30
31#[cfg(test)]
32mod tests {
33 use super::*;
34
35 #[test]
36 fn create_track_roundtrip() {
37 let req = ZfsRequest::CreateTrack {
38 base: "/pool/data/project".into(),
39 name: "track-a".into(),
40 };
41 let json = serde_json::to_string(&req).unwrap();
42 let back: ZfsRequest = serde_json::from_str(&json).unwrap();
43 assert!(matches!(back, ZfsRequest::CreateTrack { .. }));
44 }
45
46 #[test]
47 fn error_response_roundtrip() {
48 let resp = ZfsResponse::Error {
49 message: "zfs: command not found".into(),
50 };
51 let json = serde_json::to_string(&resp).unwrap();
52 let back: ZfsResponse = serde_json::from_str(&json).unwrap();
53 assert!(matches!(back, ZfsResponse::Error { .. }));
54 }
55
56 #[test]
57 fn all_request_variants_serialize() {
58 let reqs = vec![
59 ZfsRequest::CreateTrack {
60 base: "/p".into(),
61 name: "t".into(),
62 },
63 ZfsRequest::Snapshot {
64 track: "/p/t".into(),
65 label: "base".into(),
66 },
67 ZfsRequest::DiffFiles {
68 track: "/p/t".into(),
69 since: "mur-base".into(),
70 },
71 ZfsRequest::Promote {
72 track: "/p/t".into(),
73 target: "/p/main".into(),
74 },
75 ZfsRequest::Destroy {
76 track: "/p/t".into(),
77 },
78 ];
79 for req in reqs {
80 let json = serde_json::to_string(&req).unwrap();
81 let _back: ZfsRequest = serde_json::from_str(&json).unwrap();
82 }
83 }
84}