generate

Macro generate 

Source
generate!() { /* proc-macro */ }
Expand description

Generate bindings for an input WIT document.

The macro here will parse WIT as input and generate Rust bindings to work with the world that’s specified in the WIT. For a primer on WIT see this documentation and for a primer on worlds see here.

For documentation on each option, see below.

§Exploring generated bindings

Once bindings have been generated they can be explored via a number of means to see what was generated:

  • Using cargo doc should render all of the generated bindings in addition to the original comments in the WIT format itself.
  • If your IDE supports rust-analyzer code completion should be available to explore and see types.

§Namespacing

The generated bindings are put in bindings module. In WIT, worlds can import and export interfaces, functions, and types. Each interface can either be “anonymous” and only named within the context of a world or it can have a “package ID” associated with it. Names in Rust take into account all the names associated with a WIT interface. For example the package ID foo:bar/baz would create a mod foo which contains a mod bar which contains a mod baz.

WIT imports and exports are additionally separated into their own namespaces. Imports are generated at the level of the generate! macro where exports are generated under an exports namespace.

§Exports: The export! macro

Components are created by having exported WebAssembly functions with specific names, and these functions are not created when generate! is invoked. Instead these functions are created afterwards once you’ve defined your own type an implemented the various traits for it. The #[unsafe(no_mangle)] functions that will become the component are created with the generated export! macro.

Each call to generate! will itself generate a macro called export!. The macro’s first argument is the name of a type that implements the traits generated:

use miden::generate;

generate!({
    inline: r#"
        package my:test;

        world my-world {
            // ...
        }
    "#,
});

struct MyComponent;

impl Guest for MyComponent {
    // ...
}

export!(MyComponent);

This argument is a Rust type which implements the Guest traits generated by generate!. Note that all Guest traits must be implemented for the type provided or an error will be generated.

§Options to generate!

The full list of options that can be passed to the generate! macro are as follows. Note that there are no required options, they all have default values.

use miden::generate;

generate!({
    // Enables passing "inline WIT". If specified this is the default
    // package that a world is selected from. Any dependencies that this
    // inline WIT refers to must be defined in the `path` option above.
    //
    // By default this is not specified.
    inline: "
        world my-world {
            import wasi:cli/imports;

            export my-run: func()
        }
    ",

    // When generating bindings for interfaces that are not defined in the
    // same package as `world`, this option can be used to either generate
    // those bindings or point to already generated bindings.
    // For example, if your world refers to WASI types then the `wasi` crate
    // already has generated bindings for all WASI types and structures. In this
    // situation the key `with` here can be used to use those types
    // elsewhere rather than regenerating types.
    // If for example your world refers to some type and you want to use
    // your own custom implementation of that type then you can specify
    // that here as well. There is a requirement on the remapped (custom)
    // type to have the same internal structure and identical to what would
    // wit-bindgen generate (including alignment, etc.), since
    // lifting/lowering uses its fields directly.
    //
    // If, however, your world refers to interfaces for which you don't have
    // already generated bindings then you can use the special `generate` value
    // to have those bindings generated.
    //
    // The `with` key here works for interfaces and individual types.
    //
    // When an interface or type is specified here no bindings will be
    // generated at all. It's assumed bindings are fully generated
    // somewhere else. This is an indicator that any further references to types
    // defined in these interfaces should use the upstream paths specified
    // here instead.
    //
    // Any unused keys in this map are considered an error.
    with: {
        "wasi:io/poll": wasi::io::poll,
        "some:package/my-interface": generate,
        "some:package/my-interface/my-type": my_crate::types::MyType,
    },
});