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!("{name}\n attr: {attr}\n item: {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 #[unsafe(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}