Module _8_store_in_imports

Source
Available on crate feature runtime and crate feature component-model and docsrs and crate feature component-model-async only.
Expand description

Example of using StoreContextMut in imported functions.

This is an example of using the store option to the imports configuration of the bindgen! macro. Like seen in previous examples a MyWorldImports trait is generated for my-world, but imports that have access to the store get added to a separate trait with a *WithStore suffix, in this case MyWorldImportsWithStore. This second trait provides access to a StoreContextMut.

use wasmtime::component::{bindgen, HasData, Access, Accessor};
use wasmtime::{StoreContextMut, AsContextMut};

bindgen!({
    inline: r#"
        package example:store-in-imports;

        world my-world {
            import sync-with-store: func();
            import async-with-store: async func();

            import sync-without-store: func();
            import async-without-store: func();

            export run: async func();
        }
    "#,

    imports: {
        "sync-with-store": store,
        // note that this isn't required because WIT-level `async` functions
        // always have access to the store.
        // "async-with-store": store,
        "async-without-store": async,
    },
});

struct MyState {
    // ...
}

impl HasData for MyState {
    type Data<'a> = &'a mut MyState;
}

impl MyWorldImportsWithStore for MyState {
    /// Synchronous functions that have access to the store are defined in
    /// Rust as a normal `fn` with an `Access` as the first parameter.
    fn sync_with_store<T>(mut host: Access<'_, T, Self>) {
        // The `Access` type implements `AsContextMut` to manipulate and
        // operate on the store.
        let mut store: StoreContextMut<'_, T> = host.as_context_mut();

        // The `Access` type can be used to get the `Data` projection of
        // the `HasData` trait implementation above, in this case
        // ourselves.
        let my_state: &mut MyState = host.get();
    }

    /// Asynchronous functions that have access to the store are defined in
    /// Rust as an `async fn` with an `Accessor` as the first parameter.
    async fn async_with_store<T>(accessor: &Accessor<T, Self>) {
        // The `Accessor` type does not implement `AsContextMut` directly
        // and instead represents the ability to, synchronously, work with
        // the store. Notably borrows into the store or `Self` cannot be
        // persisted across await points
        accessor.with(|mut access| {
            // same as `sync_with_store` above
            let mut store: StoreContextMut<'_, T> = access.as_context_mut();
            let my_state: &mut MyState = access.get();

            // ...
        });

        some_function().await;

        accessor.with(|mut access| {
            // ...
        });
    }
}

// Functions that don't have access to the store are defined with
// `&mut self` indicating that they can only access data in `self`, not the
// entire store.
impl MyWorldImports for MyState {
    fn sync_without_store(&mut self) { /* ... */ }
    async fn async_without_store(&mut self) { /* ... */ }
}

Structs§

MyWorld
Auto-generated bindings for an instance a component which implements the world my-world.
MyWorldIndices
Auto-generated bindings for index of the exports of my-world.
MyWorldPre
Auto-generated bindings for a pre-instantiated version of a component which implements the world my-world.

Traits§

MyWorldImports
MyWorldImportsWithStore