summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClaudius "keldu" Holeksa <mail@keldu.de>2023-10-25 17:12:45 +0200
committerClaudius "keldu" Holeksa <mail@keldu.de>2023-10-25 17:12:45 +0200
commit1da06cc4d8b64b8d63782e356acb0cb946789d20 (patch)
treeeb5778c7015d7fac5364247a91e5f4945d459eac
parent5212ea31af9b1f34a1f7400166563b945f94bc5c (diff)
codec: Added basic interface and function class
Preparation work for RPC functionality.
-rw-r--r--c++/codec/rpc.h103
-rw-r--r--tests/codec.cpp108
2 files changed, 211 insertions, 0 deletions
diff --git a/c++/codec/rpc.h b/c++/codec/rpc.h
new file mode 100644
index 0000000..b1422a9
--- /dev/null
+++ b/c++/codec/rpc.h
@@ -0,0 +1,103 @@
+#pragma once
+
+#include <forstio/core/error.h>
+#include "schema.h"
+#include "data.h"
+
+namespace saw {
+template<typename SchemaFunc, typename Encode, typename Func>
+class function;
+
+template<typename Request, typename Response, typename Encode, typename Func>
+class function<schema::Function<Request, Response>, Encode, Func> {
+private:
+ Func func_;
+public:
+ function(Func func):
+ func_{std::move(func)}
+ {}
+
+ error_or<data<Response, Encode>> call(data<Request, Encode> req){
+ return func_(std::move(req));
+ }
+};
+
+template<typename T, typename Encode, typename... Funcs>
+class interface;
+
+template<typename... Requests, typename... Responses, string_literal... Names, typename Encode, typename... Funcs>
+class interface<schema::Interface<schema::Member<schema::Function<Requests, Responses>, Names>...>, Encode, Funcs...> {
+private:
+ std::tuple<function<schema::Function<Requests, Responses>, Encode, Funcs>...> funcs_;
+public:
+ interface(function<schema::Function<Requests, Responses>, Encode, Funcs>... funcs):
+ funcs_{std::move(funcs)...}
+ {}
+
+ /**
+ * Get the function based on the string literal matching the position in the tuple
+ */
+ template<string_literal Lit>
+ function<
+ schema::Function<
+ typename parameter_pack_type<
+ parameter_key_pack_index<
+ Lit, Names...
+ >::value
+ , Requests...>::type
+ ,
+ typename parameter_pack_type<
+ parameter_key_pack_index<
+ Lit, Names...
+ >::value
+ , Responses...>::type
+ >
+ ,
+ Encode
+ ,
+ typename parameter_pack_type<
+ parameter_key_pack_index<
+ Lit, Names...
+ >::value
+ , Funcs...>::type
+ >& get(){
+ return std::get<parameter_key_pack_index<Lit, Names...>::value>(funcs_);
+ }
+
+ template<string_literal Lit>
+ error_or<data<
+ typename parameter_pack_type<
+ parameter_key_pack_index<
+ Lit, Names...
+ >::value
+ , Responses...>::type
+ , Encode>> call(
+ data<
+ typename parameter_pack_type<
+ parameter_key_pack_index<
+ Lit, Names...
+ >::value
+ , Requests...>::type
+ , Encode> req
+ ){
+ return get<Lit>().call(std::move(req));
+ }
+
+};
+
+template<typename T, typename Encode>
+struct function_factory {
+ template<typename Func>
+ static function<T,Encode, Func> create(Func func){
+ return function<T,Encode,Func>{std::move(func)};
+ }
+};
+
+template<typename T, typename Encode>
+struct interface_factory {
+ template<typename... Func>
+ static interface<T,Encode, Func...> create(Func... func){
+ return interface<T,Encode, Func...>{std::move(func)...};
+ }
+};
+}
diff --git a/tests/codec.cpp b/tests/codec.cpp
index 7253ecc..439332a 100644
--- a/tests/codec.cpp
+++ b/tests/codec.cpp
@@ -1,6 +1,7 @@
#include <forstio/test/suite.h>
#include <forstio/codec/data.h>
#include <forstio/codec/simple.h>
+#include <forstio/codec/rpc.h>
#include <iostream>
@@ -27,6 +28,19 @@ using TestTuple = Tuple<
TwoDimArray,
UInt64
>;
+
+using TestInt32Pair = Tuple<
+ Int32,
+ Int32
+>;
+
+using TestCalcFunction = Function<TestInt32Pair, Int32>;
+
+using TestInterface = Interface<
+ Member<TestCalcFunction, "add">,
+ Member<TestCalcFunction, "sub">,
+ Member<TestCalcFunction, "multiply">
+>;
}
SAW_TEST("One Dimensional Array") {
using namespace saw;
@@ -256,6 +270,7 @@ SAW_TEST("KelSimple Tuple write and read back"){
SAW_EXPECT(dec_tda.at(0,1).get() == 3, "Incorrect Decoding in array 0,1");
SAW_EXPECT(native.template get<1>().get() == 410, "Incorrect Decoding in number");
}
+
SAW_TEST("KelSimple String write and read back"){
using namespace saw;
@@ -279,4 +294,97 @@ SAW_TEST("KelSimple String write and read back"){
SAW_EXPECT(native == str, "String should've been decoded back correctly");
}
+
+SAW_TEST("Function basics"){
+ using namespace saw;
+
+ {
+ data<schema::TestInt32Pair, encode::Native> native;
+
+ native.get<0>().set(5);
+ native.get<1>().set(40);
+
+ auto func_add = function_factory<schema::TestCalcFunction, encode::Native>::create(
+ [](data<schema::TestInt32Pair, encode::Native> req){
+ data<schema::Int32, encode::Native> resp;
+
+ resp.set(req.get<0>().get() + req.get<1>().get());
+
+ return resp;
+ }
+ );
+
+ auto eov = func_add.call(std::move(native));
+ SAW_EXPECT(eov.is_value(), "Returned value is an error");
+
+ auto& val = eov.get_value();
+ SAW_EXPECT(val.get() == 45, "Sum is incorrect");
+ }
+}
+
+SAW_TEST("Interface basics"){
+ using namespace saw;
+
+ data<schema::TestInt32Pair, encode::Native> native;
+
+ auto func_add =
+ [](data<schema::TestInt32Pair, encode::Native> req){
+ data<schema::Int32, encode::Native> resp;
+
+ resp.set(req.get<0>().get() + req.get<1>().get());
+
+ return resp;
+ };
+ auto func_sub =
+ [](data<schema::TestInt32Pair, encode::Native> req){
+ data<schema::Int32, encode::Native> resp;
+
+ resp.set(req.get<0>().get() - req.get<1>().get());
+
+ return resp;
+ };
+ auto func_multiply = [](data<schema::TestInt32Pair, encode::Native> req){
+ data<schema::Int32, encode::Native> resp;
+
+ resp.set(req.get<0>().get() * req.get<1>().get());
+
+ return resp;
+ };
+
+ auto iface = interface_factory<schema::TestInterface, encode::Native>::create(std::move(func_add), std::move(func_sub), std::move(func_multiply));
+
+ {
+ data<schema::TestInt32Pair, encode::Native> native;
+
+ native.get<0>().set(5);
+ native.get<1>().set(40);
+ auto eov = iface.template call<"add">(std::move(native));
+ SAW_EXPECT(eov.is_value(), "Returned value is an error");
+
+ auto& val = eov.get_value();
+ SAW_EXPECT(val.get() == 45, "Sum is incorrect");
+ }
+ {
+ data<schema::TestInt32Pair, encode::Native> native;
+
+ native.get<0>().set(5);
+ native.get<1>().set(40);
+ auto eov = iface.template call<"sub">(std::move(native));
+ SAW_EXPECT(eov.is_value(), "Returned value is an error");
+
+ auto& val = eov.get_value();
+ SAW_EXPECT(val.get() == -35, "Sum is incorrect");
+ }
+ {
+ data<schema::TestInt32Pair, encode::Native> native;
+
+ native.get<0>().set(5);
+ native.get<1>().set(40);
+ auto eov = iface.template call<"multiply">(std::move(native));
+ SAW_EXPECT(eov.is_value(), "Returned value is an error");
+
+ auto& val = eov.get_value();
+ SAW_EXPECT(val.get() == 200, "Sum is incorrect");
+ }
+}
}