fn new_for_method()

in uniffi_macros/src/export/scaffolding.rs [127:188]


    fn new_for_method(
        sig: &FnSignature,
        self_ident: &Ident,
        is_trait: bool,
        udl_mode: bool,
    ) -> Self {
        let ident = &sig.ident;
        let self_type = if is_trait {
            quote! { ::std::sync::Arc<dyn #self_ident> }
        } else {
            quote! { ::std::sync::Arc<#self_ident> }
        };
        let lift_type = ffiops::lift_type(&self_type);
        let try_lift = ffiops::try_lift(&self_type);
        let try_lift_self = if is_trait {
            // For trait interfaces we need to special case this.  Trait interfaces normally lift
            // foreign trait impl pointers.  However, for a method call, we want to lift a Rust
            // pointer.
            quote! {
                {
                    let boxed_foreign_arc = unsafe {
                        ::std::boxed::Box::from_raw(
                            uniffi_self_lowered as *mut ::std::sync::Arc<dyn #self_ident>,
                        )
                    };
                    // Take a clone for our own use.
                    ::std::result::Result::Ok(*boxed_foreign_arc)
                }
            }
        } else {
            quote! { #try_lift(uniffi_self_lowered) }
        };

        let lift_closure = sig.lift_closure(Some(quote! {
            match #try_lift_self {
                ::std::result::Result::Ok(v) => v,
                ::std::result::Result::Err(e) => {
                    return ::std::result::Result::Err(("self", e));
                }
            }
        }));
        let call_params = sig.rust_call_params(true);
        let rust_fn_call = quote! { uniffi_args.0.#ident(#call_params) };
        // UDL mode adds an extra conversion (#1749)
        let convert_result = if udl_mode && sig.looks_like_result {
            quote! { uniffi_result .map_err(::std::convert::Into::into) }
        } else {
            quote! { uniffi_result }
        };

        Self {
            param_names: iter::once(quote! { uniffi_self_lowered })
                .chain(sig.scaffolding_param_names())
                .collect(),
            param_types: iter::once(quote! { #lift_type })
                .chain(sig.scaffolding_param_types())
                .collect(),
            lift_closure,
            rust_fn_call,
            convert_result,
        }
    }