#pragma once #include #include #include #include #include #include #include "transfer.hpp" namespace saw { /** * This class acts as a helper for rpc calls and representing data on the remote. */ template class data_or_id { private: /** * Variant representing the either id or data class. */ std::variant, data> doi_; public: /** * Constructor for instantiating. */ data_or_id(const id& val): doi_{val} {} /** * Constructor for instantiating. */ data_or_id(data val): doi_{std::move(val)} {} /** * Check if this class holds an id. */ bool is_id() const { return std::holds_alternative>(doi_); } /** * Check if this class holds data. */ bool is_data() const { return std::holds_alternative>(doi_); } /** * Returns the id. */ id get_id() const { return std::get>(doi_); } /** * Return a data reference. */ data& get_data(){ return std::get>(doi_); } /** * Return a data reference. */ const data& get_data() const { return std::get>(doi_); } }; /** * Representing data on the remote */ template class remote_data; template class rpc_client; namespace impl { template struct tmpl_group_to_data_server_ptr_std_tuple; template struct tmpl_group_to_data_server_ptr_std_tuple, Encoding, Remote> { using type = std::tuple>...>; }; template struct tmpl_group_to_data_client_std_tuple; template struct tmpl_group_to_data_client_std_tuple, Encoding, Remote> { using type = std::tuple...>; }; } /** * Identifier of an interface function on the wire. * * Keyed on the member name instead of the member index, so reordering an * interface doesn't silently rebind calls between versions. */ template struct rpc_function_id { static constexpr uint32_t value = hash_literal::apply(0u); }; namespace impl { /** * Translates a runtime function id back into the compile time member name * of an interface. * * Needed by every backend where the called function arrives as data instead * of as a template argument. */ template struct iface_dispatch { static_assert(always_false, "Expecting an Interface Type"); }; template struct iface_dispatch...>> { template static Ret apply_ele(uint32_t func_id, Func& func){ if constexpr ( i < sizeof...(Names) ){ constexpr string_literal Lit = parameter_key_pack_type::literal; if(func_id == rpc_function_id::value){ return func.template operator()(); } return apply_ele(func_id, func); } else { (void) func_id; (void) func; return make_error("No interface member with this function id"); } } /** * Calls func.operator()() for the member matching the id. * The return type has to be provided, since there is no member to * deduce it from if the id doesn't match anything. */ template static Ret apply(uint32_t func_id, Func&& func){ return apply_ele(func_id, func); } }; } template class i_rpc_server { protected: virtual ~i_rpc_server() = default; public: virtual std::pair get_class_id() const = 0; template error_or> cast_to(){ { auto rhs = get_class_id(); if(To::class_id.first == rhs.first && To::class_id.second == rhs.second){ return {ptr{*static_cast(this)}}; } } return make_error("Class IDs are not matching."); } }; /** * Implementation of a remote server on the backend */ template class rpc_server { private: interface iface_; public: rpc_server(interface iface): iface_{std::move(iface)} {} }; /** * Representation of a remote. * Partially similar to a network address */ template class remote_address { static_assert(always_false, "Type of remote not supported"); /** * */ }; /** * Reference Backend structure */ template class remote { static_assert(always_false, "Type of backend not supported"); }; }