iroh_n0des_macro/
lib.rs

1use proc_macro::TokenStream;
2use proc_macro2::Span;
3use quote::quote;
4use syn::{Ident, ItemFn};
5
6/// Marks a function as a simulation test
7///
8/// This is a simple marker attribute that doesn't transform the code.
9/// The external test runner discovers these functions by parsing the AST
10/// and looking for this attribute.
11#[proc_macro_attribute]
12pub fn sim(_args: TokenStream, input: TokenStream) -> TokenStream {
13    // Parse and validate the function signature
14    let input_fn = syn::parse_macro_input!(input as syn::ItemFn);
15
16    // Validate it's async and returns Result<SimulationBuilder<_>>
17    if input_fn.sig.asyncness.is_none() {
18        return syn::Error::new_spanned(input_fn.sig.fn_token, "sim functions must be async")
19            .to_compile_error()
20            .into();
21    }
22
23    expand_sim_fn(input_fn)
24}
25
26fn expand_sim_fn(input_fn: ItemFn) -> TokenStream {
27    let name = input_fn.sig.ident.clone();
28    let name_str = name.to_string();
29    let new_name = Ident::new(&format!("n0des_sim_{name}"), Span::call_site());
30    quote! {
31        #[tokio::test]
32        async fn #new_name() -> ::anyhow::Result<()> {
33            #input_fn
34
35            ::iroh_n0des::simulation::run_sim_fn(#name_str, #name).await
36        }
37    }
38    .into()
39}