abi_stable_derive_lib/sabi_trait/
methods_tokenizer.rs

1use super::*;
2
3use crate::to_token_fn::ToTokenFnMut;
4
5#[derive(Debug,Copy,Clone)]
6pub struct MethodsTokenizer<'a>{
7    pub(crate) trait_def:&'a TraitDefinition<'a>,
8    pub(crate) which_item:WhichItem,
9}
10
11
12#[derive(Debug,Copy,Clone)]
13pub struct MethodTokenizer<'a>{
14    trait_def:&'a TraitDefinition<'a>,
15    method:&'a TraitMethod<'a>,
16    which_item:WhichItem,
17}
18
19
20impl<'a> ToTokens for MethodsTokenizer<'a> {
21    fn to_tokens(&self, ts: &mut TokenStream2) {
22        for method in &self.trait_def.methods {
23            MethodTokenizer{
24                trait_def:self.trait_def,
25                method,
26                which_item:self.which_item,
27            }.to_tokens(ts);
28        }
29    }
30}
31        
32impl<'a> ToTokens for MethodTokenizer<'a> {
33    fn to_tokens(&self, ts: &mut TokenStream2) {
34        let which_item=self.which_item;
35        let method=self.method;
36        let trait_def=self.trait_def;
37        let ctokens=trait_def.ctokens;
38        let (is_method,vis)=match which_item {
39            WhichItem::Trait
40            |WhichItem::TraitImpl
41            =>(true,None),
42            WhichItem::TraitObjectImpl=>
43                (true,Some(trait_def.submod_vis)),
44             WhichItem::VtableDecl
45            |WhichItem::VtableImpl
46            =>(false,Some(trait_def.submod_vis)),
47        };
48        
49        let default_=method.default.as_ref();
50
51        let lifetimes=Some(&method.lifetimes).filter(|l| !l.is_empty() );
52
53        // The name of the method in the __Trait trait.
54        let method_name=method.name;
55        let method_span=method_name.span();
56        let used_name=method.name;
57        let self_param=match (is_method,&method.self_param) {
58            (true,SelfParam::ByRef{lifetime,is_mutable:false})=>
59                quote_spanned!(method_span=> & #lifetime self),
60            (true,SelfParam::ByRef{lifetime,is_mutable:true})=>
61                quote_spanned!(method_span=> & #lifetime mut self),
62            (true,SelfParam::ByVal)=>
63                quote_spanned!(method_span=> self),
64            (false,SelfParam::ByRef{lifetime,is_mutable:false})=>
65                quote_spanned!(method_span=> _self:& #lifetime __ErasedObject<_Self>),
66            (false,SelfParam::ByRef{lifetime,is_mutable:true})=>
67                quote_spanned!(method_span=> _self:& #lifetime mut __ErasedObject<_Self>),
68            (false,SelfParam::ByVal)=>
69                quote_spanned!(method_span=> _self:__sabi_re::MovePtr<'_,_Self>),
70        };
71
72        let param_names_a=method.params.iter()
73            .map(move|param|ToTokenFnMut::new(move|ts|{
74                match which_item {
75                    WhichItem::Trait=>{
76                        param.pattern.to_tokens(ts);
77                    }
78                    _=>{
79                        param.name.to_tokens(ts);
80                    }
81                }
82            }));
83        let param_ty     =method.params.iter().map(|param| &param.ty   );
84        let param_names_c=param_names_a.clone();
85        let param_names_d=param_names_a.clone();
86        let param_names_e=method.params.iter().map(|x| x.pattern );
87        let return_ty=&method.output;
88        
89        let self_is_sized_bound=Some(&ctokens.self_sized)
90            .filter(|_| is_method&&method.self_param==SelfParam::ByVal );
91
92        let abi=match which_item {
93             WhichItem::VtableImpl=>Some(&ctokens.extern_c),
94            _=>method.abi,
95        };
96
97        let user_where_clause=method.where_clause.get_tokenizer(ctokens);
98
99        let other_attrs=if which_item==WhichItem::Trait { 
100            method.other_attrs
101        }else{ 
102            &[] 
103        };
104
105        if WhichItem::VtableDecl==which_item {
106            let optional_field=method.default.as_ref().map(|_| &ctokens.missing_field_option );
107            let derive_attrs=method.derive_attrs;
108            quote_spanned!( method_span=>
109                #(#[#derive_attrs])*
110                #optional_field
111                #vis #used_name:
112                    #(for< #(#lifetimes,)* >)*
113                    unsafe extern "C" fn(
114                        #self_param,
115                        #( #param_names_a:#param_ty ,)* 
116                    ) #(-> #return_ty )*
117            )
118        }else{
119            let unsafety=match which_item {
120                WhichItem::VtableImpl=>Some(&ctokens.unsafe_),
121                _=>method.unsafety
122            };
123
124            quote_spanned!(method_span=>
125                #(#[#other_attrs])*
126                #vis #unsafety #abi fn #used_name #(< #(#lifetimes,)* >)* (
127                    #self_param, 
128                    #( #param_names_a:#param_ty ,)* 
129                ) #(-> #return_ty )*
130                where
131                    #self_is_sized_bound
132                    #user_where_clause
133            )
134        }.to_tokens(ts);
135
136        let ptr_constraint=match &method.self_param {
137            SelfParam::ByRef{is_mutable:false,..}=>
138                &ctokens.ptr_ref_bound,
139            SelfParam::ByRef{is_mutable:true,..}=>
140                &ctokens.ptr_mut_bound,
141            SelfParam::ByVal=>
142                &ctokens.ptr_val_bound,
143        };
144
145        match (which_item,&method.self_param) {
146            (WhichItem::Trait,_)=>{
147                method.default.as_ref().map(|x|x.block).to_tokens(ts);
148                method.semicolon.to_tokens(ts);
149            }
150            (WhichItem::TraitImpl,_)=>{
151                quote_spanned!(method_span=>{
152                    self.#method_name(#(#param_names_c,)*)
153                }).to_tokens(ts);
154            }
155            (WhichItem::TraitObjectImpl,_)=>{
156                let method_call=match &method.self_param {
157                    SelfParam::ByRef{is_mutable:false,..}=>{
158                        quote_spanned!(method_span=> 
159                            __method(self.obj.sabi_erased_ref(),#(#param_names_c,)*) 
160                        )
161                    }
162                    SelfParam::ByRef{is_mutable:true,..}=>{
163                        quote_spanned!(method_span=> 
164                            __method(self.obj.sabi_erased_mut(),#(#param_names_c,)*) 
165                        )
166                    }
167                    SelfParam::ByVal=>{
168                        quote_spanned!(method_span=>
169                            self.obj.sabi_with_value(
170                                move|_self|__method(_self,#(#param_names_c,)*)
171                            )
172                        )
173                    }
174                };
175
176                match default_ {
177                    Some(default_)=>{
178                        let block=&default_.block;
179                        quote_spanned!(method_span=>
180                                #ptr_constraint
181                            {
182                                match self.obj.sabi_et_vtable().#method_name() {
183                                    Some(__method)=>{
184                                        unsafe{
185                                            #method_call
186                                        }
187                                    }
188                                    None=>{
189                                        #(
190                                            let #param_names_e=#param_names_d;
191                                        )*
192                                        #block
193                                    }
194                                }
195                            }
196                        ).to_tokens(ts);
197                    }
198                    None=>{
199                        quote_spanned!(method_span=>
200                                #ptr_constraint
201                            {
202                                let __method=self.obj.sabi_et_vtable().#method_name();
203                                unsafe{
204                                    #method_call
205                                }
206                            }
207                        ).to_tokens(ts);
208                    }
209                }
210            }
211            (WhichItem::VtableDecl,_)=>{
212                quote_spanned!(method_span=> , ).to_tokens(ts);
213            
214            }
215            (WhichItem::VtableImpl,SelfParam::ByRef{is_mutable:false,..})=>{
216                quote_spanned!(method_span=>{
217                    __sabi_re::sabi_from_ref(
218                        _self,
219                        move|_self| 
220                            __Trait::#method_name(_self,#(#param_names_c,)*)
221                    )
222                }).to_tokens(ts);
223            }
224            (WhichItem::VtableImpl,SelfParam::ByRef{is_mutable:true,..})=>{
225                quote_spanned!(method_span=>{
226                    __sabi_re::sabi_from_mut(
227                        _self,
228                        move|_self| 
229                            __Trait::#method_name(_self,#(#param_names_c,)*)
230                    )
231                }).to_tokens(ts);
232            }
233            (WhichItem::VtableImpl,SelfParam::ByVal)=>{
234                quote_spanned!(method_span=>{
235                    ::abi_stable::extern_fn_panic_handling!{no_early_return;
236                        __Trait::#method_name(
237                            _self.into_inner(),#(#param_names_c,)*
238                        )
239                    }
240                }).to_tokens(ts);
241            }
242        }
243    }
244}