mirror of
https://github.com/zed-industries/zed.git
synced 2025-01-10 12:36:11 +00:00
WIP: wrap async closures host-side
This commit is contained in:
parent
f110945fd6
commit
31e3a4d208
2 changed files with 173 additions and 2 deletions
|
@ -20,6 +20,12 @@ mod tests {
|
||||||
imports: WasiFn<u32, u32>,
|
imports: WasiFn<u32, u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn half(a: u32) -> u32 {
|
||||||
|
a / 2
|
||||||
|
}
|
||||||
|
|
||||||
|
let x = half;
|
||||||
|
|
||||||
async {
|
async {
|
||||||
let mut runtime = WasiPluginBuilder::new_with_default_ctx()
|
let mut runtime = WasiPluginBuilder::new_with_default_ctx()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
@ -31,6 +37,8 @@ mod tests {
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.host_function("import_swap", |(a, b): (u32, u32)| (b, a))
|
.host_function("import_swap", |(a, b): (u32, u32)| (b, a))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
// .host_function_async("import_half", half)
|
||||||
|
// .unwrap()
|
||||||
.init(include_bytes!("../../../plugins/bin/test_plugin.wasm"))
|
.init(include_bytes!("../../../plugins/bin/test_plugin.wasm"))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
|
@ -79,11 +79,153 @@ impl WasiPluginBuilder {
|
||||||
Self::new(wasi_ctx)
|
Self::new(wasi_ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn host_function<A: DeserializeOwned + Send, R: Serialize + Send + Sync + Clone>(
|
// pub fn host_function_async<A: DeserializeOwned + Send, R: Serialize, F, Fut>(
|
||||||
|
// mut self,
|
||||||
|
// name: &str,
|
||||||
|
// function: impl Fn(A) -> Pin<Box<dyn Future<Output = R> + Send + Sync>> + Sync + Send + 'static,
|
||||||
|
// ) -> Result<Self, Error>
|
||||||
|
// where
|
||||||
|
// A: DeserializeOwned + Send,
|
||||||
|
// R: Serialize + Send,
|
||||||
|
// {
|
||||||
|
// self.linker.func_wrap1_async(
|
||||||
|
// "env",
|
||||||
|
// &format!("__{}", name),
|
||||||
|
// move |caller: Caller<'_, WasiCtxAlloc>, packed_buffer: u64| {
|
||||||
|
// // let function = &function;
|
||||||
|
// Box::new(async move {
|
||||||
|
// // grab a handle to the memory
|
||||||
|
// let mut plugin_memory = match caller.get_export("memory") {
|
||||||
|
// Some(Extern::Memory(mem)) => mem,
|
||||||
|
// _ => return Err(Trap::new("Could not grab slice of plugin memory"))?,
|
||||||
|
// };
|
||||||
|
|
||||||
|
// let buffer = WasiBuffer::from_u64(packed_buffer);
|
||||||
|
|
||||||
|
// // get the args passed from Guest
|
||||||
|
// let args = Wasi::buffer_to_type(&mut plugin_memory, &mut caller, &buffer)?;
|
||||||
|
|
||||||
|
// // Call the Host-side function
|
||||||
|
// let result: R = function(args).await;
|
||||||
|
|
||||||
|
// // Serialize the result back to guest
|
||||||
|
// let result = Wasi::serialize_to_bytes(result).map_err(|_| {
|
||||||
|
// Trap::new("Could not serialize value returned from function")
|
||||||
|
// })?;
|
||||||
|
|
||||||
|
// // Ok((buffer, plugin_memory, result))
|
||||||
|
// Wasi::buffer_to_free(caller.data().free_buffer(), &mut caller, buffer).await?;
|
||||||
|
|
||||||
|
// let buffer = Wasi::bytes_to_buffer(
|
||||||
|
// caller.data().alloc_buffer(),
|
||||||
|
// &mut plugin_memory,
|
||||||
|
// &mut caller,
|
||||||
|
// result,
|
||||||
|
// )
|
||||||
|
// .await?;
|
||||||
|
|
||||||
|
// Ok(buffer.into_u64())
|
||||||
|
// })
|
||||||
|
// },
|
||||||
|
// )?;
|
||||||
|
// Ok(self)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// pub fn host_function_async<F>(mut self, name: &str, function: F) -> Result<Self, Error>
|
||||||
|
// where
|
||||||
|
// F: Fn(u64) -> Pin<Box<dyn Future<Output = u64> + Send + Sync + 'static>>
|
||||||
|
// + Send
|
||||||
|
// + Sync
|
||||||
|
// + 'static,
|
||||||
|
// {
|
||||||
|
// self.linker.func_wrap1_async(
|
||||||
|
// "env",
|
||||||
|
// &format!("__{}", name),
|
||||||
|
// move |_: Caller<'_, WasiCtxAlloc>, _: u64| {
|
||||||
|
// // let function = &function;
|
||||||
|
// Box::new(async {
|
||||||
|
// let function = function;
|
||||||
|
// // Call the Host-side function
|
||||||
|
// let result: u64 = function(7).await;
|
||||||
|
// Ok(result)
|
||||||
|
// })
|
||||||
|
// },
|
||||||
|
// )?;
|
||||||
|
// Ok(self)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// pub fn host_function_async<F, A, R>(mut self, name: &str, function: F) -> Result<Self, Error>
|
||||||
|
// where
|
||||||
|
// F: Fn(A) -> Pin<Box<dyn Future<Output = R> + Send + 'static>> + Send + Sync + 'static,
|
||||||
|
// A: DeserializeOwned + Send,
|
||||||
|
// R: Serialize + Send + Sync,
|
||||||
|
// {
|
||||||
|
// self.linker.func_wrap1_async(
|
||||||
|
// "env",
|
||||||
|
// &format!("__{}", name),
|
||||||
|
// move |mut caller: Caller<'_, WasiCtxAlloc>, packed_buffer: u64| {
|
||||||
|
// let function = |args: Vec<u8>| {
|
||||||
|
// let args = args;
|
||||||
|
// let args: A = Wasi::deserialize_to_type(&args)?;
|
||||||
|
// Ok(async {
|
||||||
|
// let result = function(args);
|
||||||
|
// Wasi::serialize_to_bytes(result.await).map_err(|_| {
|
||||||
|
// Trap::new("Could not serialize value returned from function").into()
|
||||||
|
// })
|
||||||
|
// })
|
||||||
|
// };
|
||||||
|
|
||||||
|
// // TODO: use try block once avaliable
|
||||||
|
// let result: Result<(WasiBuffer, Memory, _), Trap> = (|| {
|
||||||
|
// // grab a handle to the memory
|
||||||
|
// let mut plugin_memory = match caller.get_export("memory") {
|
||||||
|
// Some(Extern::Memory(mem)) => mem,
|
||||||
|
// _ => return Err(Trap::new("Could not grab slice of plugin memory"))?,
|
||||||
|
// };
|
||||||
|
|
||||||
|
// let buffer = WasiBuffer::from_u64(packed_buffer);
|
||||||
|
|
||||||
|
// // get the args passed from Guest
|
||||||
|
// let args = Wasi::buffer_to_bytes(&mut plugin_memory, &mut caller, &buffer)?;
|
||||||
|
|
||||||
|
// // Call the Host-side function
|
||||||
|
// let result = function(args);
|
||||||
|
|
||||||
|
// Ok((buffer, plugin_memory, result))
|
||||||
|
// })();
|
||||||
|
|
||||||
|
// Box::new(async move {
|
||||||
|
// let (buffer, mut plugin_memory, thingo) = result?;
|
||||||
|
// let thingo: Result<_, Error> = thingo;
|
||||||
|
// let result: Result<Vec<u8>, Error> = thingo?.await;
|
||||||
|
|
||||||
|
// // Wasi::buffer_to_free(caller.data().free_buffer(), &mut caller, buffer).await?;
|
||||||
|
|
||||||
|
// // let buffer = Wasi::bytes_to_buffer(
|
||||||
|
// // caller.data().alloc_buffer(),
|
||||||
|
// // &mut plugin_memory,
|
||||||
|
// // &mut caller,
|
||||||
|
// // result,
|
||||||
|
// // )
|
||||||
|
// // .await?;
|
||||||
|
|
||||||
|
// // Ok(buffer.into_u64())
|
||||||
|
// Ok(27)
|
||||||
|
// })
|
||||||
|
// },
|
||||||
|
// )?;
|
||||||
|
// Ok(self)
|
||||||
|
// }
|
||||||
|
|
||||||
|
pub fn host_function<A, R>(
|
||||||
mut self,
|
mut self,
|
||||||
name: &str,
|
name: &str,
|
||||||
function: impl Fn(A) -> R + Send + Sync + 'static,
|
function: impl Fn(A) -> R + Send + Sync + 'static,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error>
|
||||||
|
where
|
||||||
|
A: DeserializeOwned + Send,
|
||||||
|
R: Serialize + Send + Sync,
|
||||||
|
{
|
||||||
self.linker.func_wrap1_async(
|
self.linker.func_wrap1_async(
|
||||||
"env",
|
"env",
|
||||||
&format!("__{}", name),
|
&format!("__{}", name),
|
||||||
|
@ -335,6 +477,12 @@ impl Wasi {
|
||||||
Ok(bytes)
|
Ok(bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn deserialize_to_type<R: DeserializeOwned>(bytes: &[u8]) -> Result<R, Error> {
|
||||||
|
// serialize the argument using bincode
|
||||||
|
let bytes = bincode::deserialize(bytes)?;
|
||||||
|
Ok(bytes)
|
||||||
|
}
|
||||||
|
|
||||||
// fn deserialize<R: DeserializeOwned>(
|
// fn deserialize<R: DeserializeOwned>(
|
||||||
// plugin_memory: &mut Memory,
|
// plugin_memory: &mut Memory,
|
||||||
// mut store: impl AsContextMut<Data = WasiCtxAlloc>,
|
// mut store: impl AsContextMut<Data = WasiCtxAlloc>,
|
||||||
|
@ -382,6 +530,21 @@ impl Wasi {
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Takes a `(ptr, len)` pair and returns the corresponding deserialized buffer.
|
||||||
|
fn buffer_to_bytes<'a>(
|
||||||
|
plugin_memory: &'a Memory,
|
||||||
|
store: impl AsContext<Data = WasiCtxAlloc> + 'a,
|
||||||
|
buffer: &WasiBuffer,
|
||||||
|
) -> Result<Vec<u8>, Error> {
|
||||||
|
let buffer_start = buffer.ptr as usize;
|
||||||
|
let buffer_end = buffer_start + buffer.len as usize;
|
||||||
|
|
||||||
|
// read the buffer at this point into a byte array
|
||||||
|
// deserialize the byte array into the provided serde type
|
||||||
|
let result = plugin_memory.data(store.as_context())[buffer_start..buffer_end].to_vec();
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
|
||||||
async fn buffer_to_free(
|
async fn buffer_to_free(
|
||||||
free_buffer: TypedFunc<u64, ()>,
|
free_buffer: TypedFunc<u64, ()>,
|
||||||
mut store: impl AsContextMut<Data = WasiCtxAlloc>,
|
mut store: impl AsContextMut<Data = WasiCtxAlloc>,
|
||||||
|
|
Loading…
Reference in a new issue