diff options
-rw-r--r-- | c++/codec/rpc.h | 103 | ||||
-rw-r--r-- | tests/codec.cpp | 108 |
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"); + } +} } |