various: simplify code; work on security and performance

Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: I9a5114addcab5fbff430ab2b919b83466a6a6964
This commit is contained in:
raf 2026-02-02 17:32:11 +03:00
commit c4adc4e3e0
Signed by: NotAShelf
GPG key ID: 29D95B64378DB4BF
75 changed files with 12921 additions and 358 deletions

View file

@ -0,0 +1,186 @@
//! WASM bridge types and helpers for plugin communication
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
/// Memory allocation info for passing data between host and plugin
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WasmMemoryAlloc {
/// Pointer to allocated memory
pub ptr: u32,
/// Size of allocation in bytes
pub len: u32,
}
/// Request from host to plugin
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HostRequest {
/// Request ID for matching with response
pub request_id: String,
/// Method name being called
pub method: String,
/// Serialized parameters
pub params: Vec<u8>,
}
/// Response from plugin to host
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PluginResponse {
/// Request ID this response corresponds to
pub request_id: String,
/// Success or error
pub result: WasmResult<Vec<u8>>,
}
/// Result type for WASM operations
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum WasmResult<T> {
Ok(T),
Err(String),
}
impl<T> From<Result<T, String>> for WasmResult<T> {
fn from(r: Result<T, String>) -> Self {
match r {
Ok(v) => WasmResult::Ok(v),
Err(e) => WasmResult::Err(e),
}
}
}
/// Host functions available to plugins
pub mod host_functions {
/// Log a message from plugin
pub const LOG: &str = "host_log";
/// Read a file (if permitted)
pub const READ_FILE: &str = "host_read_file";
/// Write a file (if permitted)
pub const WRITE_FILE: &str = "host_write_file";
/// Make an HTTP request (if permitted)
pub const HTTP_REQUEST: &str = "host_http_request";
/// Get configuration value
pub const GET_CONFIG: &str = "host_get_config";
/// Emit an event
pub const EMIT_EVENT: &str = "host_emit_event";
}
/// Log level for plugin logging
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub enum LogLevel {
Trace,
Debug,
Info,
Warn,
Error,
}
/// Log message from plugin
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LogMessage {
pub level: LogLevel,
pub target: String,
pub message: String,
pub fields: HashMap<String, String>,
}
/// HTTP request parameters
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HttpRequest {
pub method: String,
pub url: String,
pub headers: HashMap<String, String>,
pub body: Option<Vec<u8>>,
}
/// HTTP response
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HttpResponse {
pub status: u16,
pub headers: HashMap<String, String>,
pub body: Vec<u8>,
}
/// Helper functions for serializing/deserializing data across WASM boundary
pub mod helpers {
use super::*;
/// Serialize a value to bytes for passing to WASM
pub fn serialize<T: Serialize>(value: &T) -> Result<Vec<u8>, String> {
serde_json::to_vec(value).map_err(|e| format!("Serialization error: {}", e))
}
/// Deserialize bytes from WASM to a value
pub fn deserialize<T: for<'de> Deserialize<'de>>(bytes: &[u8]) -> Result<T, String> {
serde_json::from_slice(bytes).map_err(|e| format!("Deserialization error: {}", e))
}
/// Create a success response
pub fn ok_response<T: Serialize>(request_id: String, value: &T) -> Result<Vec<u8>, String> {
let result = WasmResult::Ok(serialize(value)?);
let response = PluginResponse { request_id, result };
serialize(&response)
}
/// Create an error response
pub fn error_response(request_id: String, error: String) -> Result<Vec<u8>, String> {
let result = WasmResult::<Vec<u8>>::Err(error);
let response = PluginResponse { request_id, result };
serialize(&response)
}
}
#[cfg(test)]
mod tests {
use super::helpers::*;
use super::*;
#[test]
fn test_serialize_deserialize() {
let data = vec![1u8, 2, 3, 4];
let bytes = serialize(&data).unwrap();
let recovered: Vec<u8> = deserialize(&bytes).unwrap();
assert_eq!(data, recovered);
}
#[test]
fn test_ok_response() {
let request_id = "test-123".to_string();
let value = "success";
let response_bytes = ok_response(request_id.clone(), &value).unwrap();
let response: PluginResponse = deserialize(&response_bytes).unwrap();
assert_eq!(response.request_id, request_id);
match response.result {
WasmResult::Ok(data) => {
let recovered: String = deserialize(&data).unwrap();
assert_eq!(recovered, value);
}
WasmResult::Err(_) => panic!("Expected Ok result"),
}
}
#[test]
fn test_error_response() {
let request_id = "test-456".to_string();
let error_msg = "Something went wrong";
let response_bytes = error_response(request_id.clone(), error_msg.to_string()).unwrap();
let response: PluginResponse = deserialize(&response_bytes).unwrap();
assert_eq!(response.request_id, request_id);
match response.result {
WasmResult::Err(msg) => assert_eq!(msg, error_msg),
WasmResult::Ok(_) => panic!("Expected Err result"),
}
}
}