use std::path::PathBuf;
use std::sync::Arc;
use uuid::Uuid;
use crate::error::Result;
use crate::security::{Capabilities, ResourceLimits};
#[derive(Debug, Clone)]
pub struct RuntimeMetrics {
pub compiled_modules: usize,
pub active_instances: usize,
pub total_memory_usage: usize,
pub peak_memory_usage: usize,
pub fuel_consumption_rate: Option<f64>,
pub cache_hit_rate: Option<f64>,
pub last_compilation_time_ms: Option<u64>,
}
#[derive(Debug, Clone)]
pub struct RuntimeConfig {
pub enable_fuel: bool,
pub enable_memory_limits: bool,
pub native_stack_trace: bool,
pub debug_info: bool,
pub compilation_threads: usize,
pub cache_modules: bool,
pub cache_directory: Option<PathBuf>,
}
impl Default for RuntimeConfig {
fn default() -> Self {
Self {
enable_fuel: true,
enable_memory_limits: true,
native_stack_trace: false,
debug_info: false,
compilation_threads: num_cpus::get(),
cache_modules: true,
cache_directory: None,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct ModuleId(Uuid);
impl ModuleId {
pub fn new() -> Self {
Self(Uuid::new_v4())
}
pub fn as_uuid(&self) -> Uuid {
self.0
}
}
impl std::fmt::Display for ModuleId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
impl Default for ModuleId {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum WasmInstanceState {
Created,
Running,
Paused,
Exited(i32),
Crashed,
}
pub trait WasmModule: Send + Sync {
fn id(&self) -> ModuleId;
fn name(&self) -> Option<&str>;
fn size(&self) -> usize;
fn exports(&self) -> Vec<String>;
fn clone_module(&self) -> Box<dyn WasmModule>;
fn as_any(&self) -> &dyn std::any::Any;
}
pub trait WasmInstance: Send + Sync {
fn state(&self) -> WasmInstanceState;
fn memory_usage(&self) -> usize;
fn fuel_usage(&self) -> Option<u64>;
fn reset_fuel(&self) -> Result<()>;
fn add_fuel(&self, fuel: u64) -> Result<()>;
unsafe fn memory_ptr(&self) -> Result<*mut u8>;
fn memory_size(&self) -> usize;
fn function_caller(&self) -> Box<dyn WasmFunctionCaller>;
fn call_simple_function(&self, function_name: &str, params: &[i32]) -> Result<i32>;
}
pub trait WasmFunctionCaller: Send + Sync {
fn call_function_json(
&self,
function_name: &str,
params_json: &str,
) -> Result<String>;
fn call_function_msgpack(
&self,
function_name: &str,
params_msgpack: &[u8],
) -> Result<Vec<u8>>;
fn as_any(&self) -> &dyn std::any::Any;
}
#[allow(async_fn_in_trait)]
pub trait WasmFunctionCallerAsync {
async fn call_function_json_async(
&self,
function_name: &str,
params_json: &str,
) -> Result<String>;
async fn call_function_msgpack_async(
&self,
function_name: &str,
params_msgpack: &[u8],
) -> Result<Vec<u8>>;
}
#[allow(async_fn_in_trait)]
pub trait WasmFunctionCallerExt {
async fn call_function<P, R>(
&self,
function_name: &str,
params: &P,
) -> Result<R>
where
P: serde::Serialize + Send + Sync,
R: for<'de> serde::Deserialize<'de> + Send;
}
impl<T: WasmFunctionCaller + Send + Sync> WasmFunctionCallerExt for T {
async fn call_function<P, R>(
&self,
function_name: &str,
params: &P,
) -> Result<R>
where
P: serde::Serialize + Send + Sync,
R: for<'de> serde::Deserialize<'de> + Send,
{
let params_json = serde_json::to_string(params)?;
let result_json = self.call_function_json(function_name, ¶ms_json)?;
let result = serde_json::from_str(&result_json)?;
Ok(result)
}
}
pub trait WasmRuntime: Send + Sync {
fn initialize(&mut self, config: RuntimeConfig) -> Result<()>;
fn load_module(&self, wasm_bytes: &[u8]) -> Result<Box<dyn WasmModule>>;
fn get_module(&self, id: ModuleId) -> Result<Arc<dyn WasmModule>>;
fn get_module_ids(&self) -> Vec<ModuleId>;
fn create_instance(
&self,
module: &dyn WasmModule,
resources: ResourceLimits,
capabilities: Capabilities,
) -> Result<Box<dyn WasmInstance>>;
fn get_metrics(&self) -> RuntimeMetrics;
fn shutdown(&self) -> Result<()>;
}
pub fn create_runtime(_config: &RuntimeConfig) -> Result<Box<dyn WasmRuntime>> {
#[cfg(feature = "wasmtime-runtime")]
{
Ok(Box::new(crate::runtime::wasmtime::WasmtimeRuntime::new(_config)?))
}
#[cfg(all(feature = "wasmer-runtime", not(feature = "wasmtime-runtime")))]
{
return Ok(Box::new(crate::runtime::wasmer::WasmerRuntime::new()?));
}
#[cfg(not(any(feature = "wasmtime-runtime", feature = "wasmer-runtime")))]
{
return Err(crate::error::Error::RuntimeInitialization(
"No WebAssembly runtime feature is enabled".to_string(),
));
}
}
pub mod wasmtime;
#[cfg(feature = "wasmer-runtime")]
pub mod wasmer;
pub mod wasm_common;
pub mod component;
#[cfg(feature = "wasmtime-runtime")]
pub use self::wasmtime::WasmtimeRuntime;
#[cfg(feature = "wasmer-runtime")]
pub use self::wasmer::WasmerRuntime;