Struct wasmtime::component::Resource

source ·
pub struct Resource<T> { /* private fields */ }
Expand description

A host-defined resource in the component model.

This type can be thought of as roughly a newtype wrapper around u32 for use as a resource with the component model. The main guarantee that the component model provides is that the u32 is not forgeable by guests and there are guaranteed semantics about when a u32 may be in use by the guest and when it’s guaranteed no longer needed. This means that it is safe for embedders to consider the internal u32 representation “trusted” and use it for things like table indices with infallible accessors that panic on out-of-bounds. This should only panic for embedder bugs, not because of any possible behavior in the guest.

A Resource<T> value dynamically represents both an (own $t) in the component model as well as a (borrow $t). It can be inspected via Resource::owned to test whether it is an owned handle. An owned handle which is not actively borrowed can be destroyed at any time as it’s guaranteed that the guest does not have access to it. A borrowed handle, on the other hand, may be accessed by the guest so it’s not necessarily guaranteed to be able to be destroyed.

Note that the “own” and “borrow” here refer to the component model, not Rust. The semantics of Rust ownership and borrowing are slightly different than the component model’s (but spiritually the same) in that more dynamic tracking is employed as part of the component model. This means that it’s possible to get runtime errors when using a Resource<T>. For example it is an error to call Resource::new_borrow and pass that to a component function expecting (own $t) and this is not statically disallowed.

The Resource type implements both the Lift and Lower trait to be used with typed functions in the component model or as part of aggregate structures and datatypes.

§Destruction of a resource

Resources in the component model are optionally defined with a destructor, but this host resource type does not specify a destructor. It is left up to the embedder to be able to determine how best to a destroy a resource when it is owned.

Note, though, that while Resource itself does not specify destructors it’s still possible to do so via the Linker::resource definition. When a resource type is defined for a guest component a destructor can be specified which can be used to hook into resource destruction triggered by the guest.

This means that there are two ways that resource destruction is handled:

  • Host resources destroyed by the guest can hook into the Linker::resource destructor closure to handle resource destruction. This could, for example, remove table entries.

  • Host resources owned by the host itself have no automatic means of destruction. The host can make its own determination that its own resource is not lent out to the guest and at that time choose to destroy or deallocate it.

§Dynamic behavior of a resource

A host-defined Resource does not necessarily represent a static value. Its internals may change throughout its usage to track the state associated with the resource. The internal 32-bit host-defined representation never changes, however.

For example if there’s a component model function of the form:

(func (param "a" (borrow $t)) (param "b" (own $t)))

Then that can be extracted in Rust with:

let func = instance.get_typed_func::<(&Resource<T>, &Resource<T>), ()>(&mut store, "name")?;

Here the exact same resource can be provided as both arguments but that is not valid to do so because the same resource cannot be actively borrowed and passed by-value as the second parameter at the same time. The internal state in Resource<T> will track this information and provide a dynamic runtime error in this situation.

Mostly it’s important to be aware that there is dynamic state associated with a Resource<T> to provide errors in situations that cannot be statically ruled out.

§Borrows and host responsibilities

Borrows to resources in the component model are guaranteed to be transient such that if a borrow is passed as part of a function call then when the function returns it’s guaranteed that the guest no longer has access to the resource. This guarantee, however, must be manually upheld by the host when it receives its own borrow.

As mentioned above the Resource<T> type can represent a borrowed value in addition to an owned value. This means a guest can provide the host with a borrow, such as an argument to an imported function:

linker.root().func_wrap("name", |_cx, (r,): (Resource<MyType>,)| {
    assert!(!r.owned());
    // .. here `r` is a borrowed value provided by the guest and the host
    // shouldn't continue to access it beyond the scope of this call
})?;

In this situation the host should take care to not attempt to persist the resource beyond the scope of the call. It’s the host’s resource so it technically can do what it wants with it but nothing is statically preventing r to stay pinned to the lifetime of the closure invocation. It’s considered a mistake that the host performed if r is persisted too long and accessed at the wrong time.

Implementations§

source§

impl<T> Resource<T>
where T: 'static,

source

pub fn new_own(rep: u32) -> Resource<T>

Creates a new owned resource with the rep specified.

The returned value is suitable for passing to a guest as either a (borrow $t) or (own $t).

source

pub fn new_borrow(rep: u32) -> Resource<T>

Creates a new borrowed resource which isn’t actually rooted in any ownership.

This can be used to pass to a guest as a borrowed resource and the embedder will know that the rep won’t be in use by the guest afterwards. Exactly how the lifetime of rep works is up to the embedder.

source

pub fn rep(&self) -> u32

Returns the underlying 32-bit representation used to originally create this resource.

source

pub fn owned(&self) -> bool

Returns whether this is an owned resource or not.

Owned resources can be safely destroyed by the embedder at any time, and borrowed resources have an owner somewhere else on the stack so can only be accessed, not destroyed.

source

pub fn try_from_resource_any( resource: ResourceAny, store: impl AsContextMut, ) -> Result<Self>

Attempts to convert a ResourceAny into Resource.

This method will check that resource has type ResourceType::host::<T>() and then convert it into a typed version of the resource.

§Errors

This function will return an error if resource does not have type ResourceType::host::<T>(). This function may also return an error if resource is no longer valid, for example it was previously converted.

§Panics

This function will panic if resource does not belong to the store specified.

source

pub fn try_into_resource_any( self, store: impl AsContextMut, ) -> Result<ResourceAny>

Trait Implementations§

source§

impl<T> Debug for Resource<T>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<T: 'static> ComponentType for Resource<T>

source§

impl<T: 'static> Lift for Resource<T>

source§

impl<T: 'static> Lower for Resource<T>

Auto Trait Implementations§

§

impl<T> !Freeze for Resource<T>

§

impl<T> RefUnwindSafe for Resource<T>

§

impl<T> Send for Resource<T>

§

impl<T> Sync for Resource<T>

§

impl<T> Unpin for Resource<T>

§

impl<T> UnwindSafe for Resource<T>

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> IntoEither for T

source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
source§

impl<T> Pointable for T

source§

const ALIGN: usize = _

The alignment of pointer.
source§

type Init = T

The type for initializers.
source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.