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}