Skip to content

Commit

Permalink
Scaffolding: add support for custom types
Browse files Browse the repository at this point in the history
Signed-off-by: Martynas Gurskas <[email protected]>
  • Loading branch information
Lipt0nas committed Mar 19, 2024
1 parent 7defd99 commit b8f552f
Show file tree
Hide file tree
Showing 13 changed files with 246 additions and 7 deletions.
4 changes: 4 additions & 0 deletions bindgen/src/bindings/cpp/gen_cpp/filters/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,10 @@ pub(crate) fn ffi_converter_name(as_ct: &impl AsCodeType) -> Result<String> {
Ok(as_ct.as_codetype().ffi_converter_name())
}

pub(crate) fn custom_converter_name(as_ct: &impl AsCodeType) -> Result<String> {
Ok(format!("CustomTypeConverter{}", as_ct.as_codetype().type_label()))
}

pub(crate) fn canonical_name(as_ct: &impl AsCodeType) -> Result<String> {
Ok(as_ct.as_codetype().canonical_name())
}
Expand Down
4 changes: 4 additions & 0 deletions bindgen/src/bindings/cpp/templates/cpp_scaffolding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ typedef int ForeignCallback(uint64_t handle, uint32_t method, uint8_t *args_data
ObjectMap<{{ typ|canonical_name }}> {{ name }}_map;
{%- when Type::CallbackInterface { module_path, name } %}
{% include "scaffolding/callback.hpp" %}
{%- when Type::Custom { module_path, name, builtin } %}
{% include "scaffolding/custom.hpp" %}
{% else %}
{%- endmatch %}
{%- endfor %}
Expand Down Expand Up @@ -327,6 +329,8 @@ void rustbuffer_free(RustBuffer& buf) {
{% include "scaffolding/obj.cpp" %}
{%- when Type::CallbackInterface { module_path, name } %}
{% include "scaffolding/callback.cpp" %}
{%- when Type::Custom { module_path, name, builtin } %}
{% include "scaffolding/custom.cpp" %}
{%- else %}
{%- endmatch %}
{%- endfor %}
Expand Down
2 changes: 1 addition & 1 deletion bindgen/src/bindings/cpp/templates/custom.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,4 @@ int32_t {{ ffi_converter_name }}::allocation_size(const {{ type_name }} &val) {
{%- else %}
{%- endmatch %}
{%- else %}
{%- endmatch %}
{%- endmatch %}
2 changes: 1 addition & 1 deletion bindgen/src/bindings/cpp/templates/custom.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ struct {{ typ|ffi_converter_name }} {
{%- endmatch %}
{%- else -%}
typedef struct {{ builtin|ffi_converter_name }} {{ typ|ffi_converter_name }};
{%- endmatch %}
{%- endmatch %}
36 changes: 36 additions & 0 deletions bindgen/src/bindings/cpp/templates/scaffolding/custom.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{%- let converter = typ|custom_converter_name -%}
{{ type_name }} {{ converter }}::lift(RustBuffer buff) {
auto stream = RustStream(&buff);
auto builtin_val = {{ builtin|read_fn }}(stream);

return Uniffi{{ converter }}::into_custom(builtin_val);
}

RustBuffer {{ converter }}::lower(const {{ type_name }} &val) {
auto buf = rustbuffer_alloc(allocation_size(val));
auto stream = RustStream(&buf);
auto builtin_val = Uniffi{{ converter }}::from_custom(val);

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

return std::move(buf);
}

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

return Uniffi{{ converter }}::into_custom(builtin_val);
}

void {{ converter }}::write(RustStream &stream, const {{ type_name }} &val) {
auto builtin_val = Uniffi{{ converter }}::from_custom(val);

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

int32_t {{ converter }}::allocation_size(const {{ type_name }} &val) {
auto builtin_val = Uniffi{{ converter }}::from_custom(val);

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

8 changes: 8 additions & 0 deletions bindgen/src/bindings/cpp/templates/scaffolding/custom.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
struct {{ typ|custom_converter_name }} {
static {{ typ|type_name }} lift(RustBuffer);
static RustBuffer lower(const {{ typ|type_name }} &);
static {{ typ|type_name }} read(RustStream &);
static void write(RustStream &, const {{ typ|type_name }} &);
static int32_t allocation_size(const {{ typ|type_name }} &);
};
typedef struct {{ typ|custom_converter_name }} {{ typ|ffi_converter_name }};
4 changes: 2 additions & 2 deletions cpp-tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -75,14 +75,14 @@ scaffolding_test_case(arithmetic)
scaffolding_test_case(callbacks)
scaffolding_test_case(fixture_callbacks)
scaffolding_test_case(chronological)
# scaffolding_test_case(custom_types)
scaffolding_test_case(custom_types)
scaffolding_test_case(geometry)
scaffolding_test_case(rondpoint)
scaffolding_test_case(sprites)
scaffolding_test_case(todolist)
scaffolding_test_case(traits)
scaffolding_test_case(coverall)
# scaffolding_test_case(custom_types_builtin)
scaffolding_test_case(custom_types_builtin)

add_library(uniffi_fixtures SHARED
${SCAFFOLDING_LIB_FILES})
Expand Down
18 changes: 18 additions & 0 deletions cpp-tests/scaffolding_tests/custom_types/lib_custom_types.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#include "lib_custom_types.hpp"

custom_types::CustomTypesDemo custom_types::get_custom_types_demo(std::optional<custom_types::CustomTypesDemo> demo) {
return demo.value_or(custom_types::CustomTypesDemo{
.url = "http://example.com/",
.handle = 123,
.time_interval_ms = 456000,
.time_interval_sec_dbl = 456.0,
.time_interval_sec_flt = 777.0f,
});
}

custom_types::ExampleCustomType custom_types::get_example_custom_type() {
UniffiCustomTypeConverterUrl url_converter;
return "abadidea";
}

#include <custom_types_cpp_scaffolding.cpp>
84 changes: 84 additions & 0 deletions cpp-tests/scaffolding_tests/custom_types/lib_custom_types.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
#include <cstdint>
#include <optional>
#include <string>

namespace {
namespace custom_types {
typedef std::string ExampleCustomType;
struct UniffiCustomTypeConverterExampleCustomType {
static ExampleCustomType into_custom(std::string val) {
return val;
}

static std::string from_custom(ExampleCustomType val) {
return val;
}
};

typedef std::string Url;
struct UniffiCustomTypeConverterUrl {
static Url into_custom(std::string val) {
return val;
}

static std::string from_custom(Url val) {
return val;
}
};

typedef int64_t Handle;
struct UniffiCustomTypeConverterHandle {
static Handle into_custom(int64_t val) {
return val;
}

static int64_t from_custom(Handle val) {
return val;
}
};

typedef int64_t TimeIntervalMs;
struct UniffiCustomTypeConverterTimeIntervalMs {
static TimeIntervalMs into_custom(int64_t val) {
return val;
}

static int64_t from_custom(TimeIntervalMs val) {
return val;
}
};

typedef double TimeIntervalSecDbl;
struct UniffiCustomTypeConverterTimeIntervalSecDbl {
static TimeIntervalSecDbl into_custom(double val) {
return val;
}

static double from_custom(TimeIntervalSecDbl val) {
return val;
}
};

typedef float TimeIntervalSecFlt;
struct UniffiCustomTypeConverterTimeIntervalSecFlt {
static TimeIntervalSecFlt into_custom(float val) {
return val;
}

static float from_custom(TimeIntervalSecFlt val) {
return val;
}
};

struct CustomTypesDemo {
Url url;
Handle handle;
TimeIntervalMs time_interval_ms;
TimeIntervalSecDbl time_interval_sec_dbl;
TimeIntervalSecFlt time_interval_sec_flt;
};

CustomTypesDemo get_custom_types_demo(std::optional<CustomTypesDemo> demo);
ExampleCustomType get_example_custom_type();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#include "lib_custom_types_builtin.hpp"

#include <limits>

custom_types_builtin::CustomTypesBuiltin custom_types_builtin::get_custom_types_builtin() {
return custom_types_builtin::CustomTypesBuiltin{
.string = "Hello, world!",
.custom_string = custom_types_builtin::CustomString{"Custom string"},
.array = std::vector<std::string>{"Hello, world!"},
.bytes = std::vector<uint8_t>{0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
.table = std::unordered_map<std::string, std::string>{{"hello", "world"}},
.boolean = true,
.int8 = std::numeric_limits<int8_t>::max(),
.int16 = std::numeric_limits<int16_t>::max(),
.int32 = std::numeric_limits<int32_t>::max(),
.int64 = std::numeric_limits<int64_t>::max(),
.uint8 = std::numeric_limits<uint8_t>::max(),
.uint16 = std::numeric_limits<uint16_t>::max(),
.uint32 = std::numeric_limits<uint32_t>::max(),
.uint64 = std::numeric_limits<uint64_t>::max(),
.flt = std::numeric_limits<float>::max(),
.dbl = std::numeric_limits<double>::max(),
};
}

custom_types_builtin::CustomTypesBuiltin custom_types_builtin::return_custom_types_builtin(custom_types_builtin::CustomTypesBuiltin type) {
return type;
}

#include <custom_types_builtin_cpp_scaffolding.cpp>
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#include <string>
#include <vector>
#include <unordered_map>
#include <cstdint>

#define DEFINE_CUSTOM_TYPE(custom, underlying) \
typedef underlying custom; \
struct UniffiCustomTypeConverter##custom { \
static custom into_custom(underlying val) { return val; } \
static underlying from_custom(custom val) { return val; } \
};

namespace {
namespace custom_types_builtin {
typedef std::unordered_map<std::string, std::string> StringMap;

DEFINE_CUSTOM_TYPE(MyString, std::string)
DEFINE_CUSTOM_TYPE(CustomString, std::string)
DEFINE_CUSTOM_TYPE(Array, std::vector<std::string>)
DEFINE_CUSTOM_TYPE(Bytes, std::vector<uint8_t>)
DEFINE_CUSTOM_TYPE(Table, StringMap)
DEFINE_CUSTOM_TYPE(Boolean, bool)
DEFINE_CUSTOM_TYPE(Int8, int8_t)
DEFINE_CUSTOM_TYPE(Int16, int16_t)
DEFINE_CUSTOM_TYPE(Int32, int32_t)
DEFINE_CUSTOM_TYPE(Int64, int64_t)
DEFINE_CUSTOM_TYPE(UInt8, uint8_t)
DEFINE_CUSTOM_TYPE(UInt16, uint16_t)
DEFINE_CUSTOM_TYPE(UInt32, uint32_t)
DEFINE_CUSTOM_TYPE(UInt64, uint64_t)
DEFINE_CUSTOM_TYPE(Float, float)
DEFINE_CUSTOM_TYPE(Double, double)

struct 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;
};

CustomTypesBuiltin get_custom_types_builtin();
CustomTypesBuiltin return_custom_types_builtin(CustomTypesBuiltin type);
}
}
2 changes: 1 addition & 1 deletion test_scaffolding_cs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ dotnet test --filter \
& FullyQualifiedName!~Disposable \
& FullyQualifiedName!~TestTraitMethods \
& FullyQualifiedName!~OptionalParameterTests \
& FullyQualifiedName!~TestCustomTypes \
& FullyQualifiedName!~TestCustomTypesBuiltin \
& FullyQualifiedName!~TestGlobalMethodsClassName \
& FullyQualifiedName!~DateTimeMinMax \
& FullyQualifiedName!~ChronologicalWorks \
Expand Down
3 changes: 1 addition & 2 deletions test_scaffolding_go.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ pushd $GENERATOR_DIR

pushd $BINDINGS_DIR
# We exclude tests that are not part of the main Rust fixtures
EXCLUDE_LIST="custom_types_test\
|destroy_test\
EXCLUDE_LIST="destroy_test\
|docstring_test\
|errors_test\
|ext_types_test\
Expand Down

0 comments on commit b8f552f

Please sign in to comment.