#pragma once #include #include #include "schema.hpp" #include "data.hpp" namespace saw { template class function; namespace impl { template struct FuncReturnTypeHelper { using Type = data; }; template struct FuncReturnTypeHelper { using Type = void; }; template struct FuncTypeHelper { using Type = std::function::Type>(data&, Ctx)>; }; template struct FuncTypeHelper { using Type = std::function::Type>(data&)>; }; } template class function, Encode, Context> { private: typename impl::FuncTypeHelper::Type func_; using ResponseDataType = typename impl::FuncReturnTypeHelper::Type; public: template function(Func func): func_{std::move(func)} {} error_or call(data& req, Context ctx = {}){ if constexpr (std::is_same_v){ (void) ctx; return func_(req); } else { return func_(req, ctx); } } }; template class interface; template class interface, Names>...>, Encode, Context> { public: using Schema = schema::Interface,Names>...>; private: std::tuple, Encode, Context>...> funcs_; public: interface(function, Encode, Context>... funcs): funcs_{std::move(funcs)...} {} /** * Get the function based on the string literal matching the position in the tuple */ template 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 , Context >& get(){ return std::get::value>(funcs_); } template error_or< typename impl::FuncReturnTypeHelper< typename parameter_pack_type< parameter_key_pack_index< Lit, Names... >::value , Responses...>::type , Encode>::Type > call( data< typename parameter_pack_type< parameter_key_pack_index< Lit, Names... >::value , Requests...>::type , Encode>& req, Context ctx = {} ){ if constexpr (std::is_same_v) { (void) ctx; return get().call(req); }else{ return get().call(req, ctx); } } }; template struct function_factory { template static function create(Func func){ return function {std::move(func)}; } }; template struct interface_factory { template static interface create(Func... func){ return interface{std::move(func)...}; } }; }