multiversx_sc_derive/generate/
proxy_callback_gen.rs1use super::snippets;
2use crate::model::{
3 ArgPaymentMetadata, CallbackMetadata, ContractTrait, Method, MethodArgument, PublicRole,
4};
5
6pub fn cb_proxy_arg_declarations(method_args: &[MethodArgument]) -> Vec<proc_macro2::TokenStream> {
8 method_args
9 .iter()
10 .filter_map(|arg| {
11 if arg.metadata.payment.is_payment_arg() || arg.metadata.callback_call_result {
12 None
13 } else {
14 let pat = &arg.pat;
15 let ty = &arg.ty;
16 Some(quote! {#pat : #ty })
17 }
18 })
19 .collect()
20}
21
22fn generate_callback_proxy_method(
23 m: &Method,
24 callback: &CallbackMetadata,
25) -> proc_macro2::TokenStream {
26 let arg_decl = cb_proxy_arg_declarations(&m.method_args);
27 let cb_name_literal = callback.callback_name.to_string();
28
29 let cb_arg_push_snippets: Vec<proc_macro2::TokenStream> = m
30 .method_args
31 .iter()
32 .map(|arg| {
33 if let ArgPaymentMetadata::NotPayment = arg.metadata.payment {
34 if arg.metadata.callback_call_result {
35 quote! {}
36 } else {
37 let pat = &arg.pat;
38 quote! {
39 ___callback_call___.push_endpoint_arg(&#pat);
40 }
41 }
42 } else {
43 quote! {}
44 }
45 })
46 .collect();
47 let method_name = &m.name;
48 quote! {
49 #[allow(clippy::too_many_arguments)]
50 #[allow(clippy::type_complexity)]
51 fn #method_name(
52 self,
53 #(#arg_decl),*
54 ) -> multiversx_sc::types::CallbackClosure<Self::Api> {
55 let mut ___callback_call___ =
56 multiversx_sc::types::new_callback_call::<Self::Api>(#cb_name_literal);
57 #(#cb_arg_push_snippets)*
58 ___callback_call___
59 }
60 }
61}
62
63pub fn generate_callback_proxies_object(methods: &[Method]) -> proc_macro2::TokenStream {
64 let proxy_methods: Vec<proc_macro2::TokenStream> = methods
65 .iter()
66 .filter_map(|m| {
67 if let PublicRole::Callback(callback) | PublicRole::CallbackPromise(callback) =
68 &m.public_role
69 {
70 Some(generate_callback_proxy_method(m, callback))
71 } else {
72 None
73 }
74 })
75 .collect();
76
77 let callback_proxy_object_def = snippets::callback_proxy_object_def();
78
79 quote! {
80 #callback_proxy_object_def
81
82 pub trait CallbackProxy: multiversx_sc::contract_base::CallbackProxyObjBase + Sized {
83 #(#proxy_methods)*
84 }
85
86 impl<A> self::CallbackProxy for CallbackProxyObj<A> where A: multiversx_sc::api::VMApi + 'static {}
87 }
88}
89
90pub fn generate_callback_proxies(
91 contract: &ContractTrait,
92) -> (
93 proc_macro2::TokenStream,
94 proc_macro2::TokenStream,
95 proc_macro2::TokenStream,
96) {
97 if contract.callback_count() == 0 {
98 (quote! {}, quote! {}, quote! {})
99 } else {
100 (
101 quote! {
102 fn callbacks(&self) -> self::CallbackProxyObj<Self::Api>;
103 },
104 quote! {
105 fn callbacks(&self) -> self::CallbackProxyObj<Self::Api> {
106 <self::CallbackProxyObj::<Self::Api> as multiversx_sc::contract_base::CallbackProxyObjBase>::new_cb_proxy_obj()
107 }
108 },
109 generate_callback_proxies_object(contract.methods.as_slice()),
110 )
111 }
112}