use std::path::Path;
use serde_json::Value;
use crate::error::Result;
use crate::{WasmSandbox, InstanceConfig};
pub struct SimpleSandbox;
impl SimpleSandbox {
pub async fn run<T, P>(
source_path: P,
function_name: &str,
args: &[Value],
) -> Result<T>
where
T: serde::de::DeserializeOwned + 'static,
P: AsRef<Path>,
{
let config = InstanceConfig::builder()
.memory_limit(crate::config::MemoryUnit::mb(64)) .timeout(30u64) .network_deny_all() .build()?;
Self::run_with_config(source_path, function_name, args, config).await
}
pub async fn run_with_config<T, P>(
source_path: P,
function_name: &str,
args: &[Value],
config: InstanceConfig,
) -> Result<T>
where
T: serde::de::DeserializeOwned + 'static,
P: AsRef<Path>,
{
let mut sandbox = WasmSandbox::new()?;
let wasm_bytes = crate::compile_source_to_wasm(
source_path.as_ref().to_str().ok_or_else(|| crate::Error::InvalidInput {
field: "source_path".to_string(),
reason: "Path contains invalid UTF-8 characters".to_string(),
suggestion: Some("Use a path with valid UTF-8 characters".to_string()),
})?
).await?;
let module_id = sandbox.load_module(&wasm_bytes)?;
let instance_id = sandbox.create_instance(module_id, Some(config))?;
let result: Value = sandbox.call_function(instance_id, function_name, args.to_vec()).await?;
let deserialized = serde_json::from_value(result)?;
Ok(deserialized)
}
pub async fn run_sequence<P>(
source_path: P,
function_calls: &[(&str, Vec<Value>)],
) -> Result<Vec<Value>>
where
P: AsRef<Path>,
{
let config = InstanceConfig::builder()
.memory_limit(crate::config::MemoryUnit::mb(64))
.timeout(30u64)
.network_deny_all()
.build()?;
Self::run_sequence_with_config(source_path, function_calls.iter().map(|(name, args)| (name.to_string(), args.clone())).collect(), config).await
}
pub async fn run_sequence_with_config<P>(
source_path: P,
function_calls: Vec<(String, Vec<Value>)>,
config: InstanceConfig,
) -> Result<Vec<Value>>
where
P: AsRef<Path>,
{
let mut sandbox = WasmSandbox::new()?;
let wasm_bytes = crate::compile_source_to_wasm(
source_path.as_ref().to_str().ok_or_else(|| crate::Error::InvalidInput {
field: "source_path".to_string(),
reason: "Path contains invalid UTF-8 characters".to_string(),
suggestion: Some("Use a path with valid UTF-8 characters".to_string()),
})?
).await?;
let module_id = sandbox.load_module(&wasm_bytes)?;
let instance_id = sandbox.create_instance(module_id, Some(config))?;
let mut results = Vec::new();
for (function_name, args) in function_calls {
let result: Value = sandbox.call_function(instance_id, &function_name, args).await?;
results.push(result);
}
Ok(results)
}
pub async fn create_reusable<P>(source_path: P) -> Result<ReusableSandbox>
where
P: AsRef<Path>,
{
let config = InstanceConfig::builder()
.memory_limit(crate::config::MemoryUnit::mb(64))
.timeout(30u64)
.network_deny_all()
.build()?;
Self::create_reusable_with_config(source_path, config).await
}
pub async fn create_reusable_with_config<P>(
source_path: P,
config: InstanceConfig,
) -> Result<ReusableSandbox>
where
P: AsRef<Path>,
{
let mut sandbox = WasmSandbox::new()?;
let wasm_bytes = crate::compile_source_to_wasm(
source_path.as_ref().to_str().ok_or_else(|| crate::Error::InvalidInput {
field: "source_path".to_string(),
reason: "Path contains invalid UTF-8 characters".to_string(),
suggestion: Some("Use a path with valid UTF-8 characters".to_string()),
})?
).await?;
let module_id = sandbox.load_module(&wasm_bytes)?;
let instance_id = sandbox.create_instance(module_id, Some(config))?;
Ok(ReusableSandbox {
sandbox,
instance_id,
})
}
}
pub struct ReusableSandbox {
sandbox: WasmSandbox,
instance_id: crate::InstanceId,
}
impl ReusableSandbox {
pub async fn call<T>(&mut self, function_name: String, args: Vec<Value>) -> Result<T>
where
T: serde::de::DeserializeOwned + 'static,
{
self.sandbox.call_function(self.instance_id, &function_name, args).await
}
pub fn get_resource_usage(&self) -> Result<crate::monitoring::DetailedResourceUsage> {
self.sandbox.get_instance_resource_usage(self.instance_id)
}
pub async fn reset(&mut self) -> Result<()> {
self.sandbox.reset_instance(self.instance_id)
}
}
pub use SimpleSandbox as simple;
pub async fn run<T, P>(
source_path: P,
function_name: &str,
args: &[Value],
) -> Result<T>
where
T: serde::de::DeserializeOwned + 'static,
P: AsRef<Path>,
{
SimpleSandbox::run(source_path, function_name, args).await
}
pub async fn from_source<P>(source_path: P) -> Result<ReusableSandbox>
where
P: AsRef<Path>,
{
SimpleSandbox::create_reusable(source_path).await
}
pub async fn run_with_config<T, P>(
source_path: P,
function_name: &str,
args: &[Value],
config: InstanceConfig,
) -> Result<T>
where
T: serde::de::DeserializeOwned + 'static,
P: AsRef<Path>,
{
SimpleSandbox::run_with_config(source_path, function_name, args, config).await
}
pub async fn run_sequence<P>(
source_path: P,
function_calls: &[(&str, Vec<Value>)],
) -> Result<Vec<Value>>
where
P: AsRef<Path>,
{
SimpleSandbox::run_sequence(source_path, function_calls).await
}
pub async fn create_reusable<P>(source_path: P) -> Result<ReusableSandbox>
where
P: AsRef<Path>,
{
SimpleSandbox::create_reusable(source_path).await
}