various: simplify code; work on security and performance
Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: I9a5114addcab5fbff430ab2b919b83466a6a6964
This commit is contained in:
parent
016841b200
commit
c4adc4e3e0
75 changed files with 12921 additions and 358 deletions
186
crates/pinakes-plugin-api/src/wasm.rs
Normal file
186
crates/pinakes-plugin-api/src/wasm.rs
Normal 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"),
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue