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