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>
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>
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 );
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);
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!" );
171 detail::callback_functor<Signature> arg0(
get_connection(), a0->as<uint64_t>(1) );
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!" );
182 detail::callback_functor<Signature> arg0(
get_connection(), a0->as<uint64_t>(1) );
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 )
191 bool optional_args = detail::all_optionals<std::decay_t<Arg0>, std::decay_t<Args>...>::value;
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);
206 template<
typename Interface,
typename Adaptor,
typename ... Args>
207 std::function<variant(
const fc::variants&)>
to_generic(
const std::function<api<Interface,Adaptor>(Args...)>& f )
const;
209 template<
typename Interface,
typename Adaptor,
typename ... Args>
212 template<
typename ... Args>
215 template<
typename R,
typename ... Args>
218 template<
typename ... Args>
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() ) );
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 );
272 FC_ASSERT( _local_callbacks.size() > callback_id );
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)...} );
406 FC_ASSERT( rc != this->shared_from_this() );
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;
475 generic_api* gapi = &_api;
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;
487 generic_api* gapi = &_api;
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;