Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ exclude = [
]

[workspace.dependencies]
uniffi = { version = "0.28.0" }
uniffi_bindgen = { version = "0.28.0" }
uniffi_build = { version = "0.28.0" }
uniffi_testing = { version = "0.28.0" }
uniffi = { version = "0.29.0" }
uniffi_bindgen = { version = "0.29.0" }
uniffi_build = { version = "0.29.0" }
uniffi_testing = { version = "0.29.0" }
94 changes: 50 additions & 44 deletions src/gen/callback_interface.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use genco::prelude::*;
use crate::gen::CodeType;
use uniffi_bindgen::interface::Type;
use uniffi_bindgen::interface::{AsType, Method, CallbackInterface};
use uniffi_bindgen::interface::{AsType, Method};

use crate::gen::oracle::{AsCodeType, DartCodeOracle};
use crate::gen::render::AsRenderable;
Expand Down Expand Up @@ -40,10 +40,10 @@ impl Renderable for CallbackInterfaceCodeType {
let callback = type_helper.get_ci().get_callback_interface_definition(&self.name).unwrap();

// Generate all necessary components for the callback interface
let interface = generate_callback_interface(&self, type_helper);
let vtable_interface = generate_callback_vtable_interface(&callback, type_helper);
let functions = generate_callback_functions(&callback, type_helper);
let vtable_init = generate_callback_interface_vtable_init_funtion(&callback, type_helper);
let interface = generate_callback_interface(callback.name(), &callback.as_codetype().ffi_converter_name(), &callback.methods(), type_helper);
let vtable_interface = generate_callback_vtable_interface(callback.name(), &callback.methods());
let functions = generate_callback_functions(callback.name(), &callback.methods(), type_helper);
let vtable_init = generate_callback_interface_vtable_init_function(callback.name(), &callback.methods(), "callbacks");

quote! {
$interface
Expand All @@ -54,36 +54,44 @@ impl Renderable for CallbackInterfaceCodeType {
}
}

fn generate_callback_interface(
callback_codetype: &CallbackInterfaceCodeType,
pub fn generate_callback_interface(
callback_name: &str,
ffi_converter_name: &str,
methods: &[&Method],
type_helper: &dyn TypeHelperRenderer,
) -> dart::Tokens {
let callback = type_helper.get_ci().get_callback_interface_definition(&callback_codetype.name).unwrap(); // The context here gurantees it always exists, could refactor.
let cls_name = &DartCodeOracle::class_name(callback.name());
let ffi_conv_name = &DartCodeOracle::class_name(&callback.as_codetype().ffi_converter_name());
let methods = callback.methods();
let _vtable_methods = callback.vtable_methods();

let cls_name = &DartCodeOracle::class_name(callback_name);
let ffi_conv_name = &DartCodeOracle::class_name(ffi_converter_name);
let init_fn_name = &format!("init{}VTable", callback_name);

let tokens = quote! {
// This is the abstract class to be implemented
abstract class $cls_name {
$(for m in &methods {
$(for m in methods {
$(generate_callback_methods_definitions(m, type_helper))
})
}

// This is the type helper to convert from FFI to Dart
class $ffi_conv_name {
static final _handleMap = UniffiHandleMap<$cls_name>();
static bool _vtableInitialized = false;

static $cls_name lift(int handle) {
return _handleMap.get(handle);
}

static int lower($cls_name value) {
_ensureVTableInitialized();
return _handleMap.insert(value);
}

static void _ensureVTableInitialized() {
if (!_vtableInitialized) {
$init_fn_name();
_vtableInitialized = true;
}
}

static LiftRetVal<$cls_name> read(Uint8List buf) {
final handle = buf.buffer.asByteData(buf.offsetInBytes).getInt64(0);
Expand All @@ -102,7 +110,7 @@ fn generate_callback_interface(
}

// We must define callback signatures
$(generate_callback_methods_signatures(cls_name, &methods, type_helper))
$(generate_callback_methods_signatures(cls_name, methods, type_helper))
};

tokens
Expand All @@ -129,7 +137,7 @@ fn generate_callback_methods_definitions(method: &Method, type_helper: &dyn Type
)
}

fn generate_callback_methods_signatures(callback_name: &str, methods: &Vec<&Method>, _type_helper: &dyn TypeHelperRenderer) -> dart::Tokens {
fn generate_callback_methods_signatures(callback_name: &str, methods: &[&Method], type_helper: &dyn TypeHelperRenderer) -> dart::Tokens {
let mut tokens = dart::Tokens::new();
for (method_index, method) in methods.iter().enumerate() {
//let method_name = DartCodeOracle::fn_name(method.name());
Expand All @@ -147,17 +155,17 @@ fn generate_callback_methods_signatures(callback_name: &str, methods: &Vec<&Meth
);

let method_return_type = if let Some(ret) = method.return_type() {
DartCodeOracle::native_type_label(Some(ret))
DartCodeOracle::native_type_label(Some(ret), type_helper.get_ci())
} else {
quote!(Void)
};

tokens.append(quote! {
typedef $ffi_method_type = Void Function(
Uint64, $(for arg in &method.arguments() => $(DartCodeOracle::native_type_label(Some(&arg.as_type()))),)
Uint64, $(for arg in &method.arguments() => $(DartCodeOracle::native_type_label(Some(&arg.as_type()), type_helper.get_ci())),)
Pointer<$(&method_return_type)>, Pointer<RustCallStatus>);
typedef $dart_method_type = void Function(
int, $(for arg in &method.arguments() => $(DartCodeOracle::native_dart_type_label(Some(&arg.as_type()))),)
int, $(for arg in &method.arguments() => $(DartCodeOracle::native_dart_type_label(Some(&arg.as_type()), type_helper.get_ci())),)
Pointer<$(&method_return_type)>, Pointer<RustCallStatus>);
});
}
Expand All @@ -170,34 +178,32 @@ fn generate_callback_methods_signatures(callback_name: &str, methods: &Vec<&Meth
tokens
}

fn generate_callback_vtable_interface(callback: &CallbackInterface, _type_helper: &dyn TypeHelperRenderer) -> dart::Tokens {
let vtable_name = format!("UniffiVTableCallbackInterface{}", callback.name());
let methods = callback.methods();
pub fn generate_callback_vtable_interface(callback_name: &str, methods: &[&Method]) -> dart::Tokens {
let vtable_name = format!("UniffiVTableCallbackInterface{}", callback_name);
let methods_vec: Vec<_> = methods.into_iter().enumerate().collect();

quote! {
class $vtable_name extends Struct {
final class $vtable_name extends Struct {
$(for (index, m) in &methods_vec =>
external Pointer<NativeFunction<UniffiCallbackInterface$(callback.name())Method$(format!("{}",index))>> $(DartCodeOracle::fn_name(m.name()));
external Pointer<NativeFunction<UniffiCallbackInterface$(callback_name)Method$(format!("{}",index))>> $(DartCodeOracle::fn_name(m.name()));
)
external Pointer<NativeFunction<UniffiCallbackInterface$(callback.name())Free>> uniffiFree;
external Pointer<NativeFunction<UniffiCallbackInterface$(callback_name)Free>> uniffiFree;
}
}
}

fn generate_callback_functions(callback: &CallbackInterface, _type_helper: &dyn TypeHelperRenderer) -> dart::Tokens {
let cls_name = &DartCodeOracle::class_name(callback.name());
let methods = callback.methods();
pub fn generate_callback_functions(callback_name: &str, methods: &[&Method], type_helper: &dyn TypeHelperRenderer) -> dart::Tokens {
let cls_name = &DartCodeOracle::class_name(callback_name);

let functions: Vec<dart::Tokens> = methods.iter().enumerate().map(|(index, m)| {
let method_name = &format!("{}", &DartCodeOracle::fn_name(m.name()));
let ffi_method_type = &format!("UniffiCallbackInterface{}Method{}", callback.name(), index);
let _dart_method_type = &format!("UniffiCallbackInterface{}Method{}Dart", callback.name(), index);
let ffi_method_type = &format!("UniffiCallbackInterface{}Method{}", callback_name, index);
let _dart_method_type = &format!("UniffiCallbackInterface{}Method{}Dart", callback_name, index);

// Get parameter types using the oracle
let param_types: Vec<dart::Tokens> = m.arguments().iter().map(|arg| {
let arg_name = DartCodeOracle::var_name(arg.name());
DartCodeOracle::callback_param_type(&arg.as_type(), &arg_name)
DartCodeOracle::callback_param_type(&arg.as_type(), &arg_name, type_helper.get_ci())
}).collect();

// Get argument lifts using the oracle
Expand All @@ -223,7 +229,7 @@ fn generate_callback_functions(callback: &CallbackInterface, _type_helper: &dyn
let out_return_type = DartCodeOracle::callback_out_return_type(m.return_type());

// Generate the function body
let callback_method_name = &format!("{}{}", &DartCodeOracle::fn_name(callback.name()), &DartCodeOracle::class_name(m.name()));
let callback_method_name = &format!("{}{}", &DartCodeOracle::fn_name(callback_name), &DartCodeOracle::class_name(m.name()));

quote! {
void $callback_method_name(int uniffiHandle, $(for param in &param_types => $param,) $out_return_type outReturn, Pointer<RustCallStatus> callStatus) {
Expand All @@ -244,9 +250,9 @@ fn generate_callback_functions(callback: &CallbackInterface, _type_helper: &dyn
}).collect();

// Free callback
let free_callback_fn = &format!("{}FreeCallback", DartCodeOracle::fn_name(callback.name()));
let free_callback_pointer = &format!("{}FreePointer", DartCodeOracle::fn_name(callback.name()));
let free_callback_type = &format!("UniffiCallbackInterface{}Free", callback.name());
let free_callback_fn = &format!("{}FreeCallback", DartCodeOracle::fn_name(callback_name));
let free_callback_pointer = &format!("{}FreePointer", DartCodeOracle::fn_name(callback_name));
let free_callback_type = &format!("UniffiCallbackInterface{}Free", callback_name);

quote! {
$(functions)
Expand All @@ -264,27 +270,27 @@ fn generate_callback_functions(callback: &CallbackInterface, _type_helper: &dyn
}
}

fn generate_callback_interface_vtable_init_funtion(callback: &CallbackInterface, _type_helper: &dyn TypeHelperRenderer) -> dart::Tokens {
let vtable_name = &format!("UniffiVTableCallbackInterface{}", callback.name());
let vtable_static_instance_name = format!("{}{}", DartCodeOracle::fn_name(callback.name()), "VTable");
let init_fn_name = &format!("init{}VTable", callback.name());
pub fn generate_callback_interface_vtable_init_function(callback_name: &str, methods: &[&Method], namespace: &str) -> dart::Tokens {
let vtable_name = &format!("UniffiVTableCallbackInterface{}", callback_name);
let vtable_static_instance_name = format!("{}{}", DartCodeOracle::fn_name(callback_name), "VTable");
let init_fn_name = &format!("init{}VTable", callback_name);

quote! {
late final Pointer<$vtable_name> $(&vtable_static_instance_name);

void $init_fn_name() {
$(&vtable_static_instance_name) = calloc<$vtable_name>();
$(for m in &callback.methods() {
$(&vtable_static_instance_name).ref.$(DartCodeOracle::fn_name(m.name())) = $(DartCodeOracle::fn_name(callback.name()))$(DartCodeOracle::class_name(m.name()))Pointer;
$(for m in methods {
$(&vtable_static_instance_name).ref.$(DartCodeOracle::fn_name(m.name())) = $(DartCodeOracle::fn_name(callback_name))$(DartCodeOracle::class_name(m.name()))Pointer;
})
$(&vtable_static_instance_name).ref.uniffiFree = $(format!("{}FreePointer", DartCodeOracle::fn_name(callback.name())));
$(&vtable_static_instance_name).ref.uniffiFree = $(format!("{}FreePointer", DartCodeOracle::fn_name(callback_name)));

rustCall((status) {
_UniffiLib.instance.uniffi_callbacks_fn_init_callback_vtable_$(callback.name().to_lowercase())(
_UniffiLib.instance.uniffi_$(namespace)_fn_init_callback_vtable_$(callback_name.to_lowercase())(
$(vtable_static_instance_name),
);
checkCallStatus(NullRustCallStatusErrorHandler(), status);
});
}
}
}
}
5 changes: 3 additions & 2 deletions src/gen/compounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ macro_rules! impl_renderable_for_compound {
if (ByteData.view(buf.buffer, buf.offsetInBytes).getInt8(0) == 0){
return LiftRetVal(null, 1);
}
return $inner_cl_converter_name.read(Uint8List.view(buf.buffer, buf.offsetInBytes + 1)).copyWithOffset(1);
final result = $inner_cl_converter_name.read(Uint8List.view(buf.buffer, buf.offsetInBytes + 1));
return LiftRetVal<$type_label>(result.value, result.bytesRead + 1);
}


Expand Down Expand Up @@ -161,7 +162,7 @@ macro_rules! impl_renderable_for_compound {
return offset - buf.offsetInBytes;
}
static int allocationSize($type_label value) {
return value.map((l) => $inner_cl_converter_name.allocationSize(l)).reduce((a, b) => a + b) + 4;
return value.map((l) => $inner_cl_converter_name.allocationSize(l)).fold(0, (a, b) => a + b) + 4;
}

static RustBuffer lower( $type_label value) {
Expand Down
51 changes: 51 additions & 0 deletions src/gen/custom.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
use super::oracle::{AsCodeType, DartCodeOracle};
use super::CodeType;
use super::render::{Renderable, TypeHelperRenderer};
use genco::prelude::*;
use uniffi_bindgen::backend::Type;
use uniffi_bindgen::interface::AsType;

#[derive(Debug)]
pub struct CustomCodeType {
name: String,
module_path: String,
builtin: Box<Type>,
}

impl CustomCodeType {
pub fn new(name: String, module_path: String, builtin: Box<Type>) -> Self {
CustomCodeType { name, module_path, builtin }
}
}

impl CodeType for CustomCodeType {
fn type_label(&self) -> String {
DartCodeOracle::class_name(&self.name)
}
}

impl AsType for CustomCodeType {
fn as_type(&self) -> Type {
Type::Custom {
name: self.name.clone(),
module_path: self.module_path.clone(),
builtin: self.builtin.clone(),
}
}
}

impl Renderable for CustomCodeType {
fn render_type_helper(&self, type_helper: &dyn TypeHelperRenderer) -> dart::Tokens {
type_helper.include_once_check(&self.name, &self.as_type());

let ffi_converter_name = &self.ffi_converter_name();
let type_name = &self.type_label();
let builtin_ffi_converter_name = &(*self.builtin).as_codetype().ffi_converter_name();
let builtin_name = DartCodeOracle::dart_type_label(Some(&*self.builtin));

quote! {
typedef $(type_name) = $(builtin_name);
typedef $(ffi_converter_name) = $(builtin_ffi_converter_name);
}
}
}
Loading