odra_ir/module_item/
method.rs1use quote::{quote, ToTokens};
2
3use crate::attrs::{partition_attributes, OdraAttribute};
4
5use super::utils;
6
7pub struct Method {
18 pub attrs: Vec<OdraAttribute>,
19 pub impl_item: syn::ImplItemMethod,
20 pub ident: syn::Ident,
21 pub is_mut: bool,
22 pub args: syn::punctuated::Punctuated<syn::PatType, syn::token::Comma>,
23 pub ret: syn::ReturnType,
24 pub full_sig: syn::Signature,
25 pub visibility: syn::Visibility
26}
27
28impl Method {
29 pub fn is_public(&self) -> bool {
30 matches!(self.visibility, syn::Visibility::Public(_))
31 }
32
33 pub fn is_payable(&self) -> bool {
34 self.attrs.iter().any(|attr| attr.is_payable())
35 }
36}
37
38impl ToTokens for Method {
39 fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
40 let is_non_reentrant = self.attrs.iter().any(OdraAttribute::is_non_reentrant);
41 let name = &self.ident.to_string();
42 let args = &self
43 .args
44 .iter()
45 .map(|arg| {
46 let name = &*arg.pat;
47
48 let (ty, is_slice) = utils::ty(arg);
49 let is_ref = utils::is_ref(arg);
50 let ty = quote!(<#ty as odra::types::CLTyped>::cl_type());
51 quote! {
52 odra::types::contract_def::Argument {
53 ident: odra::prelude::string::String::from(stringify!(#name)),
54 ty: #ty,
55 is_ref: #is_ref,
56 is_slice: #is_slice
57 },
58 }
59 })
60 .collect::<proc_macro2::TokenStream>();
61
62 let ret = match &self.ret {
63 syn::ReturnType::Default => quote!(odra::types::CLType::Unit),
64 syn::ReturnType::Type(_, ty) => {
65 quote!(<#ty as odra::types::CLTyped>::cl_type())
66 }
67 };
68
69 let ty = match self.attrs.iter().any(|attr| attr.is_payable()) {
70 true => {
71 quote!(odra::types::contract_def::EntrypointType::PublicPayable { non_reentrant: #is_non_reentrant })
72 }
73 false => {
74 quote!(odra::types::contract_def::EntrypointType::Public { non_reentrant: #is_non_reentrant })
75 }
76 };
77
78 let is_mut = self.is_mut;
79
80 let ep = quote! {
81 odra::types::contract_def::Entrypoint {
82 ident: odra::prelude::string::String::from(#name),
83 args: odra::prelude::vec![#args],
84 is_mut: #is_mut,
85 ret: #ret,
86 ty: #ty,
87 },
88 };
89
90 tokens.extend(ep)
91 }
92}
93
94impl TryFrom<syn::ImplItemMethod> for Method {
95 type Error = syn::Error;
96
97 fn try_from(method: syn::ImplItemMethod) -> Result<Self, Self::Error> {
98 let (odra_attrs, attrs) = partition_attributes(method.clone().attrs)?;
99 let ident = method.sig.ident.to_owned();
100 let args = utils::extract_typed_inputs(&method.sig);
101 let ret = method.clone().sig.output;
102 let full_sig = method.clone().sig;
103 let visibility = method.vis.clone();
104 let is_mut = utils::is_mut(&full_sig);
105
106 Ok(Self {
107 attrs: odra_attrs,
108 impl_item: syn::ImplItemMethod { attrs, ..method },
109 ident,
110 is_mut,
111 args,
112 ret,
113 full_sig,
114 visibility
115 })
116 }
117}