forwarding_gen/
method_member_adapter.rs1use proc_macro2::token_stream::TokenStream as TkStream;
8use quote::ToTokens;
9use syn::{Ident, Signature, Expr};
10use proc_macro2::Span;
11use sha3::{Digest, Sha3_256};
12use base32ct::{Base32Unpadded, Encoding};
13
14#[derive(Debug, Clone)]
15pub(crate) enum MethodAdaptError
16{
17 NotDispatchable(Span),
18 MalformedArgument(Span),
19 SyntaxError(syn::Error)
20}
21
22impl From<MethodAdaptError> for syn::Error
23{
24 fn from(value: MethodAdaptError) -> Self {
25 match value {
26 MethodAdaptError::NotDispatchable(s) => syn::Error::new(s, "Method not dispatchable. Object-Safe Traits require a valid receiver."),
27 MethodAdaptError::MalformedArgument(s) => syn::Error::new(s, "Malformed argument in Signature, identifier required."),
28 MethodAdaptError::SyntaxError(err) => err
29 }
30 }
31}
32
33impl From<syn::Error> for MethodAdaptError
34{
35 fn from(value: syn::Error) -> Self {
36 MethodAdaptError::SyntaxError(value)
37 }
38}
39
40impl std::fmt::Display for MethodAdaptError
41{
42 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
43 write!(f,"{}", syn::Error::from(self.clone()))
44 }
45}
46
47fn generate_macro_signature_hash(
48 submember:&Ident,
49 method_sig:&Signature,
50 base_hash:&str
51) -> String
52{
53 let strbulk = format!("member:{},signature:{},{}",
54 submember.to_string(),
55 method_sig.to_token_stream(),
56 base_hash
57 );
58
59 let mut hasher = Sha3_256::new();
60 hasher.update(strbulk.as_bytes());
61 let finv = hasher.finalize();
62 Base32Unpadded::encode_string(&finv[..])
63}
64
65pub(crate) struct TraitMethodImplMacros
66{
67 pub(crate) macro_decl:TkStream,
68 pub(crate) macro_invoke:TkStream
69}
70
71impl TraitMethodImplMacros
72{
73 pub(crate) fn create(
74 struct_member: &Ident,
75 method_sig: &Signature,
76 base_hash:&str
77 ) -> Result<Self, MethodAdaptError>
78 {
79
80 let mut params_iter = method_sig.inputs.iter();
81
82 let first_param = params_iter.next().ok_or(
84 MethodAdaptError::NotDispatchable(method_sig.ident.span())
85 )?;
86
87 let receiver_pat:TkStream = match first_param {
89 syn::FnArg::Receiver(rcv) => {
90 if rcv.reference.is_some() {
91 let muttk = rcv.mutability;
92 let stks = quote::quote!(&#muttk);
93 Ok(stks)
94 }
95 else
96 {
97 Err(MethodAdaptError::NotDispatchable(method_sig.ident.span()))
98 }
99 },
100 _ => Err(MethodAdaptError::NotDispatchable(method_sig.ident.span()))
101 }?;
102
103
104 let parameters_pair: Vec<(Expr, syn::FnArg)> = params_iter.map(
106 |arg| -> Result<(Expr, syn::FnArg), MethodAdaptError> {
107 match arg {
108 syn::FnArg::Receiver(_) => {
109 Err(MethodAdaptError::NotDispatchable(method_sig.ident.span()))
111 },
112 syn::FnArg::Typed(typed) => {
113 let innerpat = typed.pat.as_ref();
114 match innerpat {
115 syn::Pat::Ident(idx) => {
116 let ret_expr= syn::parse2::<Expr>(idx.ident.to_token_stream());
117 ret_expr.map(|expr | (expr, arg.clone() ) ).or_else(|err| Err(err.into()))
118 },
119 _ => {
120 Err(MethodAdaptError::MalformedArgument(method_sig.ident.span()))
121 }
122 }
123 }
124 }
125 }
126 ).collect::<Result< _ , _> >()?;
127
128 let (parameters, signature_params) : (Vec<Expr>, Vec<syn::FnArg>) = parameters_pair.into_iter().unzip();
129
130 let method_name = &method_sig.ident;
131
132 let method_output = method_sig.output.clone();
134 let semi_end:Option<syn::token::Semi> = match &method_output {
135 syn::ReturnType::Default => {Some(syn::token::Semi::default())},
136 _ => { None }
137 };
138
139 let method_generics = &method_sig.generics;
140 let method_where = &method_sig.generics.where_clause;
141
142
143 let inner_macro_method_name_str = format!("macromethod_{}_{}",
145 method_name.to_string(),
146 generate_macro_signature_hash(struct_member, method_sig, base_hash)
147 );
148
149 let inner_macro_method_name = Ident::new(&inner_macro_method_name_str, method_name.span());
150
151 let mdecl = quote::quote!(
153 macro_rules! #inner_macro_method_name {
154 ($self_token:ident) => {
155
156 fn #method_name #method_generics (#receiver_pat $self_token #(,#signature_params)* ) #method_output
157 #method_where
158 {
159 $self_token.#struct_member.#method_name( #(#parameters),* ) #semi_end
160 }
161 };
162 }
163 );
164
165 let minvoke = quote::quote!(#inner_macro_method_name!(self););
167
168 Ok(Self{macro_decl:mdecl, macro_invoke:minvoke})
169
170 }
171
172}