Hello,
If it is possible to push a struct with reference filed to a ResourceTable
? I failed to try to impl the Trait method that's declared by wasmtime::component::bindgen!(...)
.
// the data struct I want to push into ResourceTable, it has a reference typed field `map`
pub struct MapKeyIter<'a> {
map: &'a MapHandle,
prev: Option<Vec<u8>>,
next: Vec<u8>,
}
// bindgen!() generates Trait definition
pub trait HostMapKeyIter {
fn next(
&mut self,
self_: wasmtime::component::Resource<MapKeyIter>,
) -> wasmtime::Result<Result<Option<Value>, ()>>;
fn drop(
&mut self,
rep: wasmtime::component::Resource<MapKeyIter>,
) -> wasmtime::Result<()>;
}
// My impl code of `HostMapKeyIter` trait
impl<'a, State> ebpf::HostMapKeyIter for BpfCtx<'a, State> {
fn next(
&mut self,
self_: wasmtime::component::Resource<libbpf_rs::MapKeyIter>,
) -> Result<Result<Option<Vec<u8>>, ()>, wasmtime::Error> {
let map_key_iter: &'_ mut libbpf_rs::MapKeyIter = self.table.get_mut(&self_)?;
Ok(Ok(map_key_iter.next()))
}
fn drop(
&mut self,
rep: wasmtime::component::Resource<libbpf_rs::MapKeyIter>,
) -> wasmtime::Result<()> {
self.table.delete(rep)?;
Ok(())
}
}
I got a compiler error of "borrowed data escapes outside of method
self_
escapes the method body here"
Thus I want to add a lifetime for MapKeyIter and modified the signature of next
like
fn next(
&mut self,
self_: wasmtime::component::Resource<libbpf_rs::MapKeyIter<'a>>,
) -> Result<Result<Option<Vec<u8>>, ()>, wasmtime::Error> {
It tells me lifetime mismatch and signature mismatch.
The solution for this we think is that wasmtime::component::bindgen!()
generates Trait with explicitly lifetime annotation instead of elided anonymouse lifetime, for example,
pub trait HostMapKeyIter<'a> {
fn next(
&mut self,
self_: wasmtime::component::Resource<MapKeyIter<'a>>,
) -> wasmtime::Result<Result<Option<Value>, ()>>;
fn drop(
&mut self,
rep: wasmtime::component::Resource<MapKeyIter<'a>>,
) -> wasmtime::Result<()>;
}
then avoid lifetime mismatch and signature mismatch.
Could you share your insights with us? Please let us know if you have different solution for push a struct with reference filed into a ResourceTable.
Thanks,
Chengdong
After we investigated wit bindgen marco, we realized that wit bindgen generates trait without lifetime for every resource type.
https://docs.rs/wasmtime-wit-bindgen/22.0.0/src/wasmtime_wit_bindgen/lib.rs.html#1307
uwriteln!(self.src, "pub trait Host{camel} {{");
and
fn generate_function_trait_sig(&mut self, func: &Function) {
let wt = self.gen.wasmtime_path();
self.rustdoc(&func.docs);
if self.gen.opts.async_.is_import_async(&func.name) {
self.push_str("async ");
}
self.push_str("fn ");
self.push_str(&rust_function_name(func));
self.push_str("(&mut self, ");
for (name, param) in func.params.iter() {
let name = to_rust_ident(name);
self.push_str(&name);
self.push_str(": ");
self.print_ty(param, **TypeMode::Owned**);
self.push_str(",");
}
There is no option can control this.
I think that's what this with
construct is meant for https://github.com/bytecodealliance/wasmtime/blob/main/crates/wasi-http/src/bindings.rs#L20-L37
At this time, no, you can't put anything with a lifetime into ResourceTable
(unless it's 'static
). That's required for a number of reasons related to memory safety at this time and would require some significant rearchitecting to enable that I think. I haven't tried too too hard though so it's mostly a gut feeling, if you'd like it might be reasonable to try to plumb a lifetime parameter around
Last updated: Dec 23 2024 at 13:07 UTC