mirror of
https://github.com/extism/extism.git
synced 2026-01-11 14:58:01 -05:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7230657f6f | ||
|
|
de81040c99 | ||
|
|
b79e74d516 |
@@ -9,7 +9,7 @@ repository.workspace = true
|
||||
version.workspace = true
|
||||
|
||||
[dependencies]
|
||||
wasmtime = { version = ">= 27.0.0, < 31.0.0", default-features = false, features = [
|
||||
wasmtime = { version="37", default-features = false, features = [
|
||||
'cache',
|
||||
'gc',
|
||||
'gc-drc',
|
||||
@@ -20,8 +20,8 @@ wasmtime = { version = ">= 27.0.0, < 31.0.0", default-features = false, features
|
||||
'pooling-allocator',
|
||||
'demangle',
|
||||
] }
|
||||
wasi-common = { version = ">= 27.0.0, < 31.0.0" }
|
||||
wiggle = { version = ">= 27.0.0, < 31.0.0" }
|
||||
wasi-common = "37"
|
||||
wiggle = "37"
|
||||
anyhow = "1"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
@@ -43,18 +43,20 @@ libc = "0.2"
|
||||
|
||||
[features]
|
||||
default = ["http", "register-http", "register-filesystem", "wasmtime-default-features"]
|
||||
register-http = ["ureq"] # enables wasm to be downloaded using http
|
||||
register-filesystem = [] # enables wasm to be loaded from disk
|
||||
http = ["ureq"] # enables extism_http_request
|
||||
register-http = ["ureq"] # enables wasm to be downloaded using http
|
||||
register-filesystem = [] # enables wasm to be loaded from disk
|
||||
http = ["ureq"] # enables extism_http_request
|
||||
wasmtime-exceptions = [] # enables exception-handling proposal in wasmtime (requires wasmtime gc feature)
|
||||
wasmtime-default-features = [
|
||||
'wasmtime/default',
|
||||
]
|
||||
|
||||
|
||||
[build-dependencies]
|
||||
cbindgen = { version = "0.29", default-features = false }
|
||||
|
||||
[dev-dependencies]
|
||||
criterion = "0.6.0"
|
||||
criterion = "0.7.0"
|
||||
quickcheck = "1"
|
||||
rand = "0.9.0"
|
||||
|
||||
|
||||
@@ -191,6 +191,17 @@ ExtismCompiledPlugin *extism_compiled_plugin_new(const uint8_t *wasm,
|
||||
bool with_wasi,
|
||||
char **errmsg);
|
||||
|
||||
/**
|
||||
* Pre-compile an Extism plugin and set the number of instructions a plugin is allowed to execute
|
||||
*/
|
||||
ExtismCompiledPlugin *extism_compiled_plugin_new_with_fuel_limit(const uint8_t *wasm,
|
||||
ExtismSize wasm_size,
|
||||
const ExtismFunction **functions,
|
||||
ExtismSize n_functions,
|
||||
bool with_wasi,
|
||||
uint64_t fuel_limit,
|
||||
char **errmsg);
|
||||
|
||||
/**
|
||||
* Free `ExtismCompiledPlugin`
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use std::{
|
||||
any::Any,
|
||||
collections::{BTreeMap, BTreeSet},
|
||||
path::PathBuf,
|
||||
sync::TryLockError,
|
||||
};
|
||||
|
||||
@@ -60,26 +61,16 @@ impl CompiledPlugin {
|
||||
.wasm_tail_call(true)
|
||||
.wasm_function_references(true)
|
||||
.wasm_gc(true);
|
||||
#[cfg(feature = "wasmtime-exceptions")]
|
||||
{
|
||||
config.wasm_exceptions(true);
|
||||
}
|
||||
|
||||
if builder.options.fuel.is_some() {
|
||||
config.consume_fuel(true);
|
||||
}
|
||||
|
||||
match &builder.options.cache_config {
|
||||
Some(None) => (),
|
||||
Some(Some(path)) => {
|
||||
config.cache_config_load(path)?;
|
||||
}
|
||||
None => {
|
||||
if let Ok(env) = std::env::var("EXTISM_CACHE_CONFIG") {
|
||||
if !env.is_empty() {
|
||||
config.cache_config_load(&env)?;
|
||||
}
|
||||
} else {
|
||||
config.cache_config_load_default()?;
|
||||
}
|
||||
}
|
||||
}
|
||||
config.cache(Self::configure_cache(&builder.options.cache_config)?);
|
||||
|
||||
let engine = Engine::new(&config)?;
|
||||
|
||||
@@ -97,6 +88,43 @@ impl CompiledPlugin {
|
||||
engine,
|
||||
})
|
||||
}
|
||||
|
||||
/// Return optional cache according to builder options.
|
||||
fn configure_cache(
|
||||
cache_opt: &Option<Option<std::path::PathBuf>>,
|
||||
) -> Result<Option<wasmtime::Cache>, Error> {
|
||||
match cache_opt {
|
||||
// Explicitly disabled
|
||||
Some(None) => Ok(None),
|
||||
|
||||
// Explicit path
|
||||
Some(Some(p)) => {
|
||||
let cache = wasmtime::Cache::from_file(Some(p.as_path()))?;
|
||||
Ok(Some(cache))
|
||||
}
|
||||
|
||||
// Unspecified, try environment, then system fallback
|
||||
None => {
|
||||
match std::env::var_os("EXTISM_CACHE_CONFIG") {
|
||||
Some(val) => {
|
||||
if val.is_empty() {
|
||||
// Disable cache if env var exists but is empty
|
||||
Ok(None)
|
||||
} else {
|
||||
let p = PathBuf::from(val);
|
||||
let cache = wasmtime::Cache::from_file(Some(p.as_path()))?;
|
||||
Ok(Some(cache))
|
||||
}
|
||||
}
|
||||
None => {
|
||||
// load cache configuration from the system default path
|
||||
let cache = wasmtime::Cache::from_file(None)?;
|
||||
Ok(Some(cache))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Plugin contains everything needed to execute a WASM function
|
||||
@@ -344,6 +372,7 @@ fn relink(
|
||||
let (kind, ty) = match import.ty() {
|
||||
ExternType::Func(t) => ("function", t.to_string()),
|
||||
ExternType::Global(t) => ("global", t.content().to_string()),
|
||||
ExternType::Tag(t) => ("tag", t.ty().to_string()),
|
||||
ExternType::Table(t) => ("table", t.element().to_string()),
|
||||
ExternType::Memory(_) => ("memory", String::new()),
|
||||
};
|
||||
|
||||
@@ -49,7 +49,7 @@ impl PoolPlugin {
|
||||
}
|
||||
|
||||
/// Access the underlying plugin
|
||||
pub fn plugin(&self) -> std::cell::RefMut<Plugin> {
|
||||
pub fn plugin(&self) -> std::cell::RefMut<'_, Plugin> {
|
||||
self.0.borrow_mut()
|
||||
}
|
||||
|
||||
|
||||
@@ -363,6 +363,70 @@ pub unsafe extern "C" fn extism_compiled_plugin_new(
|
||||
})
|
||||
}
|
||||
|
||||
/// Pre-compile an Extism plugin and set the number of instructions a plugin is allowed to execute
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn extism_compiled_plugin_new_with_fuel_limit(
|
||||
wasm: *const u8,
|
||||
wasm_size: Size,
|
||||
functions: *mut *const ExtismFunction,
|
||||
n_functions: Size,
|
||||
with_wasi: bool,
|
||||
fuel_limit: u64,
|
||||
errmsg: *mut *mut std::ffi::c_char,
|
||||
) -> *mut CompiledPlugin {
|
||||
trace!("Call to extism_plugin_new with wasm pointer {:?}", wasm);
|
||||
let data = std::slice::from_raw_parts(wasm, wasm_size as usize);
|
||||
|
||||
let mut builder = PluginBuilder::new(data)
|
||||
.with_wasi(with_wasi)
|
||||
.with_fuel_limit(fuel_limit);
|
||||
|
||||
if !functions.is_null() {
|
||||
let funcs = (0..n_functions)
|
||||
.map(|i| unsafe { *functions.add(i as usize) })
|
||||
.map(|ptr| {
|
||||
if ptr.is_null() {
|
||||
return Err("Cannot pass null pointer");
|
||||
}
|
||||
|
||||
let ExtismFunction(func) = &*ptr;
|
||||
let Some(func) = func.take() else {
|
||||
return Err("Function cannot be registered with multiple different Plugins");
|
||||
};
|
||||
|
||||
Ok(func)
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
.unwrap_or_else(|e| {
|
||||
if !errmsg.is_null() {
|
||||
let e = std::ffi::CString::new(e.to_string()).unwrap();
|
||||
*errmsg = e.into_raw();
|
||||
}
|
||||
Vec::new()
|
||||
});
|
||||
|
||||
if funcs.len() != n_functions as usize {
|
||||
return std::ptr::null_mut();
|
||||
}
|
||||
|
||||
builder = builder.with_functions(funcs);
|
||||
}
|
||||
|
||||
CompiledPlugin::new(builder)
|
||||
.map(|v| Box::into_raw(Box::new(v)))
|
||||
.unwrap_or_else(|e| {
|
||||
if !errmsg.is_null() {
|
||||
let e = std::ffi::CString::new(format!(
|
||||
"Unable to compile Extism plugin: {}",
|
||||
e.root_cause(),
|
||||
))
|
||||
.unwrap();
|
||||
*errmsg = e.into_raw();
|
||||
}
|
||||
std::ptr::null_mut()
|
||||
})
|
||||
}
|
||||
|
||||
/// Free `ExtismCompiledPlugin`
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn extism_compiled_plugin_free(plugin: *mut CompiledPlugin) {
|
||||
|
||||
Reference in New Issue
Block a user