use serde::{Deserialize, Serialize};
use std::path::PathBuf;
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "op", rename_all = "snake_case")]
pub enum ZfsRequest {
CreateTrack { base: PathBuf, name: String },
Snapshot { track: PathBuf, label: String },
DiffFiles { track: PathBuf, since: String },
Promote { track: PathBuf, target: PathBuf },
Destroy { track: PathBuf },
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "status", rename_all = "snake_case")]
pub enum ZfsResponse {
Track { path: PathBuf },
Snap { snap_id: String },
Files { paths: Vec<PathBuf> },
Ok,
Error { message: String },
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn create_track_roundtrip() {
let req = ZfsRequest::CreateTrack {
base: "/pool/data/project".into(),
name: "track-a".into(),
};
let json = serde_json::to_string(&req).unwrap();
let back: ZfsRequest = serde_json::from_str(&json).unwrap();
assert!(matches!(back, ZfsRequest::CreateTrack { .. }));
}
#[test]
fn error_response_roundtrip() {
let resp = ZfsResponse::Error {
message: "zfs: command not found".into(),
};
let json = serde_json::to_string(&resp).unwrap();
let back: ZfsResponse = serde_json::from_str(&json).unwrap();
assert!(matches!(back, ZfsResponse::Error { .. }));
}
#[test]
fn all_request_variants_serialize() {
let reqs = vec![
ZfsRequest::CreateTrack {
base: "/p".into(),
name: "t".into(),
},
ZfsRequest::Snapshot {
track: "/p/t".into(),
label: "base".into(),
},
ZfsRequest::DiffFiles {
track: "/p/t".into(),
since: "mur-base".into(),
},
ZfsRequest::Promote {
track: "/p/t".into(),
target: "/p/main".into(),
},
ZfsRequest::Destroy {
track: "/p/t".into(),
},
];
for req in reqs {
let json = serde_json::to_string(&req).unwrap();
let _back: ZfsRequest = serde_json::from_str(&json).unwrap();
}
}
}