#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, Storage, 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){ (void) ctx; return func_(req); } else { return func_(req, ctx); } } error_or> call(data&& req, Context ctx = {}){ if constexpr (std::is_same_v){ (void) ctx; return func_(std::move(req)); } else { return func_(std::move(req), ctx); } } }; template class interface; template class interface, Names>...>, Encode, Storage, Context> { public: using Schema = schema::Interface,Names>...>; private: std::tuple, Encode, Storage, Context>...> funcs_; public: interface(function, Encode, Storage, 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 , Storage , Context >& get(){ return std::get::value>(funcs_); } template error_or< data< typename parameter_pack_type< parameter_key_pack_index< Lit, Names... >::value , Responses...>::type , Encode, Storage>> call( data< typename parameter_pack_type< parameter_key_pack_index< Lit, Names... >::value , Requests...>::type , Encode, Storage> req, Context ctx = {} ){ if constexpr (std::is_same_v) { (void) ctx; return get().call(std::move(req)); }else{ return get().call(std::move(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)...}; } }; }