5 #include <boost/any.hpp> 16 template<
typename Signature>
23 :_callback_id(id),_api_connection(con){}
25 template<
typename... Args>
29 uint64_t _callback_id;
30 std::weak_ptr< fc::api_connection > _api_connection;
33 template<
typename R,
typename Arg0,
typename ... Args>
34 std::function<R(Args...)>
bind_first_arg(
const std::function<R(Arg0,Args...)>& f, Arg0 a0 )
38 return [f, a0 = std::decay_t<Arg0>(a0)]( Args... args ) {
return f( a0, args... ); };
41 R
call_generic(
const std::function<R()>& f, variants::const_iterator a0, variants::const_iterator e, uint32_t max_depth = 1 )
46 template<
typename R,
typename Arg0,
typename ... Args>
47 R
call_generic(
const std::function<R(Arg0,Args...)>& f, variants::const_iterator a0,
48 variants::const_iterator e, uint32_t max_depth )
52 FC_ASSERT( max_depth > 0,
"Recursion depth exceeded!" );
56 auto arg = a0->as<std::decay_t<Arg0>>(max_depth - 1);
61 template<
typename R,
typename ... Args>
62 std::function<variant(const fc::variants&, uint32_t)>
to_generic(
const std::function<R(Args...)>& f )
64 return [=](
const variants& args, uint32_t max_depth ) {
65 FC_ASSERT( max_depth > 0,
"Recursion depth exceeded!" );
66 return variant(
call_generic( f, args.begin(), args.end(), max_depth - 1 ), max_depth - 1 );
70 template<
typename ... Args>
71 std::function<variant(const fc::variants&, uint32_t)>
to_generic(
const std::function<
void(Args...)>& f )
73 return [=](
const variants& args, uint32_t max_depth ) {
74 FC_ASSERT( max_depth > 0,
"Recursion depth exceeded!" );
75 call_generic( f, args.begin(), args.end(), max_depth - 1 );
95 : _api_id(api_id), _api_connection(con) {}
112 template<
typename Api>
113 generic_api(
const Api& a,
const std::shared_ptr<fc::api_connection>& c );
119 auto itr = _by_name.find(name);
120 if( itr == _by_name.end() )
122 (
"name",name)(
"api",_by_name) );
123 return call( itr->second, args );
128 if( method_id >= _methods.size() )
130 (
"id",method_id)(
"api",_by_name) );
131 return _methods[method_id](args);
136 return _api_connection;
141 std::vector<std::string> result;
142 result.reserve( _by_name.size() );
143 for(
auto& m : _by_name ) result.push_back(m.first);
148 friend struct api_visitor;
150 template<
typename R,
typename Arg0,
typename ... Args>
151 std::function<R(Args...)>
bind_first_arg(
const std::function<R(Arg0,Args...)>& f, Arg0 a0 )
const 155 return [f, a0 = std::decay_t<Arg0>(a0)]( Args... args ) {
return f( a0, args... ); };
159 R
call_generic(
const std::function<R()>& f, variants::const_iterator a0, variants::const_iterator e, uint32_t max_depth = 1 )
const 164 template<
typename R,
typename Signature,
typename ... Args,
165 typename std::enable_if<std::is_function<Signature>::value,Signature>::type* =
nullptr>
166 R
call_generic(
const std::function<R(std::function<Signature>,Args...)>& f,
167 variants::const_iterator a0, variants::const_iterator e, uint32_t max_depth )
169 FC_ASSERT( a0 != e,
"too few arguments passed to method" );
170 FC_ASSERT( max_depth > 0,
"Recursion depth exceeded!" );
172 return call_generic<R,Args...>( this->bind_first_arg<R,std::function<Signature>,Args...>( f,
173 std::function<Signature>(arg0) ), a0+1, e, max_depth - 1 );
175 template<
typename R,
typename Signature,
typename ... Args,
176 typename std::enable_if<std::is_function<Signature>::value,Signature>::type* =
nullptr>
177 R
call_generic(
const std::function<R(
const std::function<Signature>&,Args...)>& f,
178 variants::const_iterator a0, variants::const_iterator e, uint32_t max_depth )
180 FC_ASSERT( a0 != e,
"too few arguments passed to method" );
181 FC_ASSERT( max_depth > 0,
"Recursion depth exceeded!" );
183 return call_generic<R,Args...>( this->bind_first_arg<R,const std::function<Signature>&,Args...>( f,
184 arg0 ), a0+1, e, max_depth - 1 );
187 template<
typename R,
typename Arg0,
typename ... Args>
188 R
call_generic(
const std::function<R(Arg0,Args...)>& f, variants::const_iterator a0,
189 variants::const_iterator e, uint32_t max_depth )
192 FC_ASSERT( a0 != e || optional_args,
"too few arguments passed to method" );
193 FC_ASSERT( max_depth > 0,
"Recursion depth exceeded!" );
197 auto arg = a0->as<std::decay_t<Arg0>>(max_depth - 1);
204 api_visitor(
generic_api& a,
const std::weak_ptr<fc::api_connection>& s ):_api(a),_api_con(s){ }
206 template<
typename Interface,
typename Adaptor,
typename ... Args>
209 template<
typename Interface,
typename Adaptor,
typename ... Args>
212 template<
typename ... Args>
213 std::function<variant(const fc::variants&)>
to_generic(
const std::function<
fc::api_ptr(Args...)>& f )
const;
215 template<
typename R,
typename ... Args>
216 std::function<variant(const fc::variants&)>
to_generic(
const std::function<R(Args...)>& f )
const;
218 template<
typename ... Args>
219 std::function<variant(const fc::variants&)>
to_generic(
const std::function<
void(Args...)>& f )
const;
221 template<
typename Result,
typename... Args>
222 void operator()(
const char* name, std::function<Result(Args...)>& memb )
const {
223 _api._methods.emplace_back(
to_generic( memb ) );
224 _api._by_name[name] = _api._methods.size() - 1;
228 const std::weak_ptr<fc::api_connection>& _api_con;
232 std::weak_ptr<fc::api_connection> _api_connection;
234 std::map< std::string, uint32_t > _by_name;
235 std::vector< std::function<variant(const variants&)> > _methods;
251 result->visit( api_visitor( api_id, this->shared_from_this() ) );
258 virtual void send_notice( uint64_t callback_id,
variants args =
variants() ) = 0;
262 FC_ASSERT( _local_apis.size() > api_id );
263 return _local_apis[api_id]->call( method_name, args );
267 FC_ASSERT( _local_callbacks.size() > callback_id );
268 return _local_callbacks[callback_id]( args, _max_conversion_depth );
272 FC_ASSERT( _local_callbacks.size() > callback_id );
273 _local_callbacks[callback_id]( args, _max_conversion_depth );
276 template<
typename Interface>
279 auto handle = a.get_handle();
280 auto itr = _handle_to_id.find(handle);
281 if( itr != _handle_to_id.end() )
return itr->second;
283 _local_apis.push_back( std::unique_ptr<generic_api>(
new generic_api(a, shared_from_this() ) ) );
284 _handle_to_id[handle] = _local_apis.size() - 1;
285 return _local_apis.size() - 1;
288 template<
typename Signature>
292 return _local_callbacks.size() - 1;
300 std::vector< std::unique_ptr<generic_api> > _local_apis;
301 std::map< uint64_t, api_id_type > _handle_to_id;
302 std::vector< std::function<variant(const variants&, uint32_t)> > _local_callbacks;
308 std::shared_ptr<fc::api_connection> _connection;
310 api_visitor( uint32_t api_id, std::shared_ptr<fc::api_connection> con )
311 :_api_id(api_id),_connection(std::move(con))
315 api_visitor() =
delete;
317 template<
typename Result>
318 static Result
from_variant(
const variant& v, Result*,
const std::shared_ptr<fc::api_connection>&, uint32_t max_depth )
320 return v.
as<Result>( max_depth );
323 template<
typename ResultInterface>
326 const std::shared_ptr<fc::api_connection>& con,
327 uint32_t max_depth = 1
330 return con->get_remote_api<ResultInterface>( v.
as_uint64() );
336 const std::shared_ptr<fc::api_connection>& con,
337 uint32_t max_depth = 1
346 static fc::variant convert_callbacks(
const std::shared_ptr<fc::api_connection>& con,
const T& v )
348 return fc::variant( v, con->_max_conversion_depth );
351 template<
typename Signature>
352 static fc::variant convert_callbacks(
const std::shared_ptr<fc::api_connection>& con,
const std::function<Signature>& v )
354 return con->register_callback( v );
357 template<
typename Result,
typename... Args>
358 void operator()(
const char* name, std::function<Result(Args...)>& memb )
const 360 auto con = _connection;
361 auto api_id = _api_id;
362 memb = [con,api_id,name]( Args... args ) {
363 auto var_result = con->send_call( api_id, name, { convert_callbacks(con,args)...} );
364 return from_variant( var_result, (Result*)
nullptr, con, con->_max_conversion_depth );
367 template<
typename... Args>
368 void operator()(
const char* name, std::function<
void(Args...)>& memb )
const 370 auto con = _connection;
371 auto api_id = _api_id;
372 memb = [con,api_id,name]( Args... args ) {
373 con->send_call( api_id, name, { convert_callbacks(con,args)...} );
389 return _remote_connection->receive_call( api_id, method_name, std::move(args) );
394 return _remote_connection->receive_callback( callback_id, args );
399 _remote_connection->receive_notice( callback_id, args );
406 FC_ASSERT( rc != this->shared_from_this() );
407 _remote_connection = rc;
409 const std::shared_ptr<fc::api_connection>&
remote_connection()
const {
return _remote_connection; }
414 template<
typename Api>
416 :_api_connection(c),_api(a)
418 boost::any_cast<
const Api&>(a)->visit(
api_visitor( *
this, c ) );
421 template<
typename Interface,
typename Adaptor,
typename ... Args>
425 auto api_con = _api_con;
427 return [=](
const variants& args ) {
428 auto con = api_con.lock();
431 auto api_result = gapi->call_generic( f, args.begin(), args.end(), con->_max_conversion_depth );
432 return con->register_api( api_result );
435 template<
typename Interface,
typename Adaptor,
typename ... Args>
439 auto api_con = _api_con;
442 auto con = api_con.lock();
445 auto api_result = gapi->call_generic( f, args.begin(), args.end(), con->_max_conversion_depth );
447 return con->register_api( *api_result );
452 template<
typename ... Args>
454 const std::function<
fc::api_ptr(Args...)>& f )
const 456 auto api_con = _api_con;
459 auto con = api_con.lock();
462 auto api_result = gapi->call_generic( f, args.begin(), args.end(), con->_max_conversion_depth );
465 return api_result->register_api( *con );
469 template<
typename R,
typename ... Args>
472 auto con = _api_con.lock();
474 uint32_t max_depth = con->_max_conversion_depth;
476 return [f,gapi,max_depth](
const variants& args ) {
477 return variant( gapi->call_generic( f, args.begin(), args.end(), max_depth ), max_depth );
481 template<
typename ... Args>
484 auto con = _api_con.lock();
486 uint32_t max_depth = con->_max_conversion_depth;
488 return [f,gapi,max_depth](
const variants& args ) {
489 gapi->call_generic( f, args.begin(), args.end(), max_depth );
507 template<
typename Interface,
typename Transform >
513 template<
typename T >
517 api<T>* maybe_requested_type =
dynamic_cast< api<T>*
>(
this);
518 if( maybe_requested_type !=
nullptr )
519 return *maybe_requested_type;
523 std::shared_ptr< api_connection > api_conn = maybe_any->
_api_connection.lock();
525 return api_conn->get_remote_api<T>( maybe_any->
_api_id );
529 template<
typename Signature>
530 template<
typename... Args>
533 std::shared_ptr< fc::api_connection > locked = _api_connection.lock();
536 throw fc::eof_exception();
537 locked->send_callback( _callback_id,
fc::variants{ args... } ).
template as< result_type >();
541 template<
typename... Args>
548 :_callback_id(id),_api_connection(con){}
552 std::shared_ptr< fc::api_connection > locked = _api_connection.lock();
555 throw fc::eof_exception();
556 locked->send_notice( _callback_id,
fc::variants{ args... } );
560 uint64_t _callback_id;
561 std::weak_ptr< fc::api_connection > _api_connection;
variant receive_call(api_id_type api_id, const string &method_name, const variants &args=variants()) const
const std::shared_ptr< fc::api_connection > & remote_connection() const
std::function< R(Args...)> bind_first_arg(const std::function< R(Arg0, Args...)> &f, Arg0 a0)
std::weak_ptr< fc::api_connection > get_connection()
std::function< Signature >::result_type result_type
std::function< variant(const fc::variants &, uint32_t)> to_generic(const std::function< R(Args...)> &f)
generic_api(const Api &a, const std::shared_ptr< fc::api_connection > &c)
virtual variant send_callback(uint64_t callback_id, variants args=variants()) override
result_type operator()(Args... args) const
local_api_connection(uint32_t max_depth)
virtual api_id_type register_api(api_connection &conn) const override
std::vector< std::string > get_method_names(api_id_type local_api_id=0) const
void receive_notice(uint64_t callback_id, const variants &args=variants()) const
virtual ~api_connection()
virtual variant send_call(api_id_type api_id, string method_name, variants args=variants()) override
std::vector< variant > variants
callback_functor(std::weak_ptr< fc::api_connection > con, uint64_t id)
uint64_t as_uint64() const
api_connection(uint32_t max_depth)
std::shared_ptr< api_base > api_ptr
std::vector< std::string > get_method_names() const
const uint32_t _max_conversion_depth
any_api(api_id_type api_id, const std::shared_ptr< fc::api_connection > &con)
api< T, identity_member_with_optionals > as()
variant call(uint32_t method_id, const variants &args)
provides stack-based nullable value similar to boost::optional
virtual api_id_type register_api(api_connection &conn) const override
variant call(const string &name, const variants &args)
virtual void send_notice(uint64_t callback_id, variants args=variants()) override
variant receive_callback(uint64_t callback_id, const variants &args=variants()) const
std::weak_ptr< fc::api_connection > _api_connection
std::function< variant(const fc::variants &, uint32_t)> to_generic(const std::function< void(Args...)> &f)
virtual uint64_t get_handle() const override
#define FC_ASSERT(TEST,...)
Checks a condition and throws an assert_exception if the test is FALSE.
T as(uint32_t max_depth) const
stores null, int64, uint64, double, bool, string, std::vector<variant>, and variant_object's.
void set_remote_connection(const std::shared_ptr< fc::api_connection > &rc)
#define FC_THROW_EXCEPTION(EXCEPTION, FORMAT,...)
fc::signal< void()> closed
api_id_type register_api(const Interface &a)
R call_generic(const std::function< R()> &f, variants::const_iterator a0, variants::const_iterator e, uint32_t max_depth=1)
friend struct api_visitor
void operator()(Args... args) const
object_restriction_predicate< operation > result_type
callback_functor(std::weak_ptr< fc::api_connection > con, uint64_t id)
void from_variant(const variant &var, flat_set< T, A... > &vo, uint32_t _max_depth)
uint64_t register_callback(const std::function< Signature > &cb)
std::shared_ptr< fc::api_connection > _remote_connection
boost::signals2::signal< T > signal
api< T > get_remote_api(api_id_type api_id=0)
This metafunction determines whether all of its template arguments are instantiations of fc::optional...