1use super::generics::{GenericType, ParsedGenerics};
2use super::util::parse_brace_content;
3use crate::util::{merge_lifetime_declarations, remap_lifetime_defs, remap_type_lifetimes};
4use proc_macro2::TokenStream;
5use quote::*;
6use std::cmp::Ordering;
7use std::collections::BTreeMap;
8use syn::{parse::*, punctuated::Punctuated, token::Comma, Type, *};
9
10const FN_PREFIX: &str = "cglue_wrapped_";
11
12pub struct WrappedType {
13 pub ty: GenericType,
14 pub ty_ret_tmp: Option<GenericType>,
15 pub ty_static: Option<GenericType>,
16 pub lifetime_bound: Option<Lifetime>,
17 pub lifetime_type_bound: Option<Lifetime>,
18 pub other_bounds: Option<TokenStream>,
19 pub other_bounds_simple: Option<TokenStream>,
20 pub return_conv: Option<ExprClosure>,
21 pub impl_return_conv: Option<TokenStream>,
22 pub inject_ret_tmp: bool,
23 pub unbounded_hrtb: bool,
24}
25
26#[derive(Eq, PartialEq, Clone)]
27pub struct AssocType {
28 pub ident: Ident,
29 pub generics: Generics,
30}
31
32impl AssocType {
33 pub fn remap_for_hrtb(&self) -> Self {
41 let mut params = self.generics.params.iter();
42 match (params.next(), params.next()) {
43 (Some(GenericParam::Lifetime(_)), None) => Self {
44 ident: self.ident.clone(),
45 generics: syn::parse2(quote!(<'cglue_b>)).unwrap(),
46 },
47 (None, _) => self.clone(),
48 _ => panic!("Unsupported generic parameter configuration!"),
49 }
50 }
51}
52
53impl ToTokens for AssocType {
54 fn to_tokens(&self, tokens: &mut TokenStream) {
55 self.ident.to_tokens(tokens);
56 self.generics.to_tokens(tokens);
57 }
58}
59
60impl PartialOrd for AssocType {
61 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
62 Some(self.cmp(other))
63 }
64}
65
66impl Ord for AssocType {
67 fn cmp(&self, other: &Self) -> Ordering {
68 self.ident.cmp(&other.ident)
69 }
70}
71
72impl From<Ident> for AssocType {
73 fn from(ident: Ident) -> Self {
74 Self {
75 ident,
76 generics: Default::default(),
77 }
78 }
79}
80
81impl AssocType {
82 pub fn new(ident: Ident, generics: Generics) -> Self {
83 Self { ident, generics }
84 }
85}
86
87pub struct CustomFuncImpl {
88 pub tys: Punctuated<FnArg, Comma>,
89 pub c_ret_ty: ReturnType,
90 pub pre_call_impl: TokenStream,
91 pub c_inner_body: Option<TokenStream>,
92 pub impl_func_ret: Option<TokenStream>,
93}
94
95#[derive(Default)]
96struct CustomFuncConv {
97 pub pre_call_impl: TokenStream,
98 pub c_inner_body: Option<TokenStream>,
99 pub impl_func_ret: Option<TokenStream>,
100}
101
102impl Parse for CustomFuncImpl {
103 fn parse(input: ParseStream) -> Result<Self> {
104 let content = parse_brace_content(input)?;
105 let tys = Punctuated::parse_terminated(&content)?;
106
107 input.parse::<Token![,]>()?;
108
109 let c_ret_ty = ReturnType::Type(Default::default(), input.parse::<Type>()?.into());
110
111 input.parse::<Token![,]>()?;
112
113 let pre_call_impl: TokenStream = parse_brace_content(input)?.parse()?;
114 input.parse::<Token![,]>()?;
115
116 let c_inner_body: TokenStream = parse_brace_content(input)?.parse()?;
117 let c_inner_body = if c_inner_body.is_empty() {
118 None
119 } else {
120 Some(quote!( { #c_inner_body } ))
121 };
122 input.parse::<Token![,]>()?;
123
124 let impl_func_ret: TokenStream = parse_brace_content(input)?.parse()?;
125 let impl_func_ret = if impl_func_ret.is_empty() {
126 None
127 } else {
128 Some(quote!( { #impl_func_ret } ))
129 };
130
131 input.parse::<Token![,]>().ok();
132
133 Ok(Self {
134 tys,
135 c_ret_ty,
136 pre_call_impl,
137 c_inner_body,
138 impl_func_ret,
139 })
140 }
141}
142
143struct TraitArgConv {
145 to_c_args: TokenStream,
147 call_c_args: TokenStream,
149 c_args: TokenStream,
151 c_cast_args: TokenStream,
153 to_trait_arg: TokenStream,
155}
156
157fn ret_wrap_type<'a>(
158 ty: &mut Type,
159 targets: &'a BTreeMap<Option<AssocType>, WrappedType>,
160) -> Option<(Type, Option<AssocType>, &'a WrappedType)> {
161 if let Some(wrapped) = targets.get(&None) {
165 let WrappedType { ty: new_ty, .. } = wrapped;
166
167 let ret = std::mem::replace(
168 ty,
169 syn::parse2(new_ty.to_token_stream()).expect("Failed to parse wrap_type"),
170 );
171
172 Some((ret, None, wrapped))
173 } else {
174 do_wrap_type(ty, targets)
175 }
176}
177
178fn do_wrap_type<'a>(
179 ty: &mut Type,
180 targets: &'a BTreeMap<Option<AssocType>, WrappedType>,
181) -> Option<(Type, Option<AssocType>, &'a WrappedType)> {
182 match ty {
183 Type::Reference(r) => do_wrap_type(&mut r.elem, targets),
184 Type::Slice(s) => do_wrap_type(&mut s.elem, targets),
185 Type::Path(p) => {
186 let mut iter = p.path.segments.iter();
187 match (&p.qself, p.path.leading_colon, iter.next(), iter.next()) {
188 (None, None, Some(p1), Some(p2)) => {
189 if p1.ident == "Self" {
190 if let Some(wrapped) = targets.get(&Some(p2.ident.clone().into())) {
191 let WrappedType { ty: new_ty, .. } = wrapped;
192
193 std::mem::drop(iter);
194
195 let ident = p2.ident.clone();
196 let generics: Generics = syn::parse2(p2.arguments.to_token_stream())
197 .expect("Failed to parse generics");
198
199 let ret = std::mem::replace(
200 ty,
201 syn::parse2(new_ty.to_token_stream())
202 .expect("Failed to parse wrap_type"),
203 );
204
205 return Some((ret, Some(AssocType::new(ident, generics)), wrapped));
206 }
207 }
208 }
209 (None, None, Some(p1), None) => {
210 if p1.ident == "Self" {
211 let self_return_wrap = targets
212 .get(&Some(p1.ident.clone().into()))
213 .expect("No self-wrap rule specified");
214 let WrappedType { ty: new_ty, .. } = self_return_wrap;
215
216 std::mem::drop(iter);
217
218 let ident = p1.ident.clone();
219 let ret = std::mem::replace(
222 ty,
223 syn::parse2(new_ty.to_token_stream())
224 .expect("Failed to parse self-type wrap"),
225 );
226
227 return Some((ret, Some(ident.into()), self_return_wrap));
228 }
229 }
230 _ => {}
231 }
232
233 std::mem::drop(iter);
234
235 for seg in p.path.segments.iter_mut() {
236 if let PathArguments::AngleBracketed(brac) = &mut seg.arguments {
237 for arg in brac.args.iter_mut() {
238 if let GenericArgument::Type(ty) = arg {
239 let ret = do_wrap_type(ty, targets);
240 if ret.is_some() {
241 return ret;
242 }
243 }
244 }
245 }
246 }
247
248 None
249 }
250 Type::Ptr(ptr) => do_wrap_type(&mut ptr.elem, targets),
251 Type::Tuple(tup) => tup.elems.iter_mut().find_map(|e| do_wrap_type(e, targets)),
252 _ => None,
254 }
255}
256
257impl TraitArgConv {
258 fn new(
259 arg: &FnArg,
260 targets: &BTreeMap<Option<AssocType>, WrappedType>,
261 crate_path: &TokenStream,
262 inject_lifetime: Option<&Lifetime>,
263 inject_lifetime_cast: Option<&Lifetime>,
264 lifetime_map: &BTreeMap<Lifetime, Lifetime>,
265 ) -> Self {
266 let (to_c_args, call_c_args, c_args, c_cast_args, to_trait_arg) = match arg {
267 FnArg::Receiver(r) => {
268 let lifetime = inject_lifetime.or_else(|| r.lifetime());
269 let lifetime_cast = inject_lifetime_cast.or_else(|| r.lifetime());
270
271 if r.reference.is_none() {
272 (
273 quote! {
274 let cont = self.into_ccont();
275 let __ctx = #crate_path::trait_group::CGlueObjBase::cobj_base_ref(&cont).1.clone();
281 },
282 quote!(cont,),
283 quote!(cont: CGlueC,),
284 quote!(cont: CGlueC,),
285 quote!(),
286 )
287 } else if r.mutability.is_some() {
288 (
289 quote!(let cont = self.ccont_mut();),
290 quote!(cont,),
291 quote!(cont: &#lifetime mut CGlueC,),
292 quote!(cont: &#lifetime_cast mut CGlueC,),
293 quote!(),
294 )
295 } else {
296 (
297 quote!(let cont = self.ccont_ref();),
298 quote!(cont,),
299 quote!(cont: &#lifetime CGlueC,),
300 quote!(cont: &#lifetime_cast CGlueC,),
301 quote!(),
302 )
303 }
304 }
305 t if recv_pin(t) => {
306 let lifetime = inject_lifetime.or_else(|| recv_lifetime(t));
307 let lifetime_cast = inject_lifetime_cast.or_else(|| recv_lifetime(t));
308
309 if recv_mutable(t) {
310 (
311 quote!(let cont = self.ccont_pin_mut();),
312 quote!(cont,),
313 quote!(cont: ::core::pin::Pin<&#lifetime mut CGlueC>,),
314 quote!(cont: ::core::pin::Pin<&#lifetime_cast mut CGlueC>,),
315 quote!(),
316 )
317 } else {
318 (
319 quote!(let cont = self.ccont_pin_ref();),
320 quote!(cont,),
321 quote!(cont: ::core::pin::Pin<&#lifetime CGlueC>,),
322 quote!(cont: ::core::pin::Pin<&#lifetime_cast CGlueC>,),
323 quote!(),
324 )
325 }
326 }
327 FnArg::Typed(t) => {
328 let mut t = t.clone();
329 let _old = do_wrap_type(&mut t.ty, targets);
330
331 let name = &*t.pat;
332
333 let name = match name {
335 Pat::Ident(id) => id.ident.to_token_stream(),
336 x => quote!(#x),
337 };
338
339 let ty = &*t.ty;
340
341 let mut ret = None;
342
343 let mut ty = ty.clone();
345 remap_type_lifetimes(&mut ty, lifetime_map);
346
347 match &ty {
352 Type::Reference(r) => {
353 let is_mut = r.mutability.is_some();
354
355 let lt = r
356 .lifetime
357 .as_ref()
358 .map(|lt| lifetime_map.get(lt).unwrap_or(lt))
359 .map(|v| quote!(#v,));
360
361 let new_ty = match &*r.elem {
362 Type::Slice(s) => {
363 let ty = &*s.elem;
364 Some(if is_mut {
365 quote!(#crate_path::slice::CSliceMut<#lt #ty>)
366 } else {
367 quote!(#crate_path::slice::CSliceRef<#lt #ty>)
368 })
369 .map(|v| (v, false))
370 }
371 Type::Path(p) => if let Some("str") =
372 p.path.get_ident().map(|i| i.to_string()).as_deref()
373 {
374 Some(if is_mut {
375 quote!(#crate_path::slice::CSliceMut<#lt u8>)
376 } else {
377 quote!(#crate_path::slice::CSliceRef<#lt u8>)
378 })
379 } else {
380 None
381 }
382 .map(|v| (v, true)),
383 _ => None,
384 };
385
386 if let Some((slty, into_str)) = new_ty {
387 ret = Some((
388 quote!(),
389 quote!(#name.into(),),
390 quote!(#name: #slty,),
391 quote!(#name: #slty,),
392 if into_str {
393 quote!(unsafe { #name.into_str() },)
394 } else {
395 quote!(#name.into(),)
396 },
397 ))
398 }
399 }
400 Type::Path(p) => {
402 let last = p.path.segments.last();
405 if let Some((PathArguments::AngleBracketed(args), last)) =
406 last.map(|l| (&l.arguments, l))
407 {
408 match last.ident.to_string().as_str() {
409 "Option" => {
410 if let Some(GenericArgument::Type(a)) = args.args.first() {
411 if !crate::util::is_null_pointer_optimizable(a, &[]) {
412 ret = Some((
413 quote!(let #name = #name.into();),
414 quote!(#name,),
415 quote!(#name: #crate_path::option::COption<#a>,),
416 quote!(#name: #crate_path::option::COption<#a>,),
417 quote!(#name.into(),),
418 ));
419 }
420 }
421 }
422 "Result" => {
423 let mut args = args.args.iter();
424
425 match (args.next(), args.next(), args.next(), false) {
426 (Some(GenericArgument::Type(_)), _, None, true) => {
427 }
430 (
431 Some(GenericArgument::Type(a)),
432 Some(GenericArgument::Type(b)),
433 None,
434 _,
435 ) => {
436 ret = Some((
437 quote!(let #name = #name.into();),
438 quote!(#name,),
439 quote!(#name: #crate_path::result::CResult<#a, #b>,),
440 quote!(#name: #crate_path::result::CResult<#a, #b>,),
441 quote!(#name.into(),),
442 ));
443 }
444 _ => {}
445 }
446 }
447 _ => {}
448 }
449 }
450 }
451 Type::ImplTrait(t) => {
452 if t.bounds.len() == 1 {
454 if let TypeParamBound::Trait(t) = t.bounds.first().unwrap() {
455 if t.path.segments.len() == 1 {
456 let seg = t.path.segments.first().unwrap();
457 if seg.ident == format_ident!("Into") {
458 if let PathArguments::AngleBracketed(a) = &seg.arguments {
459 if a.args.len() == 1 {
460 let ty = a.args.first().unwrap();
461
462 ret = Some((
463 quote!(let #name = #name.into();),
464 quote!(#name,),
465 quote!(#name: #ty,),
466 quote!(#name: #ty,),
467 quote!(#name,),
468 ))
469 }
470 }
471 }
472 }
473 }
474 }
475 }
476 _ => {}
477 }
478
479 ret.unwrap_or_else(|| {
480 (
481 quote!(let #name = #name;),
482 quote!(#name,),
483 quote!(#name: #ty,),
484 quote!(#name: #ty,),
485 quote!(#name,),
486 )
487 })
488 }
489 };
490
491 Self {
492 to_c_args,
493 call_c_args,
494 c_args,
495 c_cast_args,
496 to_trait_arg,
497 }
498 }
499}
500
501pub struct ParsedFunc {
502 name: Ident,
503 trait_name: Ident,
504 safe: bool,
505 abi: FuncAbi,
506 unwind_safe: bool,
507 receiver: FnArg,
508 orig_args: Vec<FnArg>,
509 args: Vec<TraitArgConv>,
510 out: ParsedReturnType,
511 generics: ParsedGenerics,
512 sig_generics: ParsedGenerics,
513 custom_conv: CustomFuncConv,
514 only_c_side: bool,
515}
516
517fn extract_pin(t: &Type) -> Option<&Type> {
518 if let Type::Path(v) = t {
519 if let Some(seg) = v.path.segments.last() {
520 if seg.ident != "Pin" {
521 return None;
522 }
523 if let PathArguments::AngleBracketed(a) = &seg.arguments {
524 if a.args.len() == 1 {
525 let a = a.args.first()?;
526 if let GenericArgument::Type(t) = a {
527 return Some(t);
528 }
529 }
530 }
531 }
532 }
533 None
534}
535
536fn recv_pin(recv: &FnArg) -> bool {
537 match recv {
538 FnArg::Receiver(_) => false,
539 FnArg::Typed(t) => matches!(extract_pin(&t.ty), Some(Type::Reference(_))),
540 }
541}
542
543fn recv_lifetime(recv: &FnArg) -> Option<&Lifetime> {
544 match recv {
545 FnArg::Receiver(r) => r.lifetime(),
546 FnArg::Typed(t) => {
547 if let Some(Type::Reference(r)) = extract_pin(&t.ty) {
548 r.lifetime.as_ref()
549 } else {
550 None
551 }
552 }
553 }
554}
555
556fn recv_reference(recv: &FnArg) -> bool {
557 match recv {
558 FnArg::Receiver(r) => r.reference.is_some(),
559 FnArg::Typed(t) => matches!(extract_pin(&t.ty), Some(Type::Reference(_))),
560 }
561}
562
563fn recv_mutable(recv: &FnArg) -> bool {
564 match recv {
565 FnArg::Receiver(r) => r.mutability.is_some(),
566 FnArg::Typed(t) => matches!(
567 extract_pin(&t.ty),
568 Some(Type::Reference(TypeReference {
569 mutability: Some(_),
570 ..
571 }))
572 ),
573 }
574}
575
576impl ParsedFunc {
577 #[allow(clippy::too_many_arguments)]
578 pub fn new(
579 sig: Signature,
580 trait_name: Ident,
581 generics: &ParsedGenerics,
582 wrap_types: &BTreeMap<Option<AssocType>, WrappedType>,
583 res_override: Option<&Ident>,
584 int_result: bool,
585 crate_path: &TokenStream,
586 only_c_side: bool,
587 custom_impl: Option<CustomFuncImpl>,
588 unwind_safe: bool,
589 ) -> Option<Self> {
590 let name = sig.ident;
591 let safe = sig.unsafety.is_none();
592 let abi = From::from(sig.abi);
593 let mut args: Vec<TraitArgConv> = vec![];
594 let mut orig_args = vec![];
595
596 let mut receiver = None;
597
598 let unsafety = if safe { quote!(unsafe) } else { quote!() };
599
600 for input in sig.inputs.iter() {
601 match &input {
602 FnArg::Receiver(_) => {
603 receiver = Some(input.clone());
604 }
605 FnArg::Typed(v) => {
606 if let Pat::Ident(ref i) = *v.pat {
607 if i.ident == "self" {
608 receiver = Some(input.clone());
609 }
610 }
611 }
612 }
613 }
614
615 let receiver = receiver?;
616
617 let out = ParsedReturnType::new(
618 (sig.output, custom_impl.as_ref().map(|i| &i.c_ret_ty)),
619 wrap_types,
620 res_override,
621 int_result,
622 &unsafety,
623 (&name, &receiver),
624 (crate_path, &trait_name, generics),
625 );
626
627 let custom_conv = if let Some(CustomFuncImpl {
629 tys,
630 pre_call_impl,
631 c_inner_body,
632 impl_func_ret,
633 ..
634 }) = custom_impl
635 {
636 orig_args.extend(sig.inputs.into_iter());
637 for arg in orig_args
639 .iter()
640 .filter(|a| match a {
641 FnArg::Receiver(_) => true,
642 FnArg::Typed(v) => {
643 if let Pat::Ident(ref i) = *v.pat {
644 if i.ident == "self" {
645 return true;
646 }
647 }
648 false
649 }
650 })
651 .take(1)
652 .chain(tys.iter())
653 {
654 args.push(TraitArgConv::new(
655 arg,
656 wrap_types,
657 crate_path,
658 out.lifetime.as_ref(),
659 out.lifetime_cast.as_ref(),
660 &out.lifetime_map,
661 ));
662 }
663
664 CustomFuncConv {
665 pre_call_impl,
666 c_inner_body,
667 impl_func_ret,
668 }
669 } else {
670 for input in sig.inputs.into_iter() {
671 let func = TraitArgConv::new(
672 &input,
673 wrap_types,
674 crate_path,
675 out.lifetime.as_ref(),
676 out.lifetime_cast.as_ref(),
677 &out.lifetime_map,
678 );
679
680 args.push(func);
681 orig_args.push(input);
682 }
683
684 Default::default()
685 };
686
687 let generics = generics.clone();
688
689 let sig_generics = ParsedGenerics::from(&sig.generics);
690
691 Some(Self {
692 name,
693 trait_name,
694 safe,
695 abi,
696 unwind_safe,
697 receiver,
698 orig_args,
699 args,
700 out,
701 generics,
702 sig_generics,
703 only_c_side,
704 custom_conv,
705 })
706 }
707
708 pub fn ret_tmp_def(&self, stream: &mut TokenStream) {
709 let name = &self.name;
710 if let (Some(_), Some(ty)) = (
712 &self.out.injected_ret_tmp,
713 self.out
714 .injected_ret_tmp_static
715 .as_ref()
716 .or(self.out.injected_ret_tmp.as_ref()),
717 ) {
718 let gen = if recv_mutable(&self.receiver) {
719 quote!(#name: ::core::mem::MaybeUninit<#ty>,)
720 } else {
721 quote!(#name: ::core::cell::Cell<::core::mem::MaybeUninit<#ty>>,)
722 };
723 stream.extend(gen);
724 }
725 }
726
727 pub fn ret_default_def(&self, stream: &mut TokenStream) {
728 let name = &self.name;
729 if self.out.injected_ret_tmp.is_some() {
730 let gen = if recv_mutable(&self.receiver) {
731 quote!(#name: ::core::mem::MaybeUninit::uninit(),)
732 } else {
733 quote!(#name: ::core::cell::Cell::new(::core::mem::MaybeUninit::uninit()),)
734 };
735 stream.extend(gen);
736 }
737 }
738
739 pub fn ret_getter_def(&self, stream: &mut TokenStream) {
740 let name = &self.name;
741
742 if let Some(ty) = &self.out.injected_ret_tmp {
743 let gen = match (&self.out.lifetime, recv_mutable(&self.receiver)) {
744 (Some(lt), true) => {
745 quote! {
746 fn #name<#lt>(&#lt mut self) -> &#lt mut ::core::mem::MaybeUninit<#ty> {
747 unsafe { std::mem::transmute(&mut self.#name) }
752 }
753 }
754 }
755 (None, true) => {
756 quote! {
757 fn #name(&mut self) -> &mut ::core::mem::MaybeUninit<#ty> {
758 &mut self.#name
759 }
760 }
761 }
762 (Some(lt), false) => {
763 quote! {
764 #[allow(clippy::mut_from_ref)]
765 fn #name<#lt>(&#lt self) -> &#lt mut ::core::mem::MaybeUninit<#ty> {
766 unsafe { std::mem::transmute(self.#name.as_ptr().as_mut().unwrap()) }
777 }
778 }
779 }
780 (None, false) => {
781 quote! {
782 #[allow(clippy::mut_from_ref)]
783 fn #name(&self) -> &mut ::core::mem::MaybeUninit<#ty> {
784 unsafe { self.#name.as_ptr().as_mut().unwrap() }
791 }
792 }
793 }
794 };
795
796 stream.extend(gen);
797 }
798 }
799
800 pub fn vtbl_args(&self) -> TokenStream {
801 let mut ret = TokenStream::new();
802
803 for arg in &self.args {
804 arg.c_args.to_tokens(&mut ret);
805 }
806
807 ret
808 }
809
810 pub fn vtbl_args_cast(&self) -> TokenStream {
811 let mut ret = TokenStream::new();
812
813 for arg in &self.args {
814 arg.c_cast_args.to_tokens(&mut ret);
815 }
816
817 ret
818 }
819
820 pub fn trait_args(&self) -> TokenStream {
821 let mut ret = TokenStream::new();
822
823 for arg in &self.orig_args {
824 let arg = match arg {
825 FnArg::Typed(pat) => {
826 if let Pat::Ident(PatIdent { ident, .. }) = &*pat.pat {
827 let ty = &*pat.ty;
828 quote!(#ident: #ty, )
830 } else {
831 quote!(#arg, )
832 }
833 }
834 FnArg::Receiver(rcv) => {
835 if rcv.reference.is_some() {
836 quote!(#rcv,)
837 } else {
838 quote!(self,)
839 }
840 }
841 };
842
843 arg.to_tokens(&mut ret);
844 }
845
846 ret
847 }
848
849 pub fn trait_passthrough_args(&self, skip: usize) -> TokenStream {
850 let mut ret = TokenStream::new();
851
852 for arg in self.orig_args.iter().skip(skip) {
853 match arg {
854 FnArg::Typed(ty) => {
855 let pat = &ty.pat;
856 quote!(#pat,).to_tokens(&mut ret);
857 }
858 FnArg::Receiver(_) => {
859 quote!(self,).to_tokens(&mut ret);
860 }
861 }
862 }
863
864 ret
865 }
866
867 pub fn to_c_def_args(&self) -> TokenStream {
868 let mut ret = TokenStream::new();
869
870 for arg in &self.args {
871 arg.to_c_args.to_tokens(&mut ret);
872 }
873
874 ret
875 }
876
877 pub fn to_c_call_args(&self) -> TokenStream {
878 let mut ret = TokenStream::new();
879
880 for arg in &self.args {
881 arg.call_c_args.to_tokens(&mut ret);
882 }
883
884 ret
885 }
886
887 pub fn to_trait_call_args(&self) -> TokenStream {
888 let mut ret = TokenStream::new();
889
890 for arg in &self.args {
891 arg.to_trait_arg.to_tokens(&mut ret);
892 }
893
894 ret
895 }
896
897 pub fn vtbl_def(&self, stream: &mut TokenStream) {
899 let name = &self.name;
900 let unsafety = &self.get_safety();
901 let extern_abi = self.extern_abi();
902 let args = self.vtbl_args();
903 let ParsedReturnType {
904 c_out,
905 c_cast_out,
906 c_ret_params,
907 lifetime,
908 lifetime_cast,
909 unbounded_hrtb,
910 lifetime_map,
911 ..
912 } = &self.out;
913
914 let ParsedGenerics {
915 life_declare: sig_life_declare,
916 ..
917 } = &self.sig_generics;
918
919 let sig_life_declare = remap_lifetime_defs(sig_life_declare, lifetime_map);
920
921 let (hrtb, args, c_out) = match (
922 lifetime.as_ref().filter(|lt| lt.ident != "cglue_a"),
923 lifetime_cast,
924 *unbounded_hrtb,
925 ) {
926 (_, Some(lifetime), false) => (quote!(#lifetime), self.vtbl_args_cast(), c_cast_out),
927 (Some(lifetime), _, _) => (quote!(#lifetime), args, c_out),
928 _ => (quote!(), args, c_out),
929 };
930
931 let sig_life_declare = merge_lifetime_declarations(&sig_life_declare, &parse_quote!(#hrtb));
932
933 let gen = quote! {
934 #name: for<#sig_life_declare> #unsafety extern #extern_abi fn(#args #c_ret_params) #c_out,
935 };
936
937 if cfg!(feature = "layout_checks") && self.unwind_safe {
939 let ty = quote!(for<#sig_life_declare> #unsafety extern "C" fn(#args #c_ret_params))
940 .to_string();
941 stream.extend(quote!(#[sabi(unsafe_change_type = #ty)]));
942 }
943
944 stream.extend(gen);
945 }
946
947 pub fn vtbl_getter_def(&self, stream: &mut TokenStream) {
949 let name = &self.name;
950 let args = self.vtbl_args();
951 let extern_abi = self.extern_abi();
952 let ParsedReturnType {
953 c_out,
954 c_cast_out,
955 c_ret_params,
956 lifetime,
957 lifetime_cast,
958 unbounded_hrtb,
959 lifetime_map,
960 ..
961 } = &self.out;
962
963 let ParsedGenerics {
964 life_declare: sig_life_declare,
965 ..
966 } = &self.sig_generics;
967
968 let sig_life_declare = remap_lifetime_defs(sig_life_declare, lifetime_map);
969
970 let (hrtb, args, c_out) = match (
971 lifetime.as_ref().filter(|lt| lt.ident != "cglue_a"),
972 lifetime_cast,
973 *unbounded_hrtb,
974 ) {
975 (_, Some(lifetime), false) => (quote!(#lifetime), self.vtbl_args_cast(), c_cast_out),
976 (Some(lifetime), _, _) => (quote!(#lifetime), args, c_out),
977 _ => (quote!(), args, c_out),
978 };
979
980 let sig_life_declare = merge_lifetime_declarations(&sig_life_declare, &parse_quote!(#hrtb));
981
982 let doc_text = format!(" Getter for {}.", name);
983
984 let gen = quote! {
985 #[doc = #doc_text]
986 pub fn #name(&self) -> for<#sig_life_declare> unsafe extern #extern_abi fn(#args #c_ret_params) #c_out {
990 unsafe { ::core::mem::transmute(self.#name) }
991 }
992 };
993
994 stream.extend(gen);
995
996 if lifetime_cast.is_some() && *unbounded_hrtb {
997 let name2 = format_ident!("{}_lifetimed", name);
998
999 let safety = self.get_safety();
1000
1001 let args_cast = self.vtbl_args_cast();
1002
1003 let gen = quote! {
1004 #[doc = #doc_text]
1005 unsafe fn #name2(&self) -> for<#lifetime_cast> #safety extern #extern_abi fn(#args_cast #c_ret_params) #c_cast_out {
1014 ::core::mem::transmute(self.#name)
1015 }
1016 };
1017
1018 stream.extend(gen);
1019 }
1020 }
1021
1022 pub fn is_wrapped(&self) -> bool {
1023 true }
1025
1026 pub fn cfunc_def(
1030 &self,
1031 tokens: &mut TokenStream,
1032 trg_path: &TokenStream,
1033 ret_tmp: &TokenStream,
1034 assocs: &ParsedGenerics,
1035 assoc_equality: &TokenStream,
1036 ) -> Option<&TokenStream> {
1037 if !self.is_wrapped() {
1038 return None;
1039 }
1040
1041 let name = &self.name;
1042 let args = self.vtbl_args();
1043 let extern_abi = self.extern_abi();
1044 let ParsedReturnType {
1045 c_out,
1046 c_where_bounds,
1047 c_where_bounds_cast,
1048 c_ret,
1049 c_pre_call,
1050 c_ret_params,
1051 use_hrtb,
1052 lifetime,
1053 lifetime_cast,
1054 unbounded_hrtb,
1055 lifetime_map,
1056 ..
1057 } = &self.out;
1058 let call_args = self.to_trait_call_args();
1059
1060 let trname = &self.trait_name;
1061 let fnname = format_ident!("{}{}", FN_PREFIX, name);
1062 let safety = self.get_safety();
1063
1064 let ParsedGenerics {
1065 life_declare,
1066 life_use,
1067 gen_declare,
1068 gen_use,
1069 gen_where_bounds,
1070 ..
1071 } = &self.generics;
1072
1073 let assoc_declare = &assocs.gen_declare;
1074
1075 let ParsedGenerics {
1076 life_declare: sig_life_declare,
1077 ..
1078 } = &self.sig_generics;
1079
1080 let sig_life_declare = remap_lifetime_defs(sig_life_declare, lifetime_map);
1081
1082 let tmp_lifetime = if *use_hrtb && !life_use.is_empty() {
1083 quote!('cglue_b, )
1084 } else {
1085 quote!(#life_use)
1086 };
1087
1088 let tmp_lifetime_anon = if *use_hrtb && !life_use.is_empty() {
1089 quote!('_, )
1090 } else {
1091 quote!(#life_use)
1092 };
1093
1094 let life_declare = if lifetime.is_none() || !life_declare.is_empty() {
1097 life_declare.clone()
1098 } else {
1099 parse_quote!(#lifetime,)
1100 };
1101
1102 let sig_life_declare = merge_lifetime_declarations(&sig_life_declare, &life_declare);
1103
1104 let mut container_bound = quote!();
1105
1106 let (c_pre_call, cglue_c_into_inner) = if !recv_reference(&self.receiver) {
1107 container_bound.extend(quote!(#trg_path::CGlueObjBase<Context = CGlueCtx> + ));
1108
1109 (
1110 quote! {
1111 let (this, cglue_ctx) = cont.cobj_base_owned();
1112 let this = unsafe { #trg_path::IntoInner::into_inner(this) };
1113 #c_pre_call
1114 },
1115 Some(quote!(
1116 CGlueC::InstType: #trg_path::IntoInner<InnerTarget = CGlueC::ObjType>,
1117 )),
1118 )
1119 } else if recv_mutable(&self.receiver) {
1120 let cobj_func = if recv_pin(&self.receiver) {
1121 quote!(cobj_pin_mut)
1122 } else {
1123 quote!(cobj_mut)
1124 };
1125 container_bound.extend(quote!(#trg_path::CGlueObjMut<#ret_tmp, Context = CGlueCtx> + ));
1126 (
1127 quote! {
1128 let (this, ret_tmp, cglue_ctx) = cont.#cobj_func();
1129 #c_pre_call
1130 },
1131 None,
1132 )
1133 } else {
1134 let cobj_func = if recv_pin(&self.receiver) {
1135 quote!(cobj_pin_ref)
1136 } else {
1137 quote!(cobj_ref)
1138 };
1139 container_bound.extend(quote!(#trg_path::CGlueObjRef<#ret_tmp, Context = CGlueCtx> + ));
1140 (
1141 quote! {
1142 let (this, ret_tmp, cglue_ctx) = cont.#cobj_func();
1143 #c_pre_call
1144 },
1145 None,
1146 )
1147 };
1148
1149 let inner_impl = if let Some(body) = self.custom_conv.c_inner_body.as_ref() {
1150 body.clone()
1151 } else {
1152 quote!(<CGlueC::ObjType as #trname<#tmp_lifetime_anon #gen_use>>::#name(this, #call_args))
1153 };
1154
1155 let c_where_bounds = if lifetime_cast.is_some() && *unbounded_hrtb {
1156 c_where_bounds_cast
1157 } else {
1158 c_where_bounds
1159 };
1160
1161 let ctx_bound = super::traits::ctx_bound();
1162
1163 let gen = quote! {
1164 #safety extern #extern_abi fn #fnname<#sig_life_declare CGlueC: #container_bound, CGlueCtx: #ctx_bound, #gen_declare #assoc_declare>(#args #c_ret_params) #c_out where #gen_where_bounds #c_where_bounds #cglue_c_into_inner CGlueC::ObjType: for<'cglue_b> #trname<#tmp_lifetime #gen_use #assoc_equality>, {
1165 #c_pre_call
1166 let ret = #inner_impl;
1167 #c_ret
1168 }
1169 };
1170
1171 tokens.extend(gen);
1172
1173 Some(c_where_bounds)
1174 }
1175
1176 pub fn vtbl_default_def(&self, tokens: &mut TokenStream) {
1177 let name = &self.name;
1178 let fnname = format_ident!("{}{}", FN_PREFIX, name);
1179 tokens.extend(quote!(#name: #fnname,));
1180 }
1181
1182 pub fn get_safety(&self) -> TokenStream {
1183 if self.safe {
1184 quote!()
1185 } else {
1186 quote!(unsafe)
1187 }
1188 }
1189
1190 pub fn extern_abi(&self) -> TokenStream {
1191 if self.unwind_safe {
1192 quote!("C-unwind")
1193 } else {
1194 quote!("C")
1195 }
1196 }
1197
1198 pub fn trait_impl(&self, tokens: &mut TokenStream) -> (bool, bool, bool) {
1199 if !self.only_c_side {
1200 let name = &self.name;
1201 let args = self.trait_args();
1202 let ParsedReturnType {
1203 ty: out,
1204 impl_func_ret,
1205 c_ret_precall_def,
1206 c_call_ret_args,
1207 lifetime_cast,
1208 unbounded_hrtb,
1209 ..
1210 } = &self.out;
1211 let def_args = self.to_c_def_args();
1212 let call_args = self.to_c_call_args();
1213 let safety = self.get_safety();
1214 let abi = self.abi.prefix();
1215
1216 let ParsedGenerics {
1217 life_declare: sig_life_declare,
1218 gen_declare: sig_gen_declare,
1219 ..
1220 } = &self.sig_generics;
1221
1222 let get_vfunc = if lifetime_cast.is_some() && *unbounded_hrtb {
1223 let name_lifetimed = format_ident!("{}_lifetimed", name);
1224 quote!(unsafe { self.get_vtbl().#name_lifetimed() })
1225 } else {
1226 quote!(self.get_vtbl().#name)
1227 };
1228
1229 let custom_precall_impl = self.custom_conv.pre_call_impl.to_token_stream();
1230
1231 let impl_func_ret = if let Some(impl_func_ret) = &self.custom_conv.impl_func_ret {
1232 impl_func_ret
1233 } else {
1234 impl_func_ret
1235 };
1236
1237 let gen = quote! {
1238 #[inline(always)]
1239 #safety #abi fn #name <#sig_life_declare #sig_gen_declare> (#args) #out {
1240 let __cglue_vfunc = #get_vfunc;
1241 #custom_precall_impl
1242 #def_args
1243 #c_ret_precall_def
1244 let mut ret = __cglue_vfunc(#call_args #c_call_ret_args);
1245 #impl_func_ret
1246 }
1247 };
1248
1249 tokens.extend(gen);
1250 }
1251
1252 (
1253 recv_mutable(&self.receiver),
1254 !recv_reference(&self.receiver),
1255 self.out.return_self,
1256 )
1257 }
1258
1259 pub fn forward_wrapped_trait_impl(&self, tokens: &mut TokenStream) -> bool {
1260 if !recv_reference(&self.receiver) {
1261 return false;
1262 }
1263
1264 let name = &self.name;
1265 let args = self.trait_args();
1266 let passthrough_args = self.trait_passthrough_args(1);
1267 let ParsedReturnType {
1268 ty: out, use_wrap, ..
1269 } = &self.out;
1270 let safety = self.get_safety();
1271 let abi = self.abi.prefix();
1272
1273 let ParsedGenerics {
1274 life_declare,
1275 gen_declare,
1276 ..
1277 } = &self.sig_generics;
1278
1279 let return_out = if *use_wrap {
1280 quote!(Self(ret))
1281 } else {
1282 quote!(ret)
1283 };
1284
1285 let gen = quote! {
1286 #[inline(always)]
1287 #safety #abi fn #name <#life_declare #gen_declare> (#args) #out {
1288 let ret = (self.0).#name(#passthrough_args);
1289 #return_out
1290 }
1291 };
1292
1293 tokens.extend(gen);
1294
1295 recv_mutable(&self.receiver)
1296 }
1297
1298 pub fn arc_wrapped_trait_impl(&self, tokens: &mut TokenStream) {
1299 let name = &self.name;
1300 let args = self.trait_args();
1301 let passthrough_args = self.trait_passthrough_args(1);
1302 let ParsedReturnType {
1303 ty: out, use_wrap, ..
1304 } = &self.out;
1305 let safety = self.get_safety();
1306 let abi = self.abi.prefix();
1307
1308 let ParsedGenerics {
1309 life_declare,
1310 gen_declare,
1311 ..
1312 } = &self.sig_generics;
1313
1314 let get_inner = if !recv_reference(&self.receiver) {
1315 quote!(self.into_inner())
1316 } else if recv_mutable(&self.receiver) {
1317 quote!(self.as_mut())
1318 } else {
1319 quote!(self.as_ref())
1320 };
1321
1322 let return_out = if *use_wrap {
1323 quote!((ret, arc).into())
1324 } else {
1325 quote!(ret)
1326 };
1327
1328 let gen = quote! {
1329 #[inline(always)]
1330 #safety #abi fn #name <#life_declare #gen_declare> (#args) #out {
1331 let (inner, arc) = #get_inner;
1332 let ret = inner.#name(#passthrough_args);
1333 #return_out
1334 }
1335 };
1336
1337 tokens.extend(gen);
1338 }
1339
1340 pub fn int_trait_impl(
1341 &self,
1342 ext_path: Option<&Path>,
1343 ext_name: &Ident,
1344 tokens: &mut TokenStream,
1345 ) {
1346 let name = &self.name;
1347 let args = self.trait_args();
1348 let passthrough_args = self.trait_passthrough_args(0);
1349 let ParsedReturnType { ty: out, .. } = &self.out;
1350 let safety = self.get_safety();
1351 let abi = self.abi.prefix();
1352
1353 let gen = quote! {
1354 #[inline(always)]
1355 #safety #abi fn #name (#args) #out {
1356 #ext_path #ext_name::#name(#passthrough_args)
1357 }
1358 };
1359
1360 tokens.extend(gen);
1361 }
1362}
1363
1364#[derive(Debug, Eq, PartialEq)]
1365enum FuncAbi {
1366 ReprC,
1367 ReprCUnwind,
1368 Wrapped,
1369}
1370
1371impl FuncAbi {
1372 pub fn prefix(&self) -> TokenStream {
1373 match self {
1374 FuncAbi::ReprC => quote!(extern "C"),
1375 FuncAbi::ReprCUnwind => quote!(extern "C-unwind"),
1376 FuncAbi::Wrapped => quote!(),
1377 }
1378 }
1379}
1380
1381impl From<Option<Abi>> for FuncAbi {
1382 fn from(abi: Option<Abi>) -> Self {
1383 if let Some(Abi {
1385 extern_token: _,
1386 name: Some(abi),
1387 }) = abi
1388 {
1389 if abi.value() == "C" {
1390 return FuncAbi::ReprC;
1391 }
1392
1393 if abi.value() == "C-unwind" {
1394 return FuncAbi::ReprCUnwind;
1395 }
1396 }
1397
1398 FuncAbi::Wrapped
1399 }
1400}
1401
1402struct ParsedReturnType {
1403 ty: ReturnType,
1404 c_out: TokenStream,
1405 c_cast_out: TokenStream,
1406 c_where_bounds: TokenStream,
1407 c_where_bounds_cast: TokenStream,
1408 c_ret_params: TokenStream,
1409 c_ret_precall_def: TokenStream,
1410 c_call_ret_args: TokenStream,
1411 c_pre_call: Option<TokenStream>,
1412 c_ret: TokenStream,
1413 impl_func_ret: TokenStream,
1414 injected_ret_tmp: Option<GenericType>,
1420 injected_ret_tmp_static: Option<GenericType>,
1421 use_hrtb: bool,
1422 lifetime: Option<Lifetime>,
1423 lifetime_cast: Option<Lifetime>,
1424 unbounded_hrtb: bool,
1425 return_self: bool,
1426 use_wrap: bool,
1427 lifetime_map: BTreeMap<Lifetime, Lifetime>,
1429}
1430
1431#[allow(clippy::single_match)]
1433fn wrapped_lifetime(mut ty: Type, target: Lifetime) -> Type {
1434 match &mut ty {
1435 Type::Path(path) => {
1436 for seg in path.path.segments.iter_mut() {
1437 if let PathArguments::AngleBracketed(args) = &mut seg.arguments {
1438 for arg in args.args.iter_mut() {
1439 match arg {
1440 GenericArgument::Lifetime(lt) => {
1441 if lt.ident != format_ident!("static") {
1442 *lt = target.clone()
1443 }
1444 }
1445 GenericArgument::Type(ty) => {
1446 *ty = wrapped_lifetime(ty.clone(), target.clone())
1447 }
1448 _ => {}
1449 }
1450 }
1451 }
1452 }
1453 }
1454 _ => {}
1455 }
1456 ty
1457}
1458
1459impl ParsedReturnType {
1460 #[allow(clippy::never_loop)]
1461 fn new(
1462 (ty, c_override): (ReturnType, Option<&ReturnType>),
1463 targets: &BTreeMap<Option<AssocType>, WrappedType>,
1464 res_override: Option<&Ident>,
1465 int_result: bool,
1466 unsafety: &TokenStream,
1467 (func_name, receiver): (&Ident, &FnArg),
1468 (crate_path, trait_name, trait_generics): (&TokenStream, &Ident, &ParsedGenerics),
1469 ) -> Self {
1470 let mut c_ty = c_override.unwrap_or(&ty).clone();
1471
1472 let mut ret = Self {
1473 c_out: ty.to_token_stream(),
1474 c_cast_out: ty.to_token_stream(),
1475 ty,
1476 c_where_bounds: quote!(),
1477 c_where_bounds_cast: quote!(),
1478 c_ret_params: quote!(),
1479 c_ret_precall_def: quote!(),
1480 c_call_ret_args: quote!(),
1481 c_pre_call: None,
1482 c_ret: quote!(ret),
1483 impl_func_ret: quote!(ret),
1484 injected_ret_tmp: None,
1485 injected_ret_tmp_static: None,
1486 use_hrtb: false,
1487 lifetime: None,
1488 lifetime_cast: None,
1489 unbounded_hrtb: false,
1490 return_self: false,
1491 use_wrap: false,
1492 lifetime_map: Default::default(),
1493 };
1494
1495 if let ReturnType::Type(_, ty) = &mut c_ty {
1496 let mut ty_cast = None;
1497
1498 if let Some(wrapped) = ret_wrap_type(&mut *ty, targets) {
1501 let old_ty = wrapped.0;
1502 let trait_ty = wrapped.1;
1503 let WrappedType {
1504 return_conv,
1505 lifetime_bound,
1506 lifetime_type_bound,
1507 other_bounds,
1508 other_bounds_simple,
1509 inject_ret_tmp,
1510 impl_return_conv,
1511 ty_static,
1512 ty_ret_tmp,
1513 ty:
1514 GenericType {
1515 generic_lifetimes: old_lifetimes,
1516 ..
1517 },
1518 ..
1519 } = wrapped.2;
1520
1521 ret.lifetime_map = trait_ty
1523 .iter()
1524 .flat_map(|assoc| assoc.generics.lifetimes().map(|v| &v.lifetime).cloned())
1525 .zip(old_lifetimes.iter().cloned())
1526 .collect();
1527
1528 let (mutable, lifetime) = match (inject_ret_tmp, &**ty) {
1531 (true, Type::Reference(ty)) => {
1532 (ty.mutability.is_some(), ty.lifetime.as_ref().cloned())
1533 }
1534 (false, _) => (false, None),
1535 _ => {
1536 panic!(
1537 "Wrapped ref return currently only valid for references! (ty: {ty})",
1538 ty = ty.to_token_stream()
1539 )
1540 }
1541 };
1542
1543 let unbounded_hrtb = lifetime.is_none() && lifetime_type_bound.is_none();
1544
1545 let cglue_b_lifetime = Lifetime {
1546 apostrophe: proc_macro2::Span::call_site(),
1547 ident: format_ident!("cglue_b"),
1548 };
1549
1550 let lifetime = lifetime.or_else(|| lifetime_bound.clone()).or_else(|| {
1551 Some(Lifetime {
1552 apostrophe: proc_macro2::Span::call_site(),
1553 ident: format_ident!("cglue_a"),
1554 })
1555 });
1556
1557 let lifetime_cast = if lifetime
1558 .as_ref()
1559 .filter(|lt| lt.ident == "cglue_a")
1560 .is_some()
1561 {
1562 ty_cast = Some(ty.clone());
1563 Some(cglue_b_lifetime.clone())
1564 } else {
1565 None
1566 };
1567
1568 if let Some(lifetime) = &lifetime {
1569 **ty = wrapped_lifetime(*ty.clone(), lifetime.clone());
1570 }
1571
1572 let lifetime_type_bound = lifetime_type_bound.clone().map(|lt| {
1574 if lt.ident != "static" {
1575 cglue_b_lifetime
1576 } else {
1577 lt
1578 }
1579 });
1580
1581 let ret_wrap = match return_conv {
1582 Some(conv) => quote! {
1583 let mut conv = #conv;
1584 conv(ret)
1585 },
1586 _ => quote!(ret.into()),
1587 };
1588
1589 let life_use = &trait_generics.life_use;
1590 let gen_use = &trait_generics.gen_use;
1591
1592 let is_static = lifetime_type_bound.map(|l| l.ident == "static") == Some(true);
1595
1596 let (static_bound, static_bound_simple) = if is_static && trait_ty.is_some() {
1597 if life_use.is_empty() {
1598 (
1599 quote!(for<'cglue_b> <CGlueC::ObjType as #trait_name<#gen_use>>::#trait_ty: 'static,),
1600 quote!(for<'cglue_b> <CGlueC::ObjType as #trait_name<#gen_use>>::#trait_ty: 'static,),
1601 )
1602 } else {
1603 (
1604 quote!(for<'cglue_b> <CGlueC::ObjType as #trait_name<'cglue_b, #gen_use>>::#trait_ty: 'static,),
1605 quote!(<CGlueC::ObjType as #trait_name<'cglue_a, #gen_use>>::#trait_ty: 'static,),
1606 )
1607 }
1608 } else {
1609 (quote!(), quote!())
1610 };
1611
1612 let where_bound = quote!(#static_bound #other_bounds);
1613 let where_bound_simple = quote!(#static_bound_simple #other_bounds_simple);
1614
1615 if let (true, Type::Reference(ty)) = (inject_ret_tmp, &mut **ty) {
1617 ty.lifetime = lifetime.clone();
1618
1619 if let Some(ty_cast) = &mut ty_cast {
1620 if let Type::Reference(ty_cast) = &mut **ty_cast {
1621 ty_cast.lifetime = lifetime_cast.clone();
1622 }
1623 }
1624 };
1625
1626 let (injected_ret_tmp, c_pre_call) = match (inject_ret_tmp, mutable) {
1627 (true, false) => (
1628 ty_ret_tmp.clone(),
1629 quote!(let ret_tmp = ret_tmp.#func_name();),
1630 ),
1631 (true, true) => (
1632 ty_ret_tmp.clone(),
1633 quote!(let ret_tmp = ret_tmp.#func_name();),
1634 ),
1635 _ => (None, quote!()),
1636 };
1637
1638 let c_pre_call = if recv_reference(receiver) {
1639 quote!(#c_pre_call let cglue_ctx = cglue_ctx.clone();)
1640 } else {
1641 c_pre_call
1642 };
1643
1644 let impl_return_conv = impl_return_conv
1645 .as_ref()
1646 .cloned()
1647 .unwrap_or_else(|| quote!(ret));
1648
1649 let return_self = trait_ty.map(|i| i.ident == "Self") == Some(true);
1650
1651 ret.c_out = quote!(-> #ty);
1652 ret.c_cast_out = quote!(-> #ty_cast);
1653
1654 if return_self {
1657 *ty = Box::new(old_ty);
1658 }
1659
1660 ret.c_where_bounds = where_bound;
1661 ret.c_where_bounds_cast = where_bound_simple;
1662 ret.c_ret_params = quote!();
1663 ret.c_ret_precall_def = quote!();
1664 ret.c_call_ret_args = quote!();
1665 ret.c_pre_call = Some(c_pre_call);
1666 ret.c_ret = quote!(#ret_wrap);
1667 ret.impl_func_ret = impl_return_conv;
1668 ret.injected_ret_tmp = injected_ret_tmp;
1669 ret.injected_ret_tmp_static = ty_static.clone();
1670 ret.use_hrtb = true;
1671 ret.unbounded_hrtb = unbounded_hrtb;
1672 ret.return_self = return_self;
1673 ret.use_wrap = true;
1674 ret.lifetime = lifetime;
1675 ret.lifetime_cast = lifetime_cast;
1676 } else {
1677 ret.c_out = quote!(-> #ty);
1678 }
1679
1680 match &mut **ty {
1681 Type::Reference(r) => {
1682 let is_mut = r.mutability.is_some();
1683
1684 let mut new_tys = vec![];
1685
1686 let default_lt = Lifetime {
1687 apostrophe: proc_macro2::Span::call_site(),
1688 ident: format_ident!("_"),
1689 };
1690
1691 for r in Some(&*r)
1692 .into_iter()
1693 .chain(ty_cast.as_deref().into_iter().filter_map(|r| {
1694 if let Type::Reference(r) = r {
1695 Some(r)
1696 } else {
1697 None
1698 }
1699 }))
1700 {
1701 let lt = r.lifetime.as_ref().unwrap_or(&default_lt);
1702
1703 new_tys.push(match &*r.elem {
1704 Type::Slice(s) => {
1705 let ty = &*s.elem;
1706 Some(if is_mut {
1707 quote!(#crate_path::slice::CSliceMut<#lt, #ty>)
1708 } else {
1709 quote!(#crate_path::slice::CSliceRef<#lt, #ty>)
1710 })
1711 .map(|v| (v, false))
1712 }
1713 Type::Path(p) => if let Some("str") =
1714 p.path.get_ident().map(|i| i.to_string()).as_deref()
1715 {
1716 Some(if is_mut {
1717 quote!(#crate_path::slice::CSliceMut<#lt, u8>)
1718 } else {
1719 quote!(#crate_path::slice::CSliceRef<#lt, u8>)
1720 })
1721 } else {
1722 None
1723 }
1724 .map(|v| (v, true)),
1725 _ => None,
1726 });
1727 }
1728
1729 if let Some((slty, into_str)) = &new_tys[0] {
1730 ret.c_out = quote!(-> #slty);
1731 if let Some(sltyc) = new_tys.get(1) {
1732 let sltyc = sltyc.as_ref().map(|(v, _)| v);
1733 ret.c_cast_out = quote!(-> #sltyc);
1734 }
1735 ret.c_ret.extend(quote!(.into()));
1736 if *into_str {
1737 let old_ret = ret.impl_func_ret;
1738 ret.impl_func_ret = quote! {
1739 unsafe { #old_ret .into_str() }
1740 }
1741 } else {
1742 ret.impl_func_ret.extend(quote!(.into()));
1743 }
1744 }
1745 }
1746 Type::Path(p) => {
1747 let last = p.path.segments.last();
1748 if let Some((PathArguments::AngleBracketed(args), last)) =
1749 last.map(|l| (&l.arguments, l))
1750 {
1751 let ident = &last.ident;
1752
1753 let result_ident = format_ident!("Result");
1754
1755 let result_ident = res_override.unwrap_or(&result_ident);
1756
1757 match ident.to_string().as_str() {
1758 "Option" => {
1759 if let Some(GenericArgument::Type(a)) = args.args.first() {
1760 if !crate::util::is_null_pointer_optimizable(a, &[]) {
1761 let new_path: Path =
1762 parse2(quote!(#crate_path::option::COption))
1763 .expect("Failed to parse COption path");
1764
1765 replace_path_keep_final_args(
1766 Some(&mut **ty),
1767 new_path.clone(),
1768 );
1769 replace_path_keep_final_args(
1770 ty_cast.as_deref_mut(),
1771 new_path,
1772 );
1773
1774 ret.c_out = quote!(-> #ty);
1775 ret.c_cast_out = quote!(-> #ty_cast);
1776 ret.c_ret.extend(quote!(.into()));
1777 ret.impl_func_ret.extend(quote!(.into()));
1778 }
1779 }
1780 }
1781 _ => {
1782 if ident == result_ident {
1783 let mut args = args.args.iter();
1784
1785 let to_match =
1786 (args.next(), args.next(), args.next(), int_result);
1787
1788 std::mem::drop(args);
1789
1790 match to_match {
1791 (Some(GenericArgument::Type(a)), _, None, true) => loop {
1792 ret.c_out = quote!(-> i32);
1793 ret.c_cast_out = quote!(-> i32);
1794
1795 let c_ret = &ret.c_ret;
1796
1797 let mapped_ret = quote! {
1798 let ret = ret.map(|ret| {
1799 #c_ret
1800 });
1801 };
1802
1803 if let Type::Tuple(tup) = a {
1804 if tup.elems.is_empty() {
1805 ret.c_ret = quote! {
1806 #mapped_ret
1807 #crate_path::result::into_int_result(ret)
1808 };
1809 let impl_func_ret = &ret.impl_func_ret;
1810 ret.impl_func_ret = quote!(#crate_path::result::from_int_result_empty(#impl_func_ret));
1811
1812 break;
1813 }
1814 }
1815
1816 ret.c_ret_params.extend(
1817 quote!(ok_out: &mut ::core::mem::MaybeUninit<#a>,),
1818 );
1819 ret.c_ret_precall_def.extend(quote!(let mut ok_out = ::core::mem::MaybeUninit::uninit();));
1820 ret.c_call_ret_args.extend(quote!(&mut ok_out,));
1821
1822 ret.c_ret = quote! {
1823 #mapped_ret
1824 #crate_path::result::into_int_out_result(ret, ok_out)
1825 };
1826 let impl_func_ret = &ret.impl_func_ret;
1827 ret.impl_func_ret = quote!(#unsafety { #crate_path::result::from_int_result(#impl_func_ret, ok_out) });
1828
1829 break;
1830 },
1831 (
1832 Some(GenericArgument::Type(_)),
1833 Some(GenericArgument::Type(_)),
1834 None,
1835 _,
1836 ) => {
1837 let new_path: Path =
1838 parse2(quote!(#crate_path::result::CResult))
1839 .expect("Failed to parse CResult path");
1840
1841 replace_path_keep_final_args(
1842 Some(&mut **ty),
1843 new_path.clone(),
1844 );
1845 replace_path_keep_final_args(
1846 ty_cast.as_deref_mut(),
1847 new_path,
1848 );
1849
1850 ret.c_out = quote!(-> #ty);
1851 ret.c_cast_out = quote!(-> #ty_cast);
1852
1853 let c_ret = &ret.c_ret;
1854
1855 let mapped_ret = quote! {
1856 let ret = ret.map(|ret| {
1857 #c_ret
1858 });
1859 };
1860
1861 ret.c_ret = quote! {
1862 #mapped_ret
1863 ret.into()
1864 };
1865
1866 ret.impl_func_ret.extend(quote!(.into()));
1867 }
1868 _ => {}
1869 };
1870 }
1871 }
1872 }
1873 }
1874 }
1875 _ => {}
1876 }
1877 }
1878
1879 ret
1880 }
1881}
1882
1883fn replace_path_keep_final_args(ty: Option<&mut Type>, new_path: Path) {
1884 if let Some(Type::Path(path)) = ty {
1885 let old_path = std::mem::replace(&mut path.path, new_path);
1886 if let Some(seg) = old_path.segments.into_iter().last() {
1887 if let Some(new_seg) = path.path.segments.iter_mut().last() {
1888 new_seg.arguments = seg.arguments;
1889 }
1890 }
1891 }
1892}