Add ability to consume an owned resource?
If I implement the export of a resource in Rust, and there is a method which takes an owned handle to this resource, the method implementation gets an Own{my-resource-name} passed by value. At the moment, this owned handle type only implements Deref, but not DerefMut or a helper function that consumes the resource handle and returns the underlying Rust type (the one we can pass to the Own{my-resource-name}::new method to construct the resource in the first place).
Even though the handle is owned and gives unique ownership, is there something in WIT or the component model that prevents the implementation of DerefMut or a consume method?
At the moment, I need to work around this deficiency by having the resource hold a RefCell<Option<MyConsumableType>>, which allows mutable access and consumption but is not infallible.
Thank you for your help! If these methods could be implemented, I'll gladly write the PR for them!
Thanks for the report, and apologies it took me a bit to get here! I believe it should be safe to implement DerefMut as you've mentioned, and a PR would be most welcome! Are you still up for sending a PR? If not no worries and I can prepare one.
No worries - and yes, I’ll work on one later today :)
@alexcrichton Could the component model also gain a method called, e.g. [resource-consume]{name}, which invalidates the resource handle (similar to drop) but does not drop the resource implementation data? That way, the Own{name} could get a consume function with an implementation similar to this (adapted from the new function template, i.e. meant to be inside a format string):
pub fn consume(own: Own{camel}) -> Rep{camel} {
#[allow(unused_imports)]
use {rt}::boxed::Box;
unsafe {{
#[cfg(target_arch = "wasm32")]
#[link(wasm_import_module = "[export]{module}")]
extern "C" {{
#[link_name = "[resource-consume]{name}"]
fn wit_import(_: i32) -> i32;
}}
#[cfg(not(target_arch = "wasm32"))]
unsafe fn wit_import(_n: i32) -> i32 {{ unreachable!() }}
// [resource-consume]{name} returns value address,
// like [resource-rep]{name}, but also invalidates the handle
let rep_ptr = ::core::mem::transmute::<isize, *mut Rep{camel}>(
wit_import(self.handle).try_into().unwrap()
);
*Box::from_raw(rep_ptr)
}}
}}
Seems reasonable to me! Can you open an issue on the component-model repository for that?
#647 has landed adding DerefMut for (what is now) Resource<T>, and the component-model feature is tracked in https://github.com/WebAssembly/component-model/issues/238.