Skip to content

Commit

Permalink
Finish custom type implementation
Browse files Browse the repository at this point in the history
Signed-off-by: Martynas Gurskas <[email protected]>
  • Loading branch information
Lipt0nas committed Dec 13, 2023
1 parent e09fe68 commit 5a2ea0d
Show file tree
Hide file tree
Showing 17 changed files with 328 additions and 16 deletions.
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.

21 changes: 18 additions & 3 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 @@ -199,6 +213,7 @@ impl<'a> CppWrapperHeader<'a> {
}
}

#[allow(dead_code)]
#[derive(Template)]
#[template(syntax = "cpp", escape = "none", path = "wrapper.cpp")]
struct CppWrapper<'a> {
Expand All @@ -214,7 +229,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

0 comments on commit 5a2ea0d

Please sign in to comment.