abi_stable_derive_lib/sabi_trait/
methods_tokenizer.rs1use 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 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| ¶m.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}