Files
smartfs/rust/crates/smartfs-protocol/src/lib.rs

244 lines
6.6 KiB
Rust

use serde::{Deserialize, Serialize};
// ── IPC envelope types ──────────────────────────────────────────────────────
/// Request from TypeScript (via stdin)
#[derive(Debug, Deserialize)]
pub struct IpcRequest {
pub id: String,
pub method: String,
pub params: serde_json::Value,
}
/// Response to TypeScript (via stdout)
#[derive(Debug, Serialize)]
pub struct IpcResponse {
pub id: String,
pub success: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub result: Option<serde_json::Value>,
#[serde(skip_serializing_if = "Option::is_none")]
pub error: Option<String>,
}
impl IpcResponse {
pub fn ok(id: String, result: serde_json::Value) -> Self {
Self { id, success: true, result: Some(result), error: None }
}
pub fn ok_void(id: String) -> Self {
Self { id, success: true, result: None, error: None }
}
pub fn err(id: String, error: String) -> Self {
Self { id, success: false, result: None, error: Some(error) }
}
}
/// Stream chunk (Rust → TS, before final response)
#[derive(Debug, Serialize)]
pub struct IpcStreamChunk {
pub id: String,
pub stream: bool,
pub data: serde_json::Value,
}
/// Unsolicited event (Rust → TS)
#[derive(Debug, Serialize)]
pub struct IpcEvent {
pub event: String,
pub data: serde_json::Value,
}
// ── Filesystem domain types ─────────────────────────────────────────────────
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct FileStats {
pub size: u64,
pub birthtime: String,
pub mtime: String,
pub atime: String,
#[serde(rename = "isFile")]
pub is_file: bool,
#[serde(rename = "isDirectory")]
pub is_directory: bool,
#[serde(rename = "isSymbolicLink")]
pub is_symbolic_link: bool,
pub mode: u32,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct DirectoryEntry {
pub name: String,
pub path: String,
#[serde(rename = "isFile")]
pub is_file: bool,
#[serde(rename = "isDirectory")]
pub is_directory: bool,
#[serde(rename = "isSymbolicLink")]
pub is_symbolic_link: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub stats: Option<FileStats>,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct WatchEvent {
#[serde(rename = "type")]
pub event_type: String,
pub path: String,
pub timestamp: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub stats: Option<FileStats>,
}
// ── Command parameter types ─────────────────────────────────────────────────
#[derive(Debug, Deserialize)]
pub struct ReadFileParams {
pub path: String,
pub encoding: Option<String>,
}
#[derive(Debug, Deserialize)]
pub struct WriteFileParams {
pub path: String,
pub content: String,
pub atomic: Option<bool>,
pub mode: Option<u32>,
pub encoding: Option<String>,
}
#[derive(Debug, Deserialize)]
pub struct AppendFileParams {
pub path: String,
pub content: String,
pub encoding: Option<String>,
}
#[derive(Debug, Deserialize)]
pub struct PathParams {
pub path: String,
}
#[derive(Debug, Deserialize)]
pub struct CopyMoveParams {
pub from: String,
pub to: String,
pub overwrite: Option<bool>,
#[serde(rename = "preserveTimestamps")]
pub preserve_timestamps: Option<bool>,
}
#[derive(Debug, Deserialize)]
pub struct ListDirectoryParams {
pub path: String,
pub recursive: Option<bool>,
#[serde(rename = "includeStats")]
pub include_stats: Option<bool>,
pub filter: Option<String>,
}
#[derive(Debug, Deserialize)]
pub struct CreateDirectoryParams {
pub path: String,
pub recursive: Option<bool>,
pub mode: Option<u32>,
}
#[derive(Debug, Deserialize)]
pub struct DeleteDirectoryParams {
pub path: String,
pub recursive: Option<bool>,
}
#[derive(Debug, Deserialize)]
pub struct WatchParams {
pub path: String,
pub id: String,
pub recursive: Option<bool>,
}
// ── Batch operations ────────────────────────────────────────────────────────
#[derive(Debug, Deserialize)]
pub struct BatchOp {
#[serde(rename = "type")]
pub op_type: String,
pub path: String,
#[serde(rename = "targetPath")]
pub target_path: Option<String>,
pub content: Option<String>,
pub encoding: Option<String>,
pub atomic: Option<bool>,
pub mode: Option<u32>,
pub overwrite: Option<bool>,
pub recursive: Option<bool>,
}
#[derive(Debug, Serialize)]
pub struct BatchResult {
pub index: usize,
pub success: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub error: Option<String>,
}
#[derive(Debug, Deserialize)]
pub struct BatchParams {
pub operations: Vec<BatchOp>,
}
// ── Transaction operations ──────────────────────────────────────────────────
#[derive(Debug, Deserialize)]
pub struct TransactionOp {
#[serde(rename = "type")]
pub op_type: String,
pub path: String,
#[serde(rename = "targetPath")]
pub target_path: Option<String>,
pub content: Option<String>,
pub encoding: Option<String>,
}
#[derive(Debug, Deserialize)]
pub struct TransactionParams {
pub operations: Vec<TransactionOp>,
}
// ── Path operations ─────────────────────────────────────────────────────────
#[derive(Debug, Deserialize)]
pub struct NormalizePathParams {
pub path: String,
}
#[derive(Debug, Deserialize)]
pub struct JoinPathParams {
pub segments: Vec<String>,
}
// ── Streaming operations ────────────────────────────────────────────────────
#[derive(Debug, Deserialize)]
pub struct ReadFileStreamParams {
pub path: String,
#[serde(rename = "chunkSize")]
pub chunk_size: Option<usize>,
}
#[derive(Debug, Deserialize)]
pub struct WriteStreamBeginParams {
pub path: String,
pub atomic: Option<bool>,
pub mode: Option<u32>,
}
#[derive(Debug, Deserialize)]
pub struct WriteStreamChunkParams {
#[serde(rename = "streamId")]
pub stream_id: String,
pub data: String,
pub last: bool,
}