9#include <fc/signals.hpp>
15 template<
typename Signature>
16 class callback_functor
19 typedef typename std::function<Signature>::result_type
result_type;
22 :_callback_id(
id),_api_connection(con){}
24 template<
typename... Args>
29 std::weak_ptr< fc::api_connection > _api_connection;
32 template<
typename R,
typename Arg0,
typename ... Args>
33 std::function<
R(Args...)>
bind_first_arg(
const std::function<
R(Arg0,Args...)>&
f, Arg0 a0 )
35 return [=]( Args... args ) {
return f( a0, args... ); };
38 R call_generic(
const std::function<
R()>&
f, variants::const_iterator a0, variants::const_iterator e )
43 template<
typename R,
typename Arg0,
typename ... Args>
44 R call_generic(
const std::function<
R(Arg0,Args...)>&
f, variants::const_iterator a0, variants::const_iterator e )
50 template<
typename R,
typename ... Args>
58 template<
typename ... Args>
99 template<
typename Api>
100 generic_api(
const Api&
a,
const std::shared_ptr<fc::api_connection>& c );
106 auto itr = _by_name.find(
name);
107 FC_ASSERT( itr != _by_name.end(),
"no method with name '${name}'", (
"name",
name)(
"api",_by_name) );
108 return call( itr->second, args );
113 FC_ASSERT( method_id < _methods.size() );
114 return _methods[method_id](args);
119 return _api_connection;
124 std::vector<std::string> result;
125 result.reserve( _by_name.size() );
126 for(
auto& m : _by_name ) result.push_back(m.first);
131 friend struct api_visitor;
133 template<
typename R,
typename Arg0,
typename ... Args>
134 std::function<
R(Args...)> bind_first_arg(
const std::function<
R(Arg0,Args...)>&
f, Arg0 a0 )
const
136 return [=]( Args... args ) {
return f( a0, args... ); };
140 R call_generic(
const std::function<
R()>&
f, variants::const_iterator a0, variants::const_iterator e )
const
145 template<
typename R,
typename Signature,
typename ... Args>
146 R call_generic(
const std::function<
R(std::function<Signature>,Args...)>&
f, variants::const_iterator a0, variants::const_iterator e )
148 FC_ASSERT( a0 != e,
"too few arguments passed to method" );
150 return call_generic<
R,Args...>( this->bind_first_arg<R,std::function<Signature>,Args...>(
f, std::function<Signature>(arg0) ), a0+1, e );
152 template<
typename R,
typename Signature,
typename ... Args>
153 R call_generic(
const std::function<
R(
const std::function<Signature>&,Args...)>&
f, variants::const_iterator a0, variants::const_iterator e )
155 FC_ASSERT( a0 != e,
"too few arguments passed to method" );
157 return call_generic<
R,Args...>( this->bind_first_arg<R,const std::function<Signature>&,Args...>(
f, arg0 ), a0+1, e );
160 template<
typename R,
typename Arg0,
typename ... Args>
161 R call_generic(
const std::function<
R(Arg0,Args...)>&
f, variants::const_iterator a0, variants::const_iterator e )
163 FC_ASSERT( a0 != e,
"too few arguments passed to method" );
164 return call_generic<
R,Args...>( this->bind_first_arg<
R,Arg0,Args...>(
f, a0->as<
typename std::decay<Arg0>::type >() ), a0+1, e );
171 template<
typename Interface,
typename Adaptor,
typename ... Args>
172 std::function<variant(
const fc::variants&)> to_generic(
const std::function<api<Interface,Adaptor>(Args...)>&
f )
const;
174 template<
typename Interface,
typename Adaptor,
typename ... Args>
175 std::function<variant(
const fc::variants&)> to_generic(
const std::function<std::optional<api<Interface,Adaptor>>(Args...)>&
f )
const;
177 template<
typename ... Args>
180 template<
typename R,
typename ... Args>
181 std::function<variant(
const fc::variants&)> to_generic(
const std::function<
R(Args...)>&
f )
const;
183 template<
typename ... Args>
184 std::function<variant(
const fc::variants&)> to_generic(
const std::function<
void(Args...)>&
f )
const;
186 template<
typename Result,
typename... Args>
187 void operator()(
const char*
name, std::function<Result(Args...)>& memb )
const {
188 _api._methods.emplace_back( to_generic( memb ) );
189 _api._by_name[
name] = _api._methods.size() - 1;
193 const std::weak_ptr<fc::api_connection>& _api_con;
197 std::weak_ptr<fc::api_connection> _api_connection;
199 std::map< std::string, uint32_t > _by_name;
200 std::vector< std::function<variant(
const variants&)> > _methods;
216 result->visit( api_visitor( api_id, this->shared_from_this() ) );
227 FC_ASSERT( _local_apis.size() > api_id );
228 return _local_apis[api_id]->call( method_name, args );
232 FC_ASSERT( _local_callbacks.size() > callback_id );
233 return _local_callbacks[callback_id]( args );
237 FC_ASSERT( _local_callbacks.size() > callback_id );
238 _local_callbacks[callback_id]( args );
241 template<
typename Interface>
244 auto handle =
a.get_handle();
245 auto itr = _handle_to_id.find(handle);
246 if( itr != _handle_to_id.end() )
return itr->second;
248 _local_apis.push_back( std::unique_ptr<generic_api>(
new generic_api(
a, shared_from_this() ) ) );
249 _handle_to_id[handle] = _local_apis.size() - 1;
250 return _local_apis.size() - 1;
253 template<
typename Signature>
257 return _local_callbacks.size() - 1;
264 std::vector< std::unique_ptr<generic_api> > _local_apis;
265 std::map< uint64_t, api_id_type > _handle_to_id;
266 std::vector< std::function<
variant(
const variants&)> > _local_callbacks;
272 std::shared_ptr<fc::api_connection> _connection;
274 api_visitor(
uint32_t api_id, std::shared_ptr<fc::api_connection> con )
275 :_api_id(api_id),_connection(std::move(con))
279 api_visitor() =
delete;
281 template<
typename Result>
282 static Result from_variant(
const variant& v, Result*,
const std::shared_ptr<fc::api_connection>& )
284 return v.
as<Result>();
287 template<
typename ResultInterface>
290 const std::shared_ptr<fc::api_connection>& con
293 return con->get_remote_api<ResultInterface>( v.
as_uint64() );
299 const std::shared_ptr<fc::api_connection>& con
306 static fc::variant convert_callbacks(
const std::shared_ptr<fc::api_connection>&,
const T& v )
311 template<
typename Signature>
312 static fc::variant convert_callbacks(
const std::shared_ptr<fc::api_connection>& con,
const std::function<Signature>& v )
314 return con->register_callback( v );
317 template<
typename Result,
typename... Args>
318 void operator()(
const char*
name, std::function<Result(Args...)>& memb )
const
320 auto con = _connection;
321 auto api_id = _api_id;
322 memb = [con,api_id,
name]( Args... args ) {
323 auto var_result = con->send_call( api_id,
name, { convert_callbacks(con,args)...} );
324 return from_variant( var_result, (Result*)
nullptr, con );
327 template<
typename... Args>
328 void operator()(
const char*
name, std::function<
void(Args...)>& memb )
const
330 auto con = _connection;
331 auto api_id = _api_id;
332 memb = [con,api_id,
name]( Args... args ) {
333 con->send_call( api_id,
name, { convert_callbacks(con,args)...} );
371 template<
typename Api>
373 :_api_connection(c),_api(
a)
375 boost::any_cast<const Api&>(
a)->visit(
api_visitor( *
this, c ) );
378 template<
typename Interface,
typename Adaptor,
typename ... Args>
382 auto api_con = _api_con;
384 return [=](
const variants& args ) {
385 auto con = api_con.lock();
388 auto api_result = gapi->call_generic(
f, args.begin(), args.end() );
389 return con->register_api( api_result );
392 template<
typename Interface,
typename Adaptor,
typename ... Args>
393 std::function<variant(
const fc::variants&)> generic_api::api_visitor::to_generic(
396 auto api_con = _api_con;
399 auto con = api_con.lock();
402 auto api_result = gapi->call_generic(
f, args.begin(), args.end() );
404 return con->register_api( *api_result );
409 template<
typename ... Args>
410 std::function<variant(
const fc::variants&)> generic_api::api_visitor::to_generic(
413 auto api_con = _api_con;
416 auto con = api_con.lock();
419 auto api_result = gapi->call_generic(
f, args.begin(), args.end() );
422 return api_result->register_api( *con );
426 template<
typename R,
typename ... Args>
427 std::function<variant(
const fc::variants&)> generic_api::api_visitor::to_generic(
const std::function<
R(Args...)>&
f )
const
430 return [
f,gapi](
const variants& args ) {
431 return variant( gapi->call_generic(
f, args.begin(), args.end() ) );
435 template<
typename ... Args>
436 std::function<variant(
const fc::variants&)> generic_api::api_visitor::to_generic(
const std::function<
void(Args...)>&
f )
const
439 return [
f,gapi](
const variants& args ) {
440 gapi->call_generic(
f, args.begin(), args.end() );
458 template<
typename Interface,
typename Transform >
464 template<
typename T >
468 api<T>* maybe_requested_type =
dynamic_cast< api<T>*
>(
this);
469 if( maybe_requested_type !=
nullptr )
470 return *maybe_requested_type;
474 std::shared_ptr< api_connection > api_conn = maybe_any->
_api_connection.lock();
476 return api_conn->get_remote_api<
T>( maybe_any->
_api_id );
480 template<
typename Signature>
481 template<
typename... Args>
484 std::shared_ptr< fc::api_connection > locked = _api_connection.lock();
487 throw fc::eof_exception();
488 locked->send_callback( _callback_id,
fc::variants{ args... } ).
template as< result_type >();
492 template<
typename... Args>
499 :_callback_id(
id),_api_connection(con){}
503 std::shared_ptr< fc::api_connection > locked = _api_connection.lock();
506 throw fc::eof_exception();
507 locked->send_notice( _callback_id,
fc::variants{ args... } );
512 std::weak_ptr< fc::api_connection > _api_connection;
api< T, identity_member > as()
variant receive_callback(uint64_t callback_id, const variants &args=variants()) const
virtual ~api_connection()
std::vector< std::string > get_method_names(api_id_type local_api_id=0) const
virtual variant send_call(api_id_type api_id, string method_name, variants args=variants())=0
api< T > get_remote_api(api_id_type api_id=0)
fc::signal< void()> closed
uint64_t register_callback(const std::function< Signature > &cb)
virtual void send_notice(uint64_t callback_id, variants args=variants())=0
void receive_notice(uint64_t callback_id, const variants &args=variants()) const
virtual variant send_callback(uint64_t callback_id, variants args=variants())=0
api_id_type register_api(const Interface &a)
variant receive_call(api_id_type api_id, const string &method_name, const variants &args=variants()) const
virtual api_id_type register_api(api_connection &conn) const override
any_api(api_id_type api_id, const std::shared_ptr< fc::api_connection > &con)
virtual api_id_type register_api(api_connection &conn) const override
virtual uint64_t get_handle() const override
std::weak_ptr< fc::api_connection > _api_connection
callback_functor(std::weak_ptr< fc::api_connection > con, uint64_t id)
void operator()(Args... args) const
callback_functor(std::weak_ptr< fc::api_connection > con, uint64_t id)
result_type operator()(Args... args) const
std::function< Signature >::result_type result_type
generic_api(const generic_api &cpy)=delete
variant call(uint32_t method_id, const variants &args)
std::vector< std::string > get_method_names() const
std::weak_ptr< fc::api_connection > get_connection()
friend struct api_visitor
variant call(const string &name, const variants &args)
generic_api(const Api &a, const std::shared_ptr< fc::api_connection > &c)
std::shared_ptr< fc::api_connection > _remote_connection
const std::shared_ptr< fc::api_connection > & remote_connection() const
void set_remote_connection(const std::shared_ptr< fc::api_connection > &rc)
virtual void send_notice(uint64_t callback_id, variants args=variants()) override
virtual variant send_call(api_id_type api_id, string method_name, variants args=variants()) override
virtual variant send_callback(uint64_t callback_id, variants args=variants()) override
stores null, int64, uint64, double, bool, string, std::vector<variant>, and variant_object's.
uint64_t as_uint64() const
#define FC_ASSERT(TEST,...)
Checks a condition and throws an assert_exception if the test is FALSE.
std::function< variant(const fc::variants &)> to_generic(const std::function< R(Args...)> &f)
R call_generic(const std::function< R()> &f, variants::const_iterator a0, variants::const_iterator e)
std::function< R(Args...)> bind_first_arg(const std::function< R(Arg0, Args...)> &f, Arg0 a0)
std::vector< fc::variant > variants
std::shared_ptr< api_base > api_ptr
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
#define T(meth, val, expected)
unsigned __int64 uint64_t