use proc_macro2::TokenStream;
use quote::{format_ident, quote};
use syn::Result;
use crate::util::mod_path;
use uniffi_meta::UNIFFI_CONTRACT_VERSION;
pub fn setup_scaffolding(namespace: String) -> Result<TokenStream> {
let module_path = mod_path()?;
let ffi_contract_version_ident = format_ident!("ffi_{module_path}_uniffi_contract_version");
let namespace_upper = namespace.to_ascii_uppercase();
let namespace_const_ident = format_ident!("UNIFFI_META_CONST_NAMESPACE_{namespace_upper}");
let namespace_static_ident = format_ident!("UNIFFI_META_NAMESPACE_{namespace_upper}");
let ffi_rustbuffer_alloc_ident = format_ident!("ffi_{module_path}_rustbuffer_alloc");
let ffi_rustbuffer_from_bytes_ident = format_ident!("ffi_{module_path}_rustbuffer_from_bytes");
let ffi_rustbuffer_free_ident = format_ident!("ffi_{module_path}_rustbuffer_free");
let ffi_rustbuffer_reserve_ident = format_ident!("ffi_{module_path}_rustbuffer_reserve");
let reexport_hack_ident = format_ident!("{module_path}_uniffi_reexport_hack");
let ffi_rust_future_scaffolding_fns = rust_future_scaffolding_fns(&module_path);
Ok(quote! {
#[doc(hidden)]
pub struct UniFfiTag;
#[allow(clippy::missing_safety_doc, missing_docs)]
#[doc(hidden)]
#[no_mangle]
pub extern "C" fn #ffi_contract_version_ident() -> u32 {
#UNIFFI_CONTRACT_VERSION
}
const #namespace_const_ident: ::uniffi::MetadataBuffer = ::uniffi::MetadataBuffer::from_code(::uniffi::metadata::codes::NAMESPACE)
.concat_str(#module_path)
.concat_str(#namespace);
#[doc(hidden)]
#[no_mangle]
pub static #namespace_static_ident: [u8; #namespace_const_ident.size] = #namespace_const_ident.into_array();
#[allow(clippy::missing_safety_doc, missing_docs)]
#[doc(hidden)]
#[no_mangle]
pub extern "C" fn #ffi_rustbuffer_alloc_ident(size: u64, call_status: &mut uniffi::RustCallStatus) -> uniffi::RustBuffer {
uniffi::ffi::uniffi_rustbuffer_alloc(size, call_status)
}
#[allow(clippy::missing_safety_doc, missing_docs)]
#[doc(hidden)]
#[no_mangle]
pub unsafe extern "C" fn #ffi_rustbuffer_from_bytes_ident(bytes: uniffi::ForeignBytes, call_status: &mut uniffi::RustCallStatus) -> uniffi::RustBuffer {
uniffi::ffi::uniffi_rustbuffer_from_bytes(bytes, call_status)
}
#[allow(clippy::missing_safety_doc, missing_docs)]
#[doc(hidden)]
#[no_mangle]
pub unsafe extern "C" fn #ffi_rustbuffer_free_ident(buf: uniffi::RustBuffer, call_status: &mut uniffi::RustCallStatus) {
uniffi::ffi::uniffi_rustbuffer_free(buf, call_status);
}
#[allow(clippy::missing_safety_doc, missing_docs)]
#[doc(hidden)]
#[no_mangle]
pub unsafe extern "C" fn #ffi_rustbuffer_reserve_ident(buf: uniffi::RustBuffer, additional: u64, call_status: &mut uniffi::RustCallStatus) -> uniffi::RustBuffer {
uniffi::ffi::uniffi_rustbuffer_reserve(buf, additional, call_status)
}
#ffi_rust_future_scaffolding_fns
#[allow(missing_docs)]
#[doc(hidden)]
pub const fn uniffi_reexport_hack() {}
#[doc(hidden)]
#[macro_export]
macro_rules! uniffi_reexport_scaffolding {
() => {
#[doc(hidden)]
#[no_mangle]
pub extern "C" fn #reexport_hack_ident() {
$crate::uniffi_reexport_hack()
}
};
}
#[allow(unused)]
#[doc(hidden)]
pub trait UniffiCustomTypeConverter {
type Builtin;
fn into_custom(val: Self::Builtin) -> uniffi::Result<Self> where Self: Sized;
fn from_custom(obj: Self) -> Self::Builtin;
}
})
}
fn rust_future_scaffolding_fns(module_path: &str) -> TokenStream {
let fn_info = [
(quote! { u8 }, "u8"),
(quote! { i8 }, "i8"),
(quote! { u16 }, "u16"),
(quote! { i16 }, "i16"),
(quote! { u32 }, "u32"),
(quote! { i32 }, "i32"),
(quote! { u64 }, "u64"),
(quote! { i64 }, "i64"),
(quote! { f32 }, "f32"),
(quote! { f64 }, "f64"),
(quote! { *const ::std::ffi::c_void }, "pointer"),
(quote! { ::uniffi::RustBuffer }, "rust_buffer"),
(quote! { () }, "void"),
];
fn_info.iter()
.map(|(return_type, fn_suffix)| {
let ffi_rust_future_poll = format_ident!("ffi_{module_path}_rust_future_poll_{fn_suffix}");
let ffi_rust_future_cancel = format_ident!("ffi_{module_path}_rust_future_cancel_{fn_suffix}");
let ffi_rust_future_complete = format_ident!("ffi_{module_path}_rust_future_complete_{fn_suffix}");
let ffi_rust_future_free = format_ident!("ffi_{module_path}_rust_future_free_{fn_suffix}");
quote! {
#[allow(clippy::missing_safety_doc, missing_docs)]
#[doc(hidden)]
#[no_mangle]
pub unsafe extern "C" fn #ffi_rust_future_poll(handle: ::uniffi::Handle, callback: ::uniffi::RustFutureContinuationCallback, data: u64) {
::uniffi::ffi::rust_future_poll::<#return_type, crate::UniFfiTag>(handle, callback, data);
}
#[allow(clippy::missing_safety_doc, missing_docs)]
#[doc(hidden)]
#[no_mangle]
pub unsafe extern "C" fn #ffi_rust_future_cancel(handle: ::uniffi::Handle) {
::uniffi::ffi::rust_future_cancel::<#return_type, crate::UniFfiTag>(handle)
}
#[allow(clippy::missing_safety_doc, missing_docs)]
#[doc(hidden)]
#[no_mangle]
pub unsafe extern "C" fn #ffi_rust_future_complete(
handle: ::uniffi::Handle,
out_status: &mut ::uniffi::RustCallStatus
) -> #return_type {
::uniffi::ffi::rust_future_complete::<#return_type, crate::UniFfiTag>(handle, out_status)
}
#[allow(clippy::missing_safety_doc, missing_docs)]
#[doc(hidden)]
#[no_mangle]
pub unsafe extern "C" fn #ffi_rust_future_free(handle: ::uniffi::Handle) {
::uniffi::ffi::rust_future_free::<#return_type, crate::UniFfiTag>(handle)
}
}
})
.collect()
}