miden_base_macros/
lib.rs

1//! Module for Miden SDK macros
2//!
3//! ### How to use WIT generation.
4//!
5//! 1. Add `#[component]` on you `impl MyAccountType {`.
6//! 2. Add `#[export_type]` on every defined type that is used in the public(exported) method
7//!    signature.
8//!
9//! Example:
10//! ```rust
11//!
12//! #[export_type]
13//! pub struct StructA {
14//!     pub foo: Word,
15//!     pub asset: Asset,
16//! }
17//!
18//! #[export_type]
19//! pub struct StructB {
20//!     pub bar: Felt,
21//!     pub baz: Felt,
22//! }
23//!
24//! #[component]
25//! struct MyAccount;
26//!
27//! #[component]
28//! impl MyAccount {
29//!     pub fn (&self, a: StructA) -> StructB {
30//!         ...
31//!     }
32//! }
33//! ```
34//!
35
36//! ### Escape hatch (disable WIT generation)
37//!
38//! in a small fraction of the cases where the WIT generation is not possible (think a type defined
39//! only in an external WIT file) or not desirable the WIT generation can be disabled:
40//!
41//! To disable WIT interface generation:
42//! - Don't use `#[component]` attribute macro in the `impl MyAccountType` section;
43//!
44//! To use manually crafted WIT interface:
45//! - Put the WIT file in the `wit` folder;
46//! - call `miden::generate!();` and `bindings::export!(MyAccountType);`
47//! - implement `impl Guest for MyAccountType`;
48
49use crate::script::ScriptConfig;
50
51extern crate proc_macro;
52
53mod account_component_metadata;
54mod boilerplate;
55mod component_macro;
56mod export_type;
57mod generate;
58mod script;
59mod types;
60mod util;
61
62/// Generates the WIT interface and storage metadata.
63///
64/// **NOTE:** Mark each type used in the public method with `#[export_type]` attribute macro.
65///
66/// To disable WIT interface generation:
67/// - don't use `#[component]` attribute macro in the `impl MyAccountType` section;
68///
69/// To use manually crafted WIT interface:
70/// - put WIT interface file in the `wit` folder;
71/// - call `miden::generate!();` and `bindings::export!(MyAccountType);`
72/// - implement `impl Guest for MyAccountType`;
73#[proc_macro_attribute]
74pub fn component(
75    attr: proc_macro::TokenStream,
76    item: proc_macro::TokenStream,
77) -> proc_macro::TokenStream {
78    component_macro::component(attr, item)
79}
80
81/// Generates an equvalent type in the WIT interface.
82/// Required for every type mentioned in the public methods of an account component.
83///
84/// Intended to be used together with `#[component]` attribute macro.
85#[proc_macro_attribute]
86pub fn export_type(
87    attr: proc_macro::TokenStream,
88    item: proc_macro::TokenStream,
89) -> proc_macro::TokenStream {
90    export_type::expand(attr, item)
91}
92
93/// Marks the function as a note script
94#[proc_macro_attribute]
95pub fn note_script(
96    attr: proc_macro::TokenStream,
97    item: proc_macro::TokenStream,
98) -> proc_macro::TokenStream {
99    script::expand(
100        attr,
101        item,
102        ScriptConfig {
103            export_interface: "miden:base/note-script@1.0.0",
104            guest_trait_path: "self::bindings::exports::miden::base::note_script::Guest",
105        },
106    )
107}
108
109/// Marks the function as a transaction script
110#[proc_macro_attribute]
111pub fn tx_script(
112    attr: proc_macro::TokenStream,
113    item: proc_macro::TokenStream,
114) -> proc_macro::TokenStream {
115    script::expand(
116        attr,
117        item,
118        ScriptConfig {
119            export_interface: "miden:base/transaction-script@1.0.0",
120            guest_trait_path: "self::bindings::exports::miden::base::transaction_script::Guest",
121        },
122    )
123}
124
125/// Generate bindings for an input WIT document.
126///
127/// The macro here will parse [WIT] as input and generate Rust bindings to work with the `world`
128/// that's specified in the [WIT]. For a primer on WIT see [this documentation][WIT] and for a
129/// primer on worlds see [here][worlds].
130///
131/// [WIT]: https://component-model.bytecodealliance.org/design/wit.html
132/// [worlds]: https://component-model.bytecodealliance.org/design/worlds.html
133///
134/// For documentation on each option, see below.
135///
136/// ## Exploring generated bindings
137///
138/// Once bindings have been generated they can be explored via a number of means
139/// to see what was generated:
140///
141/// * Using `cargo doc` should render all of the generated bindings in addition
142///   to the original comments in the WIT format itself.
143/// * If your IDE supports `rust-analyzer` code completion should be available
144///   to explore and see types.
145///
146/// ## Namespacing
147///
148/// The generated bindings are put in `bindings` module.
149/// In WIT, worlds can import and export `interface`s, functions, and types. Each
150/// `interface` can either be "anonymous" and only named within the context of a
151/// `world` or it can have a "package ID" associated with it. Names in Rust take
152/// into account all the names associated with a WIT `interface`. For example
153/// the package ID `foo:bar/baz` would create a `mod foo` which contains a `mod
154/// bar` which contains a `mod baz`.
155///
156/// WIT imports and exports are additionally separated into their own
157/// namespaces. Imports are generated at the level of the `generate!` macro
158/// where exports are generated under an `exports` namespace.
159///
160/// ## Exports: The `export!` macro
161///
162/// Components are created by having exported WebAssembly functions with
163/// specific names, and these functions are not created when `generate!` is
164/// invoked. Instead these functions are created afterwards once you've defined
165/// your own type an implemented the various `trait`s for it. The
166/// `#[unsafe(no_mangle)]` functions that will become the component are created
167/// with the generated `export!` macro.
168///
169/// Each call to `generate!` will itself generate a macro called `export!`.
170/// The macro's first argument is the name of a type that implements the traits
171/// generated:
172///
173/// ```
174/// use miden::generate;
175///
176/// generate!({
177///     inline: r#"
178///         package my:test;
179///
180///         world my-world {
181/// #           export hello: func();
182///             // ...
183///         }
184///     "#,
185/// });
186///
187/// struct MyComponent;
188///
189/// impl Guest for MyComponent {
190/// #   fn hello() {}
191///     // ...
192/// }
193///
194/// export!(MyComponent);
195/// #
196/// # fn main() {}
197/// ```
198///
199/// This argument is a Rust type which implements the `Guest` traits generated
200/// by `generate!`. Note that all `Guest` traits must be implemented for the
201/// type provided or an error will be generated.
202///
203/// ## Options to `generate!`
204///
205/// The full list of options that can be passed to the `generate!` macro are as
206/// follows. Note that there are no required options, they all have default
207/// values.
208///
209///
210/// ```
211/// use miden::generate;
212/// # macro_rules! generate { ($($t:tt)*) => () }
213///
214/// generate!({
215///     // Enables passing "inline WIT". If specified this is the default
216///     // package that a world is selected from. Any dependencies that this
217///     // inline WIT refers to must be defined in the `path` option above.
218///     //
219///     // By default this is not specified.
220///     inline: "
221///         world my-world {
222///             import wasi:cli/imports;
223///
224///             export my-run: func()
225///         }
226///     ",
227///
228///     // When generating bindings for interfaces that are not defined in the
229///     // same package as `world`, this option can be used to either generate
230///     // those bindings or point to already generated bindings.
231///     // For example, if your world refers to WASI types then the `wasi` crate
232///     // already has generated bindings for all WASI types and structures. In this
233///     // situation the key `with` here can be used to use those types
234///     // elsewhere rather than regenerating types.
235///     // If for example your world refers to some type and you want to use
236///     // your own custom implementation of that type then you can specify
237///     // that here as well. There is a requirement on the remapped (custom)
238///     // type to have the same internal structure and identical to what would
239///     // wit-bindgen generate (including alignment, etc.), since
240///     // lifting/lowering uses its fields directly.
241///     //
242///     // If, however, your world refers to interfaces for which you don't have
243///     // already generated bindings then you can use the special `generate` value
244///     // to have those bindings generated.
245///     //
246///     // The `with` key here works for interfaces and individual types.
247///     //
248///     // When an interface or type is specified here no bindings will be
249///     // generated at all. It's assumed bindings are fully generated
250///     // somewhere else. This is an indicator that any further references to types
251///     // defined in these interfaces should use the upstream paths specified
252///     // here instead.
253///     //
254///     // Any unused keys in this map are considered an error.
255///     with: {
256///         "wasi:io/poll": wasi::io::poll,
257///         "some:package/my-interface": generate,
258///         "some:package/my-interface/my-type": my_crate::types::MyType,
259///     },
260/// });
261/// ```
262///
263#[proc_macro]
264pub fn generate(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
265    generate::expand(input)
266}