Skip to main content

wasmsh_protocol/
lib.rs

1//! Message protocol for the wasmsh browser worker bridge.
2//!
3//! Defines versioned, serializable messages exchanged between the host
4//! page and the wasmsh Web Worker.
5//!
6//! ## Protocol version
7//! Current version: `0.1.0`
8
9#![warn(missing_docs)]
10
11/// Protocol version string.
12pub const PROTOCOL_VERSION: &str = "0.1.0";
13
14/// A command sent from the host to the worker.
15#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
16#[non_exhaustive]
17pub enum HostCommand {
18    /// Initialize the shell runtime with optional configuration.
19    Init {
20        /// Maximum step budget per execution (0 = unlimited).
21        step_budget: u64,
22        /// Hostnames/IPs allowed for network access (empty = no network).
23        ///
24        /// Patterns: exact host (`api.example.com`), wildcard (`*.example.com`),
25        /// IP (`192.168.1.100`), host with port (`api.example.com:8080`).
26        #[serde(default)]
27        allowed_hosts: Vec<String>,
28    },
29    /// Execute a shell command string.
30    Run {
31        /// The shell source text to execute.
32        input: String,
33    },
34    /// Cancel the currently running execution.
35    Cancel,
36    /// Mount a virtual filesystem at the given path.
37    Mount {
38        /// Absolute path at which to mount the filesystem.
39        path: String,
40    },
41    /// Read a file from the virtual filesystem.
42    ReadFile {
43        /// Absolute path of the file to read.
44        path: String,
45    },
46    /// Write data to a file in the virtual filesystem.
47    WriteFile {
48        /// Absolute path of the file to write.
49        path: String,
50        /// Raw bytes to write into the file.
51        data: Vec<u8>,
52    },
53    /// List directory contents.
54    ListDir {
55        /// Absolute path of the directory to list.
56        path: String,
57    },
58}
59
60/// An event sent from the worker to the host.
61#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
62#[non_exhaustive]
63pub enum WorkerEvent {
64    /// Shell produced stdout output.
65    Stdout(Vec<u8>),
66    /// Shell produced stderr output.
67    Stderr(Vec<u8>),
68    /// Command execution finished with exit code.
69    Exit(i32),
70    /// A diagnostic message (warning, info, trace).
71    Diagnostic(DiagnosticLevel, String),
72    /// A file in the VFS was changed.
73    FsChanged(String),
74    /// Protocol version announcement (sent on Init).
75    Version(String),
76}
77
78/// Diagnostic severity level.
79#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
80#[non_exhaustive]
81pub enum DiagnosticLevel {
82    /// Informational message.
83    Info,
84    /// Non-fatal warning.
85    Warning,
86    /// Error-level diagnostic.
87    Error,
88    /// Low-level trace output.
89    Trace,
90}
91
92#[cfg(test)]
93mod tests {
94    use super::*;
95
96    #[test]
97    fn protocol_version() {
98        assert!(!PROTOCOL_VERSION.is_empty());
99    }
100
101    #[test]
102    fn host_command_variants() {
103        let cmd = HostCommand::Run {
104            input: "echo hello".into(),
105        };
106        assert!(matches!(cmd, HostCommand::Run { .. }));
107    }
108
109    #[test]
110    fn worker_event_variants() {
111        let evt = WorkerEvent::Exit(0);
112        assert_eq!(evt, WorkerEvent::Exit(0));
113
114        let evt = WorkerEvent::Diagnostic(DiagnosticLevel::Warning, "test".into());
115        assert!(matches!(
116            evt,
117            WorkerEvent::Diagnostic(DiagnosticLevel::Warning, _)
118        ));
119    }
120}