ic_cdk_macros/
lib.rs

1#![doc = include_str!("../README.md")]
2#![warn(
3    elided_lifetimes_in_paths,
4    missing_debug_implementations,
5    unsafe_op_in_unsafe_fn,
6    clippy::undocumented_unsafe_blocks,
7    clippy::missing_safety_doc
8)]
9
10use proc_macro::TokenStream;
11use syn::Error;
12
13mod export;
14
15fn handle_debug_and_errors<F>(
16    cb: F,
17    name: &str,
18    attr: TokenStream,
19    item: TokenStream,
20) -> TokenStream
21where
22    F: FnOnce(
23        proc_macro2::TokenStream,
24        proc_macro2::TokenStream,
25    ) -> Result<proc_macro2::TokenStream, Error>,
26{
27    if std::env::var_os("IC_CDK_DEBUG").is_some() {
28        eprintln!("--- IC_CDK_MACROS DEBUG ---");
29        eprintln!("{}\n    attr: {}\n    item: {}", name, attr, item);
30    }
31
32    let result = cb(attr.into(), item.into());
33
34    if std::env::var_os("IC_CDK_DEBUG").is_some() {
35        eprintln!("--------- RESULT  ---------");
36        if let Ok(ref stream) = result {
37            eprintln!("{}", stream);
38        }
39        eprintln!("---------------------------");
40    }
41
42    result.map_or_else(|e| e.to_compile_error().into(), Into::into)
43}
44
45#[proc_macro]
46pub fn export_candid(input: TokenStream) -> TokenStream {
47    let input: proc_macro2::TokenStream = input.into();
48    quote::quote! {
49        ::candid::export_service!(#input);
50
51        #[no_mangle]
52        pub fn get_candid_pointer() -> *mut std::os::raw::c_char {
53            let c_string = std::ffi::CString::new(__export_service()).unwrap();
54            c_string.into_raw()
55        }
56    }
57    .into()
58}
59
60#[proc_macro_attribute]
61pub fn query(attr: TokenStream, item: TokenStream) -> TokenStream {
62    handle_debug_and_errors(export::ic_query, "ic_query", attr, item)
63}
64
65#[proc_macro_attribute]
66pub fn update(attr: TokenStream, item: TokenStream) -> TokenStream {
67    handle_debug_and_errors(export::ic_update, "ic_update", attr, item)
68}
69
70#[proc_macro_attribute]
71pub fn init(attr: TokenStream, item: TokenStream) -> TokenStream {
72    handle_debug_and_errors(export::ic_init, "ic_init", attr, item)
73}
74
75#[proc_macro_attribute]
76pub fn pre_upgrade(attr: TokenStream, item: TokenStream) -> TokenStream {
77    handle_debug_and_errors(export::ic_pre_upgrade, "ic_pre_upgrade", attr, item)
78}
79
80#[proc_macro_attribute]
81pub fn post_upgrade(attr: TokenStream, item: TokenStream) -> TokenStream {
82    handle_debug_and_errors(export::ic_post_upgrade, "ic_post_upgrade", attr, item)
83}
84
85#[proc_macro_attribute]
86pub fn heartbeat(attr: TokenStream, item: TokenStream) -> TokenStream {
87    handle_debug_and_errors(export::ic_heartbeat, "ic_heartbeat", attr, item)
88}
89
90#[proc_macro_attribute]
91pub fn inspect_message(attr: TokenStream, item: TokenStream) -> TokenStream {
92    handle_debug_and_errors(export::ic_inspect_message, "ic_inspect_message", attr, item)
93}
94
95#[proc_macro_attribute]
96pub fn on_low_wasm_memory(attr: TokenStream, item: TokenStream) -> TokenStream {
97    handle_debug_and_errors(
98        export::ic_on_low_wasm_memory,
99        "ic_on_low_wasm_memory",
100        attr,
101        item,
102    )
103}