Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Finish custom type implementation #8

Merged
merged 2 commits into from
Dec 13, 2023
Merged
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
11 changes: 11 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 18 additions & 9 deletions bindgen/src/bindings/cpp/gen_cpp/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,15 @@ use serde::{Deserialize, Serialize};
use topological_sort::TopologicalSort;
use uniffi_bindgen::{
interface::{AsType, Type, UniffiTrait},
BindingsConfig, ComponentInterface,
BindingsConfig, ComponentInterface, backend::TemplateExpression,
};

#[derive(Clone, Deserialize, Serialize, Debug, Default)]
struct CustomTypesConfig {
imports: Option<Vec<String>>,
type_name: Option<String>,
into_custom: TemplateExpression,
from_custom: TemplateExpression,
}

#[derive(Clone, Deserialize, Serialize, Debug, Default)]
Expand Down Expand Up @@ -59,6 +62,7 @@ struct InternalTypeRenderer<'a> {
#[template(syntax = "cpp", escape = "none", path = "types.cpp")]
struct TypeRenderer<'a> {
ci: &'a ComponentInterface,
config: &'a Config,
}

#[derive(Template)]
Expand All @@ -83,10 +87,20 @@ struct CppWrapperHeader<'a> {

impl<'a> CppWrapperHeader<'a> {
fn new(ci: &'a ComponentInterface, config: &'a Config) -> Self {
let includes = config.custom_types.values().fold(
BTreeSet::new(),
|mut acc: BTreeSet<String>, custom_type| {
if let Some(imports) = &custom_type.imports {
acc.extend(imports.iter().cloned());
}
acc
},
);

Self {
ci,
config,
includes: RefCell::new(BTreeSet::new()),
includes: includes.into(),
}
}

Expand Down Expand Up @@ -188,17 +202,12 @@ impl<'a> CppWrapperHeader<'a> {
sorted.into_iter().chain(rest)
}

pub(crate) fn add_include(&self, include: &str) -> &str {
self.includes.borrow_mut().insert(include.to_string());

""
}

pub(crate) fn includes(&self) -> Vec<String> {
self.includes.borrow().iter().cloned().collect()
}
}

#[allow(dead_code)]
#[derive(Template)]
#[template(syntax = "cpp", escape = "none", path = "wrapper.cpp")]
struct CppWrapper<'a> {
Expand All @@ -214,7 +223,7 @@ impl<'a> CppWrapper<'a> {
ci,
config,
internal_type_helper_code: InternalTypeRenderer { ci }.render().unwrap(),
type_helper_code: TypeRenderer { ci }.render().unwrap(),
type_helper_code: TypeRenderer { ci, config }.render().unwrap(),
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion bindgen/src/bindings/cpp/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ impl BindingGenerator for CppBindingGenerator {
Ok(())
}

fn check_library_path(&self, library_path: &Utf8Path, cdylib_name: Option<&str>) -> Result<()> {
fn check_library_path(&self, _library_path: &Utf8Path, cdylib_name: Option<&str>) -> Result<()> {
if cdylib_name.is_none() {
bail!("A path to a library file is required to generate bindings");
}
Expand Down
38 changes: 38 additions & 0 deletions bindgen/src/bindings/cpp/templates/custom.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{%- match config.custom_types.get(name.as_str()) %}
{%- when Some with (type_config) %}
{%- match type_config.type_name %}
{%- when Some with (type_name) %}
{%- let ffi_type_name = builtin|ffi_type|ffi_type_name %}
{{ type_name }} uniffi::{{ ffi_converter_name }}::lift(RustBuffer buff) {
auto builtin_val = {{ builtin|lift_fn }}(buff);

return {{ type_config.into_custom.render("builtin_val") }};
}

RustBuffer uniffi::{{ ffi_converter_name }}::lower(const {{ type_name }} &val) {
auto builtin_val = {{ type_config.from_custom.render("val") }};

return {{ builtin|lower_fn }}(builtin_val);
}

{{ type_name }} uniffi::{{ ffi_converter_name }}::read(uniffi::RustStream &stream) {
auto builtin_val = {{ builtin|read_fn }}(stream);

return {{ type_config.into_custom.render("builtin_val") }};
}

void uniffi::{{ ffi_converter_name }}::write(uniffi::RustStream &stream, const {{ type_name }} &val) {
auto builtin_val = {{ type_config.from_custom.render("val") }};

{{ builtin|write_fn }}(stream, builtin_val);
}

int32_t uniffi::{{ ffi_converter_name }}::allocation_size(const {{ type_name }} &val) {
auto builtin_val = {{ type_config.from_custom.render("val") }};

return {{ builtin|allocation_size_fn }}(builtin_val);
}
{%- else %}
{%- endmatch %}
{%- else %}
{%- endmatch %}
20 changes: 12 additions & 8 deletions bindgen/src/bindings/cpp/templates/custom.hpp
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
{%- match config.custom_types.get(name.as_str()) %}
{%- when Some with (type_config) %}
{%- match type_config.imports %}
{%- when Some with (includes) %}
{%- for include in includes %}
{{ self.add_include(include) }}
{%- endfor %}
{%- match type_config.type_name %}
{%- when Some with (type_name) %}
struct {{ typ|ffi_converter_name }} {
static {{ name }} lift(RustBuffer);
static RustBuffer lower(const {{ name }} &);
static {{ name }} read(uniffi::RustStream &);
static void write(RustStream &, const {{ name }} &);
static int32_t allocation_size(const {{ name }} &);
};
{%- else %}
{%- endmatch %}
{%- when None %}
typedef {{ builtin|type_name }} {{ name }};
{%- endmatch %}
{%- else -%}
typedef struct {{ builtin|ffi_converter_name }} {{ typ|ffi_converter_name }};
{%- endmatch %}
2 changes: 2 additions & 0 deletions bindgen/src/bindings/cpp/templates/types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
{% include "duration_helper.cpp" %}
{%- when Type::External { module_path, name, namespace, kind, tagged } %}
{% include "ext_typ_tmpl.cpp" %}
{%- when Type::Custom { module_path, name, builtin } %}
{%- include "custom.cpp" %}
{%- else %}
{%- endmatch %}
{%- endfor %}
16 changes: 13 additions & 3 deletions bindgen/src/bindings/cpp/templates/wrapper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <{{ include }}>
{%- endfor %}


{%~ let namespace = ci.namespace() %}
#include "{{ namespace }}_scaffolding.hpp"

Expand All @@ -42,6 +43,17 @@ struct {{ name }};
struct {{ name }};
{%- when Type::CallbackInterface { module_path, name } %}
struct {{ name }};
{%- when Type::Custom { module_path, name, builtin } %}
{%- match config.custom_types.get(name.as_str()) %}
{%- when None %}
typedef {{ builtin|type_name }} {{ name }};
{%- when Some with (type_config) %}
{%- match type_config.type_name %}
{%- when Some with (type_name) %}
typedef {{ type_name }} {{ name }};
{%- else %}
{%- endmatch %}
{%- endmatch %}
{%- else %}
{%- endmatch %}
{%- endfor %}
Expand All @@ -56,8 +68,6 @@ struct {{ name }};
{%- else %}
{% include "enum.hpp" %}
{%- endif %}
{%- when Type::Custom { module_path, name, builtin } %}
{%- include "custom.hpp" %}
{%- when Type::Record { module_path, name } %}
{% include "rec.hpp" %}
{%- when Type::CallbackInterface { module_path, name } %}
Expand Down Expand Up @@ -213,7 +223,7 @@ template <typename T> struct HandleMap {
{%- when Type::CallbackInterface { module_path, name } %}
{% include "callback_conv.hpp" %}
{%- when Type::Custom { module_path, name, builtin } %}
typedef struct {{ builtin|ffi_converter_name }} {{ typ|ffi_converter_name }};
{% include "custom.hpp" %}
{%- else %}
{%- endmatch %}
{%- endfor %}
Expand Down
1 change: 1 addition & 0 deletions cpp-tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ test_case(traits)
test_case(coverall)
test_case(uniffi_docstring)
test_case(trait_methods)
test_case(custom_types_builtin)

add_custom_target(libs ALL
BYPRODUCTS ${BINDING_FILES}
Expand Down
35 changes: 35 additions & 0 deletions cpp-tests/tests/custom_types_builtin/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#include <test_common.hpp>

#include <custom_types_builtin.hpp>

void assert_custom_type(custom_types_builtin::CustomTypesBuiltin& type) {
auto table = std::unordered_map<std::string, std::string>{{"hello", "world"}};
auto bytes = std::vector<uint8_t>{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};

ASSERT_EQ(type.string, "Hello, world!");
ASSERT_EQ(type.custom_string.string, "Custom string");
ASSERT_EQ(type.array, std::vector<std::string>{"Hello, world!"});
ASSERT_EQ(type.bytes, bytes);
ASSERT_EQ(type.table, table);
ASSERT_EQ(type.boolean, true);
ASSERT_EQ(type.int8, std::numeric_limits<int8_t>::max());
ASSERT_EQ(type.int16, std::numeric_limits<int16_t>::max());
ASSERT_EQ(type.int32, std::numeric_limits<int32_t>::max());
ASSERT_EQ(type.int64, std::numeric_limits<int64_t>::max());
ASSERT_EQ(type.uint8, std::numeric_limits<uint8_t>::max());
ASSERT_EQ(type.uint16, std::numeric_limits<uint16_t>::max());
ASSERT_EQ(type.uint32, std::numeric_limits<uint32_t>::max());
ASSERT_EQ(type.uint64, std::numeric_limits<uint64_t>::max());
ASSERT_EQ(type.flt, std::numeric_limits<float>::max());
ASSERT_EQ(type.dbl, std::numeric_limits<double>::max());
}

int main() {
auto custom_type = custom_types_builtin::get_custom_types_builtin();
assert_custom_type(custom_type);

custom_type = custom_types_builtin::return_custom_types_builtin(custom_type);
assert_custom_type(custom_type);

return 0;
}
13 changes: 13 additions & 0 deletions cpp-tests/tests/include/custom_string.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#pragma once

#include <string>

struct CustomString {
std::string string;

CustomString(const std::string &string): string(string) { }

std::string to_string() const {
return this->string;
}
};
2 changes: 1 addition & 1 deletion fixtures/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@ uniffi-fixture-coverall = { git = "https://github.com/NordSecurity/uniffi-rs.git
uniffi-fixture-docstring = { git = "https://github.com/NordSecurity/uniffi-rs.git", branch = "nordsec.0.25.0" }
uniffi-fixture-time = { git = "https://github.com/NordSecurity/uniffi-rs.git", branch = "nordsec.0.25.0" }
uniffi-fixture-trait-methods = { git = "https://github.com/NordSecurity/uniffi-rs.git", branch = "nordsec.0.25.0" }

uniffi-custom-types-builtin = { path = "custom-types-builtin" }
17 changes: 17 additions & 0 deletions fixtures/custom-types-builtin/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[package]
name = "uniffi-custom-types-builtin"
version = "0.1.0"
edition = "2021"

[lib]
crate-type = ["lib", "cdylib"]
name = "uniffi_cpp_custom_types_builtin"

[dependencies]
uniffi = { git = "https://github.com/NordSecurity/uniffi-rs.git", branch = "nordsec.0.25.0" }
once_cell = "1.12"
paste = "1.0"
thiserror = "1.0"

[build-dependencies]
uniffi = { git = "https://github.com/NordSecurity/uniffi-rs.git", branch = "nordsec.0.25.0", features = ["build"] }
3 changes: 3 additions & 0 deletions fixtures/custom-types-builtin/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fn main() {
uniffi::generate_scaffolding("src/custom_types_builtin.udl").unwrap();
}
71 changes: 71 additions & 0 deletions fixtures/custom-types-builtin/src/custom_types_builtin.udl
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
[Custom]
typedef string MyString;

[Custom]
typedef string CustomString;

[Custom]
typedef bytes Bytes;

[Custom]
typedef sequence<string> Array;

[Custom]
typedef record<string, string> Table;

[Custom]
typedef boolean Boolean;

[Custom]
typedef i8 Int8;

[Custom]
typedef i16 Int16;

[Custom]
typedef i32 Int32;

[Custom]
typedef i64 Int64;

[Custom]
typedef u8 UInt8;

[Custom]
typedef u16 UInt16;

[Custom]
typedef u32 UInt32;

[Custom]
typedef u64 UInt64;

[Custom]
typedef float Float;

[Custom]
typedef double Double;

dictionary CustomTypesBuiltin {
MyString string;
CustomString custom_string;
Array array;
Bytes bytes;
Table table;
Boolean boolean;
Int8 int8;
Int16 int16;
Int32 int32;
Int64 int64;
UInt8 uint8;
UInt16 uint16;
UInt32 uint32;
UInt64 uint64;
Float flt;
Double dbl;
};

namespace custom_types_builtin {
CustomTypesBuiltin get_custom_types_builtin();
CustomTypesBuiltin return_custom_types_builtin(CustomTypesBuiltin custom_types);
};
Loading