in uniffi_macros/src/export/callback_interface.rs [188:252]
fn gen_method_impl(sig: &FnSignature, vtable_cell: &Ident) -> syn::Result<TokenStream> {
let FnSignature {
ident,
is_async,
return_ty,
kind,
receiver,
name,
span,
..
} = sig;
if !matches!(kind, FnKind::TraitMethod { .. }) {
return Err(syn::Error::new(
*span,
format!(
"Internal UniFFI error: Unexpected function kind for callback interface {name}: {kind:?}",
),
));
}
let self_param = match receiver {
Some(ReceiverArg::Ref) => quote! { &self },
Some(ReceiverArg::Arc) => quote! { self: Arc<Self> },
None => {
return Err(syn::Error::new(
*span,
"callback interface methods must take &self as their first argument",
));
}
};
let params = sig.params();
let lower_exprs = sig.args.iter().map(|a| {
let lower = ffiops::lower(&a.ty);
let ident = &a.ident;
quote! { #lower(#ident) }
});
let lift_return_type = ffiops::lift_return_type(&sig.return_ty);
let lift_foreign_return = ffiops::lift_foreign_return(&sig.return_ty);
if !is_async {
Ok(quote! {
fn #ident(#self_param, #(#params),*) -> #return_ty {
let vtable = #vtable_cell.get();
let mut uniffi_call_status: ::uniffi::RustCallStatus = ::std::default::Default::default();
let mut uniffi_return_value: #lift_return_type = ::uniffi::FfiDefault::ffi_default();
(vtable.#ident)(self.handle, #(#lower_exprs,)* &mut uniffi_return_value, &mut uniffi_call_status);
#lift_foreign_return(uniffi_return_value, uniffi_call_status)
}
})
} else {
Ok(quote! {
async fn #ident(#self_param, #(#params),*) -> #return_ty {
let vtable = #vtable_cell.get();
::uniffi::foreign_async_call::<_, #return_ty, crate::UniFfiTag>(move |uniffi_future_callback, uniffi_future_callback_data| {
let mut uniffi_foreign_future: ::uniffi::ForeignFuture = ::uniffi::FfiDefault::ffi_default();
(vtable.#ident)(self.handle, #(#lower_exprs,)* uniffi_future_callback, uniffi_future_callback_data, &mut uniffi_foreign_future);
uniffi_foreign_future
}).await
}
})
}
}