#pragma once #include #include #include "schema.hpp" #include "data.hpp" namespace saw { template class function; namespace impl { template struct FuncTypeHelper { using Type = std::function(data, Ctx)>; }; template struct FuncTypeHelper { using Type = std::function(data)>; }; } template class function, Encode, Context> { private: typename impl::FuncTypeHelper::Type func_; public: template function(Func func): func_{std::move(func)} {} error_or> call(data req, Context ctx = {}){ if constexpr (std::is_same_v){ return func_(std::move(req)); } else { return func_(std::move(req), ctx); } } }; template class i_interface { public: virtual ~i_interface() = default; }; template class interface; template class interface, Names>...>, Encode> { public: using Schema = schema::Interface,Names>...>; private: std::tuple, Encode>...> funcs_; public: interface(function, Encode>... 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 >& get(){ return std::get::value>(funcs_); } template 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().call(std::move(req)); } }; 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)...}; } }; }