diff --git a/README.md b/README.md index 9b7c5e7..73b8524 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ defmodule MyApp.Mixfile do defp deps() do [ - {:unifex, "~>> 1.1.2"} + {:unifex, "~>> 1.2.0"} ] end end diff --git a/lib/unifex/code_generator/base_types/int64.ex b/lib/unifex/code_generator/base_types/int64.ex index a65c7de..b282b47 100644 --- a/lib/unifex/code_generator/base_types/int64.ex +++ b/lib/unifex/code_generator/base_types/int64.ex @@ -4,7 +4,7 @@ defmodule Unifex.CodeGenerator.BaseTypes.Int64 do Maps `int64` Unifex type to an `int64_t` native type. - Implemented only for NIF as function parameter as well as return type. + Implemented both for NIF and CNode as function parameter as well as return type. """ use Unifex.CodeGenerator.BaseType @@ -27,4 +27,26 @@ defmodule Unifex.CodeGenerator.BaseTypes.Int64 do })> end end + + defmodule CNode do + @moduledoc false + use Unifex.CodeGenerator.BaseType + + @impl true + def generate_arg_parse(argument, name, _ctx) do + ~g""" + ({ + long long tmp_longlong; + int result = ei_decode_longlong(#{argument}->buff, #{argument}->index, &tmp_longlong); + #{name} = (int64_t)tmp_longlong; + result; + }) + """ + end + + @impl true + def generate_arg_serialize(name, _ctx) do + ~g + end + end end diff --git a/lib/unifex/code_generator/base_types/uint64.ex b/lib/unifex/code_generator/base_types/uint64.ex index f724552..27821d0 100644 --- a/lib/unifex/code_generator/base_types/uint64.ex +++ b/lib/unifex/code_generator/base_types/uint64.ex @@ -4,7 +4,7 @@ defmodule Unifex.CodeGenerator.BaseTypes.Uint64 do Maps `uint64` Unifex type to a `uint64_t` native type. - Implemented only for NIF as function parameter as well as return type. + Implemented both for NIF and CNode as function parameter as well as return type. """ use Unifex.CodeGenerator.BaseType @@ -12,4 +12,26 @@ defmodule Unifex.CodeGenerator.BaseTypes.Uint64 do def generate_native_type(_ctx) do ~g end + + defmodule CNode do + @moduledoc false + use Unifex.CodeGenerator.BaseType + + @impl true + def generate_arg_parse(argument, name, _ctx) do + ~g""" + ({ + unsigned long long tmp_ulonglong; + int result = ei_decode_ulonglong(#{argument}->buff, #{argument}->index, &tmp_ulonglong); + #{name} = (uint64_t)tmp_ulonglong; + result; + }) + """ + end + + @impl true + def generate_arg_serialize(name, _ctx) do + ~g + end + end end diff --git a/mix.exs b/mix.exs index 3394932..a2f78a1 100644 --- a/mix.exs +++ b/mix.exs @@ -1,8 +1,7 @@ defmodule Unifex.MixProject do use Mix.Project - @version "1.1.2" - + @version "1.2.0" @github_url "https://github.com/membraneframework/unifex" def project do diff --git a/pages/supported_types.md b/pages/supported_types.md index 9bd35b5..a8a24f9 100644 --- a/pages/supported_types.md +++ b/pages/supported_types.md @@ -12,9 +12,9 @@ state of work on remaining types. | `atom` | `char *` | ✅ | ✅ | ✅ | ✅ | | `bool` | `int` | ✅ | ✅ | ✅ | ✅ | | `unsigned` | `unsigned int` | ✅ | ✅ | ✅ | ✅ | -| `uint64` | `uint64_t` | ✅ | ✅ | ❌ | ❌ | +| `uint64` | `uint64_t` | ✅ | ✅ | ✅ | ✅ | | `int` | `int` | ✅ | ✅ | ✅ | ✅ | -| `int64` | `int64_t` | ✅ | ✅ | ❌ | ❌ | +| `int64` | `int64_t` | ✅ | ✅ | ✅ | ✅ | | `float` | `double` | ✅ | ✅ | ✅ | ✅ | | `payload` | `UnifexPayload` | ✅ | ✅ | ✅ | ✅ | | `pid` | `UnifexPid` | ✅ | ✅ | ✅ | ✅ | diff --git a/test/fixtures/cnode_ref_generated/cnode/example.c b/test/fixtures/cnode_ref_generated/cnode/example.c index 0b40b88..c5325c5 100644 --- a/test/fixtures/cnode_ref_generated/cnode/example.c +++ b/test/fixtures/cnode_ref_generated/cnode/example.c @@ -84,6 +84,28 @@ UNIFEX_TERM test_uint_result_ok(UnifexEnv *env, unsigned int out_uint) { return out_buff; } +UNIFEX_TERM test_uint64_result_ok(UnifexEnv *env, uint64_t out_uint64) { + UNIFEX_TERM out_buff = (ei_x_buff *)malloc(sizeof(ei_x_buff)); + unifex_cnode_prepare_ei_x_buff(env, out_buff, "result"); + + ei_x_encode_tuple_header(out_buff, 2); + ei_x_encode_atom(out_buff, "ok"); + ei_x_encode_ulonglong(out_buff, (long long)out_uint64); + + return out_buff; +} + +UNIFEX_TERM test_int64_result_ok(UnifexEnv *env, int64_t out_int64) { + UNIFEX_TERM out_buff = (ei_x_buff *)malloc(sizeof(ei_x_buff)); + unifex_cnode_prepare_ei_x_buff(env, out_buff, "result"); + + ei_x_encode_tuple_header(out_buff, 2); + ei_x_encode_atom(out_buff, "ok"); + ei_x_encode_longlong(out_buff, (long long)out_int64); + + return out_buff; +} + UNIFEX_TERM test_string_result_ok(UnifexEnv *env, char const *out_string) { UNIFEX_TERM out_buff = (ei_x_buff *)malloc(sizeof(ei_x_buff)); unifex_cnode_prepare_ei_x_buff(env, out_buff, "result"); @@ -537,6 +559,55 @@ UNIFEX_TERM test_uint_caller(UnifexEnv *env, UnifexCNodeInBuff *in_buff) { return result; } +UNIFEX_TERM test_uint64_caller(UnifexEnv *env, UnifexCNodeInBuff *in_buff) { + UNIFEX_MAYBE_UNUSED(in_buff); + UNIFEX_TERM result; + uint64_t in_uint64; + + if (({ + unsigned long long tmp_ulonglong; + int result = + ei_decode_ulonglong(in_buff->buff, in_buff->index, &tmp_ulonglong); + in_uint64 = (uint64_t)tmp_ulonglong; + result; + })) { + result = unifex_raise( + env, + "Unifex CNode: cannot parse argument 'in_uint64' of type ':uint64'"); + goto exit_test_uint64_caller; + } + + result = test_uint64(env, in_uint64); + goto exit_test_uint64_caller; +exit_test_uint64_caller: + + return result; +} + +UNIFEX_TERM test_int64_caller(UnifexEnv *env, UnifexCNodeInBuff *in_buff) { + UNIFEX_MAYBE_UNUSED(in_buff); + UNIFEX_TERM result; + int64_t in_int64; + + if (({ + long long tmp_longlong; + int result = + ei_decode_longlong(in_buff->buff, in_buff->index, &tmp_longlong); + in_int64 = (int64_t)tmp_longlong; + result; + })) { + result = unifex_raise( + env, "Unifex CNode: cannot parse argument 'in_int64' of type ':int64'"); + goto exit_test_int64_caller; + } + + result = test_int64(env, in_int64); + goto exit_test_int64_caller; +exit_test_int64_caller: + + return result; +} + UNIFEX_TERM test_string_caller(UnifexEnv *env, UnifexCNodeInBuff *in_buff) { UNIFEX_MAYBE_UNUSED(in_buff); UNIFEX_TERM result; @@ -1699,6 +1770,10 @@ UNIFEX_TERM unifex_cnode_handle_message(UnifexEnv *env, char *fun_name, return test_float_caller(env, in_buff); } else if (strcmp(fun_name, "test_uint") == 0) { return test_uint_caller(env, in_buff); + } else if (strcmp(fun_name, "test_uint64") == 0) { + return test_uint64_caller(env, in_buff); + } else if (strcmp(fun_name, "test_int64") == 0) { + return test_int64_caller(env, in_buff); } else if (strcmp(fun_name, "test_string") == 0) { return test_string_caller(env, in_buff); } else if (strcmp(fun_name, "test_list") == 0) { diff --git a/test/fixtures/cnode_ref_generated/cnode/example.cpp b/test/fixtures/cnode_ref_generated/cnode/example.cpp index 0b40b88..c5325c5 100644 --- a/test/fixtures/cnode_ref_generated/cnode/example.cpp +++ b/test/fixtures/cnode_ref_generated/cnode/example.cpp @@ -84,6 +84,28 @@ UNIFEX_TERM test_uint_result_ok(UnifexEnv *env, unsigned int out_uint) { return out_buff; } +UNIFEX_TERM test_uint64_result_ok(UnifexEnv *env, uint64_t out_uint64) { + UNIFEX_TERM out_buff = (ei_x_buff *)malloc(sizeof(ei_x_buff)); + unifex_cnode_prepare_ei_x_buff(env, out_buff, "result"); + + ei_x_encode_tuple_header(out_buff, 2); + ei_x_encode_atom(out_buff, "ok"); + ei_x_encode_ulonglong(out_buff, (long long)out_uint64); + + return out_buff; +} + +UNIFEX_TERM test_int64_result_ok(UnifexEnv *env, int64_t out_int64) { + UNIFEX_TERM out_buff = (ei_x_buff *)malloc(sizeof(ei_x_buff)); + unifex_cnode_prepare_ei_x_buff(env, out_buff, "result"); + + ei_x_encode_tuple_header(out_buff, 2); + ei_x_encode_atom(out_buff, "ok"); + ei_x_encode_longlong(out_buff, (long long)out_int64); + + return out_buff; +} + UNIFEX_TERM test_string_result_ok(UnifexEnv *env, char const *out_string) { UNIFEX_TERM out_buff = (ei_x_buff *)malloc(sizeof(ei_x_buff)); unifex_cnode_prepare_ei_x_buff(env, out_buff, "result"); @@ -537,6 +559,55 @@ UNIFEX_TERM test_uint_caller(UnifexEnv *env, UnifexCNodeInBuff *in_buff) { return result; } +UNIFEX_TERM test_uint64_caller(UnifexEnv *env, UnifexCNodeInBuff *in_buff) { + UNIFEX_MAYBE_UNUSED(in_buff); + UNIFEX_TERM result; + uint64_t in_uint64; + + if (({ + unsigned long long tmp_ulonglong; + int result = + ei_decode_ulonglong(in_buff->buff, in_buff->index, &tmp_ulonglong); + in_uint64 = (uint64_t)tmp_ulonglong; + result; + })) { + result = unifex_raise( + env, + "Unifex CNode: cannot parse argument 'in_uint64' of type ':uint64'"); + goto exit_test_uint64_caller; + } + + result = test_uint64(env, in_uint64); + goto exit_test_uint64_caller; +exit_test_uint64_caller: + + return result; +} + +UNIFEX_TERM test_int64_caller(UnifexEnv *env, UnifexCNodeInBuff *in_buff) { + UNIFEX_MAYBE_UNUSED(in_buff); + UNIFEX_TERM result; + int64_t in_int64; + + if (({ + long long tmp_longlong; + int result = + ei_decode_longlong(in_buff->buff, in_buff->index, &tmp_longlong); + in_int64 = (int64_t)tmp_longlong; + result; + })) { + result = unifex_raise( + env, "Unifex CNode: cannot parse argument 'in_int64' of type ':int64'"); + goto exit_test_int64_caller; + } + + result = test_int64(env, in_int64); + goto exit_test_int64_caller; +exit_test_int64_caller: + + return result; +} + UNIFEX_TERM test_string_caller(UnifexEnv *env, UnifexCNodeInBuff *in_buff) { UNIFEX_MAYBE_UNUSED(in_buff); UNIFEX_TERM result; @@ -1699,6 +1770,10 @@ UNIFEX_TERM unifex_cnode_handle_message(UnifexEnv *env, char *fun_name, return test_float_caller(env, in_buff); } else if (strcmp(fun_name, "test_uint") == 0) { return test_uint_caller(env, in_buff); + } else if (strcmp(fun_name, "test_uint64") == 0) { + return test_uint64_caller(env, in_buff); + } else if (strcmp(fun_name, "test_int64") == 0) { + return test_int64_caller(env, in_buff); } else if (strcmp(fun_name, "test_string") == 0) { return test_string_caller(env, in_buff); } else if (strcmp(fun_name, "test_list") == 0) { diff --git a/test/fixtures/cnode_ref_generated/cnode/example.h b/test/fixtures/cnode_ref_generated/cnode/example.h index f105e45..0adfe78 100644 --- a/test/fixtures/cnode_ref_generated/cnode/example.h +++ b/test/fixtures/cnode_ref_generated/cnode/example.h @@ -98,6 +98,8 @@ UNIFEX_TERM test_atom(UnifexEnv *env, char *in_atom); UNIFEX_TERM test_bool(UnifexEnv *env, int in_bool); UNIFEX_TERM test_float(UnifexEnv *env, double in_float); UNIFEX_TERM test_uint(UnifexEnv *env, unsigned int in_uint); +UNIFEX_TERM test_uint64(UnifexEnv *env, uint64_t in_uint64); +UNIFEX_TERM test_int64(UnifexEnv *env, int64_t in_int64); UNIFEX_TERM test_string(UnifexEnv *env, char *in_string); UNIFEX_TERM test_list(UnifexEnv *env, int *in_list, unsigned int in_list_length); @@ -122,6 +124,8 @@ UNIFEX_TERM test_atom_result_ok(UnifexEnv *env, char const *out_atom); UNIFEX_TERM test_bool_result_ok(UnifexEnv *env, int out_bool); UNIFEX_TERM test_float_result_ok(UnifexEnv *env, double out_float); UNIFEX_TERM test_uint_result_ok(UnifexEnv *env, unsigned int out_uint); +UNIFEX_TERM test_uint64_result_ok(UnifexEnv *env, uint64_t out_uint64); +UNIFEX_TERM test_int64_result_ok(UnifexEnv *env, int64_t out_int64); UNIFEX_TERM test_string_result_ok(UnifexEnv *env, char const *out_string); UNIFEX_TERM test_list_result_ok(UnifexEnv *env, int const *out_list, unsigned int out_list_length); @@ -151,6 +155,8 @@ UNIFEX_TERM test_atom_caller(UnifexEnv *env, UnifexCNodeInBuff *in_buff); UNIFEX_TERM test_bool_caller(UnifexEnv *env, UnifexCNodeInBuff *in_buff); UNIFEX_TERM test_float_caller(UnifexEnv *env, UnifexCNodeInBuff *in_buff); UNIFEX_TERM test_uint_caller(UnifexEnv *env, UnifexCNodeInBuff *in_buff); +UNIFEX_TERM test_uint64_caller(UnifexEnv *env, UnifexCNodeInBuff *in_buff); +UNIFEX_TERM test_int64_caller(UnifexEnv *env, UnifexCNodeInBuff *in_buff); UNIFEX_TERM test_string_caller(UnifexEnv *env, UnifexCNodeInBuff *in_buff); UNIFEX_TERM test_list_caller(UnifexEnv *env, UnifexCNodeInBuff *in_buff); UNIFEX_TERM test_list_of_strings_caller(UnifexEnv *env, diff --git a/test_projects/cnode/c_src/example/example.c b/test_projects/cnode/c_src/example/example.c index f52b985..407d9ae 100644 --- a/test_projects/cnode/c_src/example/example.c +++ b/test_projects/cnode/c_src/example/example.c @@ -8,6 +8,15 @@ UNIFEX_TERM init(UnifexEnv *env) { return res; } +UNIFEX_TERM test_uint64(UnifexEnv *env, uint64_t in_uint64) { + return test_uint64_result_ok(env, in_uint64); +} + +UNIFEX_TERM test_int64(UnifexEnv *env, int64_t in_int64) { + return test_int64_result_ok(env, in_int64); +} + + UNIFEX_TERM test_nil(UnifexEnv* env) { return test_nil_result_nil(env); } diff --git a/test_projects/cnode/c_src/example/example.spec.exs b/test_projects/cnode/c_src/example/example.spec.exs index df8401c..8b20f8f 100644 --- a/test_projects/cnode/c_src/example/example.spec.exs +++ b/test_projects/cnode/c_src/example/example.spec.exs @@ -18,6 +18,10 @@ spec test_float(in_float :: float) :: {:ok :: label, out_float :: float} spec test_uint(in_uint :: unsigned) :: {:ok :: label, out_uint :: unsigned} +spec test_uint64(in_uint64 :: uint64) :: {:ok :: label, out_uint64 :: uint64} + +spec test_int64(in_int64 :: int64) :: {:ok :: label, out_int64 :: int64} + spec test_string(in_string :: string) :: {:ok :: label, out_string :: string} spec test_list(in_list :: [int]) :: {:ok :: label, out_list :: [int]} diff --git a/test_projects/cnode/test/example_test.exs b/test_projects/cnode/test/example_test.exs index c92fe11..dc37e09 100644 --- a/test_projects/cnode/test/example_test.exs +++ b/test_projects/cnode/test/example_test.exs @@ -8,6 +8,19 @@ defmodule ExampleTest do [cnode: cnode] end + test "uint64", context do + assert {:ok, 0} = Unifex.CNode.call(context[:cnode], :test_uint64, [0]) + # max uint64 value + assert {:ok, 18446744073709551615} = Unifex.CNode.call(context[:cnode], :test_uint64, [18446744073709551615]) + end + + test "int64", context do + assert {:ok, 0} = Unifex.CNode.call(context[:cnode], :test_int64, [0]) + # max int64 value + assert {:ok, 9223372036854775807} = Unifex.CNode.call(context[:cnode], :test_int64, [9223372036854775807]) + assert {:ok, -9223372036854775807} = Unifex.CNode.call(context[:cnode], :test_int64, [-9223372036854775807]) + end + test "nil", context do assert nil == Unifex.CNode.call(context[:cnode], :test_nil, []) end