summaryrefslogtreecommitdiffstats
path: root/third_party/rust/uniffi_macros/src/object.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/uniffi_macros/src/object.rs')
-rw-r--r--third_party/rust/uniffi_macros/src/object.rs76
1 files changed, 54 insertions, 22 deletions
diff --git a/third_party/rust/uniffi_macros/src/object.rs b/third_party/rust/uniffi_macros/src/object.rs
index 573a1eaadd..6bcc07a14e 100644
--- a/third_party/rust/uniffi_macros/src/object.rs
+++ b/third_party/rust/uniffi_macros/src/object.rs
@@ -1,17 +1,27 @@
use proc_macro2::{Ident, Span, TokenStream};
use quote::quote;
use syn::DeriveInput;
-use uniffi_meta::free_fn_symbol_name;
-use crate::util::{create_metadata_items, ident_to_string, mod_path, tagged_impl_header};
+use crate::util::{
+ create_metadata_items, extract_docstring, ident_to_string, mod_path, tagged_impl_header,
+};
+use uniffi_meta::ObjectImpl;
pub fn expand_object(input: DeriveInput, udl_mode: bool) -> syn::Result<TokenStream> {
let module_path = mod_path()?;
let ident = &input.ident;
+ let docstring = extract_docstring(&input.attrs)?;
let name = ident_to_string(ident);
- let free_fn_ident = Ident::new(&free_fn_symbol_name(&module_path, &name), Span::call_site());
+ let clone_fn_ident = Ident::new(
+ &uniffi_meta::clone_fn_symbol_name(&module_path, &name),
+ Span::call_site(),
+ );
+ let free_fn_ident = Ident::new(
+ &uniffi_meta::free_fn_symbol_name(&module_path, &name),
+ Span::call_site(),
+ );
let meta_static_var = (!udl_mode).then(|| {
- interface_meta_static_var(ident, false, &module_path)
+ interface_meta_static_var(ident, ObjectImpl::Struct, &module_path, docstring)
.unwrap_or_else(syn::Error::into_compile_error)
});
let interface_impl = interface_impl(ident, udl_mode);
@@ -19,7 +29,19 @@ pub fn expand_object(input: DeriveInput, udl_mode: bool) -> syn::Result<TokenStr
Ok(quote! {
#[doc(hidden)]
#[no_mangle]
- pub extern "C" fn #free_fn_ident(
+ pub unsafe extern "C" fn #clone_fn_ident(
+ ptr: *const ::std::ffi::c_void,
+ call_status: &mut ::uniffi::RustCallStatus
+ ) -> *const ::std::ffi::c_void {
+ uniffi::rust_call(call_status, || {
+ unsafe { ::std::sync::Arc::increment_strong_count(ptr) };
+ Ok(ptr)
+ })
+ }
+
+ #[doc(hidden)]
+ #[no_mangle]
+ pub unsafe extern "C" fn #free_fn_ident(
ptr: *const ::std::ffi::c_void,
call_status: &mut ::uniffi::RustCallStatus
) {
@@ -41,6 +63,7 @@ pub fn expand_object(input: DeriveInput, udl_mode: bool) -> syn::Result<TokenStr
pub(crate) fn interface_impl(ident: &Ident, udl_mode: bool) -> TokenStream {
let name = ident_to_string(ident);
let impl_spec = tagged_impl_header("FfiConverterArc", ident, udl_mode);
+ let lower_return_impl_spec = tagged_impl_header("LowerReturn", ident, udl_mode);
let lift_ref_impl_spec = tagged_impl_header("LiftRef", ident, udl_mode);
let mod_path = match mod_path() {
Ok(p) => p,
@@ -52,7 +75,7 @@ pub(crate) fn interface_impl(ident: &Ident, udl_mode: bool) -> TokenStream {
// if they are not, but unfortunately it fails with an unactionably obscure error message.
// By asserting the requirement explicitly, we help Rust produce a more scrutable error message
// and thus help the user debug why the requirement isn't being met.
- uniffi::deps::static_assertions::assert_impl_all!(#ident: Sync, Send);
+ uniffi::deps::static_assertions::assert_impl_all!(#ident: ::core::marker::Sync, ::core::marker::Send);
#[doc(hidden)]
#[automatically_derived]
@@ -78,17 +101,10 @@ pub(crate) fn interface_impl(ident: &Ident, udl_mode: bool) -> TokenStream {
::std::sync::Arc::into_raw(obj) as Self::FfiType
}
- /// When lifting, we receive a "borrow" of the `Arc` that is owned by
- /// the foreign-language code, and make a clone of it for our own use.
- ///
- /// Safety: the provided value must be a pointer previously obtained by calling
- /// the `lower()` or `write()` method of this impl.
+ /// When lifting, we receive an owned `Arc` that the foreign language code cloned.
fn try_lift(v: Self::FfiType) -> ::uniffi::Result<::std::sync::Arc<Self>> {
let v = v as *const #ident;
- // We musn't drop the `Arc` that is owned by the foreign-language code.
- let foreign_arc = ::std::mem::ManuallyDrop::new(unsafe { ::std::sync::Arc::<Self>::from_raw(v) });
- // Take a clone for our own use.
- Ok(::std::sync::Arc::clone(&*foreign_arc))
+ Ok(unsafe { ::std::sync::Arc::<Self>::from_raw(v) })
}
/// When writing as a field of a complex structure, make a clone and transfer ownership
@@ -117,8 +133,17 @@ pub(crate) fn interface_impl(ident: &Ident, udl_mode: bool) -> TokenStream {
const TYPE_ID_META: ::uniffi::MetadataBuffer = ::uniffi::MetadataBuffer::from_code(::uniffi::metadata::codes::TYPE_INTERFACE)
.concat_str(#mod_path)
- .concat_str(#name)
- .concat_bool(false);
+ .concat_str(#name);
+ }
+
+ unsafe #lower_return_impl_spec {
+ type ReturnType = <Self as ::uniffi::FfiConverterArc<crate::UniFfiTag>>::FfiType;
+
+ fn lower_return(obj: Self) -> ::std::result::Result<Self::ReturnType, ::uniffi::RustBuffer> {
+ Ok(<Self as ::uniffi::FfiConverterArc<crate::UniFfiTag>>::lower(::std::sync::Arc::new(obj)))
+ }
+
+ const TYPE_ID_META: ::uniffi::MetadataBuffer = <Self as ::uniffi::FfiConverterArc<crate::UniFfiTag>>::TYPE_ID_META;
}
unsafe #lift_ref_impl_spec {
@@ -129,18 +154,25 @@ pub(crate) fn interface_impl(ident: &Ident, udl_mode: bool) -> TokenStream {
pub(crate) fn interface_meta_static_var(
ident: &Ident,
- is_trait: bool,
+ imp: ObjectImpl,
module_path: &str,
+ docstring: String,
) -> syn::Result<TokenStream> {
let name = ident_to_string(ident);
+ let code = match imp {
+ ObjectImpl::Struct => quote! { ::uniffi::metadata::codes::INTERFACE },
+ ObjectImpl::Trait => quote! { ::uniffi::metadata::codes::TRAIT_INTERFACE },
+ ObjectImpl::CallbackTrait => quote! { ::uniffi::metadata::codes::CALLBACK_TRAIT_INTERFACE },
+ };
+
Ok(create_metadata_items(
"interface",
&name,
quote! {
- ::uniffi::MetadataBuffer::from_code(::uniffi::metadata::codes::INTERFACE)
- .concat_str(#module_path)
- .concat_str(#name)
- .concat_bool(#is_trait)
+ ::uniffi::MetadataBuffer::from_code(#code)
+ .concat_str(#module_path)
+ .concat_str(#name)
+ .concat_long_str(#docstring)
},
None,
))