message_bus_macros/
lib.rs

1use proc_macro::TokenStream;
2use proc_macro_error::proc_macro_error;
3use std::{
4    collections::hash_map::DefaultHasher,
5    fs,
6    hash::{Hash, Hasher},
7    path::Path,
8};
9
10mod analysis;
11mod ast;
12mod codegen;
13
14#[proc_macro]
15#[proc_macro_error]
16pub fn make_message_bus(items: TokenStream) -> TokenStream {
17    let ast = match ast::parse(items.into()) {
18        Ok(ast) => ast,
19        Err(err) => return err.into_compile_error().into(),
20    };
21
22    let analysis = match analysis::analyze(&ast) {
23        Ok(analysis) => analysis,
24        Err(err) => return err.into_compile_error().into(),
25    };
26
27    let tokens = codegen::generate(&ast, &analysis);
28
29    write_expansion_to_file(&tokens);
30
31    tokens
32}
33
34fn write_expansion_to_file(tokens: &TokenStream) {
35    // Default output path: <project_dir>/target/
36    let out_dir = Path::new("target");
37
38    if !out_dir.exists() {
39        return;
40    }
41
42    // Try to write the expanded code to disk
43    if let Some(out_str) = out_dir.to_str() {
44        let token_string = tokens.to_string();
45        let _hash_of_codegen = calculate_hash(&token_string);
46
47        fs::write(format!("{out_str}/async-bus-expansion.rs"), token_string).ok();
48    }
49}
50
51fn calculate_hash<T>(t: &T) -> u64
52where
53    T: Hash,
54{
55    let mut s = DefaultHasher::new();
56    t.hash(&mut s);
57    s.finish()
58}