mirror of
https://github.com/extism/extism.git
synced 2026-01-11 14:58:01 -05:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d704a5068e |
@@ -1,7 +1,7 @@
|
||||
use extism::*;
|
||||
|
||||
// pretend this is redis or something :)
|
||||
type KVStore = std::collections::BTreeMap<String, Vec<u8>>;
|
||||
type KVStore = std::sync::Arc<std::sync::Mutex<std::collections::BTreeMap<String, Vec<u8>>>>;
|
||||
|
||||
// When a first argument separated with a semicolon is provided to `host_fn` it is used as the
|
||||
// variable name and type for the `UserData` parameter
|
||||
|
||||
@@ -81,18 +81,18 @@ pub(crate) enum UserDataHandle {
|
||||
/// using `UserData::get`. The `C` data is stored as a pointer and cleanup function and isn't usable from Rust. The cleanup function
|
||||
/// will be called when the inner `CPtr` is dropped.
|
||||
#[derive(Debug)]
|
||||
pub enum UserData<T: Sized> {
|
||||
pub enum UserData<T: Sync + Clone + Sized> {
|
||||
C(Arc<CPtr>),
|
||||
Rust(Arc<std::sync::Mutex<T>>),
|
||||
Rust(T),
|
||||
}
|
||||
|
||||
impl<T: Default> Default for UserData<T> {
|
||||
impl<T: Default + Sync + Clone> Default for UserData<T> {
|
||||
fn default() -> Self {
|
||||
UserData::new(T::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Clone for UserData<T> {
|
||||
impl<T: Sync + Clone> Clone for UserData<T> {
|
||||
fn clone(&self) -> Self {
|
||||
match self {
|
||||
UserData::C(ptr) => UserData::C(ptr.clone()),
|
||||
@@ -101,7 +101,7 @@ impl<T> Clone for UserData<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> UserData<T> {
|
||||
impl<T: Sync + Clone> UserData<T> {
|
||||
/// Create a new `UserData` from an existing pointer and free function, this is used
|
||||
/// by the C API to wrap C pointers into user data
|
||||
pub(crate) fn new_pointer(
|
||||
@@ -126,12 +126,11 @@ impl<T> UserData<T> {
|
||||
///
|
||||
/// This will wrap the provided value in a reference-counted mutex
|
||||
pub fn new(x: T) -> Self {
|
||||
let data = Arc::new(std::sync::Mutex::new(x));
|
||||
UserData::Rust(data)
|
||||
UserData::Rust(x)
|
||||
}
|
||||
|
||||
/// Get a copy of the inner value
|
||||
pub fn get(&self) -> Result<Arc<std::sync::Mutex<T>>, Error> {
|
||||
pub fn get(&self) -> Result<T, Error> {
|
||||
match self {
|
||||
UserData::C { .. } => anyhow::bail!("C UserData should not be used from Rust"),
|
||||
UserData::Rust(data) => Ok(data.clone()),
|
||||
@@ -150,8 +149,8 @@ impl Drop for CPtr {
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<T> Send for UserData<T> {}
|
||||
unsafe impl<T> Sync for UserData<T> {}
|
||||
unsafe impl<T: Sync + Clone> Send for UserData<T> {}
|
||||
unsafe impl<T: Sync + Clone> Sync for UserData<T> {}
|
||||
unsafe impl Send for CPtr {}
|
||||
unsafe impl Sync for CPtr {}
|
||||
|
||||
@@ -180,7 +179,7 @@ pub struct Function {
|
||||
|
||||
impl Function {
|
||||
/// Create a new host function
|
||||
pub fn new<T: 'static, F>(
|
||||
pub fn new<T: 'static + Sync + Clone, F>(
|
||||
name: impl Into<String>,
|
||||
args: impl IntoIterator<Item = ValType>,
|
||||
returns: impl IntoIterator<Item = ValType>,
|
||||
@@ -211,7 +210,9 @@ impl Function {
|
||||
namespace: None,
|
||||
_user_data: match &user_data {
|
||||
UserData::C(ptr) => UserDataHandle::C(ptr.clone()),
|
||||
UserData::Rust(x) => UserDataHandle::Rust(x.clone()),
|
||||
UserData::Rust(x) => {
|
||||
UserDataHandle::Rust(std::sync::Arc::new(std::sync::Mutex::new(x.clone())))
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ impl<'a> PluginBuilder<'a> {
|
||||
}
|
||||
|
||||
/// Add a single host function
|
||||
pub fn with_function<T: 'static, F>(
|
||||
pub fn with_function<T: Sync + Clone + 'static, F>(
|
||||
mut self,
|
||||
name: impl Into<String>,
|
||||
args: impl IntoIterator<Item = ValType>,
|
||||
@@ -80,7 +80,7 @@ impl<'a> PluginBuilder<'a> {
|
||||
}
|
||||
|
||||
/// Add a single host function in a specific namespace
|
||||
pub fn with_function_in_namespace<T: 'static, F>(
|
||||
pub fn with_function_in_namespace<T: Sync + Clone + 'static, F>(
|
||||
mut self,
|
||||
namespace: impl Into<String>,
|
||||
name: impl Into<String>,
|
||||
|
||||
@@ -453,7 +453,7 @@ fn hello_world_user_data(
|
||||
_plugin: &mut CurrentPlugin,
|
||||
inputs: &[Val],
|
||||
outputs: &mut [Val],
|
||||
user_data: UserData<std::fs::File>,
|
||||
user_data: UserData<std::sync::Arc<std::sync::Mutex<std::fs::File>>>,
|
||||
) -> Result<(), Error> {
|
||||
let data = user_data.get()?;
|
||||
let mut data = data.lock().unwrap();
|
||||
@@ -470,7 +470,8 @@ fn test_userdata() {
|
||||
if path.exists() {
|
||||
std::fs::remove_file(&path).unwrap();
|
||||
}
|
||||
let file = std::fs::File::create(&path).unwrap();
|
||||
let file =
|
||||
std::sync::Arc::new(std::sync::Mutex::new(std::fs::File::create(&path).unwrap()));
|
||||
let f = Function::new(
|
||||
"hello_world",
|
||||
[PTR],
|
||||
|
||||
Reference in New Issue
Block a user