Json RPC works
- adding call_fused() for tuple + functor - fixed json handling of true,false, and null - cast from value to tuple
This commit is contained in:
parent
a6541b825a
commit
031e2db4db
9 changed files with 91 additions and 31 deletions
|
|
@ -4,16 +4,18 @@
|
|||
#include <boost/preprocessor/repeat.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_params.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
|
||||
#include <boost/preprocessor/facilities/empty.hpp>
|
||||
|
||||
|
||||
namespace fc { namespace json {
|
||||
//static std::function<fc::future<R>( BOOST_PP_ENUM_PARAMS(n,A) ) >
|
||||
|
||||
namespace detail {
|
||||
struct rpc_member {
|
||||
#define RPC_MEMBER_FUNCTOR(z,n,IS_CONST) \
|
||||
template<typename R, typename C, typename P BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS( n, typename A)> \
|
||||
static fc::function<fc::future<R> BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n,A) > \
|
||||
template<typename R, typename C, typename P BOOST_PP_ENUM_TRAILING_PARAMS( n, typename A)> \
|
||||
static fc::function<fc::future<R> BOOST_PP_ENUM_TRAILING_PARAMS(n,A) > \
|
||||
functor( P, R (C::*mem_func)(BOOST_PP_ENUM_PARAMS(n,A)) IS_CONST, \
|
||||
const rpc_connection::ptr& c = rpc_connection::ptr(), const char* name = nullptr ) { \
|
||||
return [=](BOOST_PP_ENUM_BINARY_PARAMS(n,A,a))->fc::future<R>{ \
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ namespace fc { namespace json {
|
|||
template<typename T>
|
||||
struct pending_result_impl : virtual public promise<T>, virtual public pending_result {
|
||||
virtual void handle_result( const fc::value& s ) {
|
||||
slog( "cast %s", typeid(T).name() );
|
||||
this->set_value( value_cast<T>(s) );
|
||||
}
|
||||
protected:
|
||||
|
|
@ -40,13 +41,16 @@ namespace fc { namespace json {
|
|||
};
|
||||
|
||||
|
||||
template<typename R, typename Args>
|
||||
template<typename R, typename... Args>
|
||||
struct rpc_server_method_impl : public rpc_server_method {
|
||||
rpc_server_method_impl( const fc::function<R,Args>& f ):func(f){}
|
||||
//static_assert( fc::is_tuple<Args>::type::value, "params should be a tuple" );
|
||||
rpc_server_method_impl( const fc::function<R,Args...>& f ):func(f){}
|
||||
virtual value call( const value& v ) {
|
||||
return value( func( fc::value_cast<Args>( v ) ) );
|
||||
// slog( "cast %s", typeid(Args).name() );
|
||||
return value( call_fused( func, fc::value_cast<fc::tuple<Args...> >( v ) ) );
|
||||
//return value( func( fc::value_cast<Args>( v )) );
|
||||
}
|
||||
fc::function<R,Args> func;
|
||||
fc::function<R,Args...> func;
|
||||
};
|
||||
|
||||
template<typename InterfaceType>
|
||||
|
|
@ -54,8 +58,8 @@ namespace fc { namespace json {
|
|||
public:
|
||||
add_method_visitor( const fc::ptr<InterfaceType>& p, fc::json::rpc_connection& c ):_ptr(p),_con(c){}
|
||||
|
||||
template<typename R, typename Args>
|
||||
void operator()( const char* name, fc::function<R,Args>& meth);
|
||||
template<typename R, typename... Args>
|
||||
void operator()( const char* name, fc::function<R,Args...>& meth);
|
||||
|
||||
const fc::ptr<InterfaceType>& _ptr;
|
||||
fc::json::rpc_connection& _con;
|
||||
|
|
@ -91,6 +95,7 @@ namespace fc { namespace json {
|
|||
|
||||
template<typename R, typename Args >
|
||||
void add_method( const fc::string& name, const fc::function<R,Args>& a ) {
|
||||
static_assert( is_tuple<Args>::type::value, "is tuple" );
|
||||
this->add_method( name, rpc_server_method::ptr(new detail::rpc_server_method_impl<R,Args>(a) ) );
|
||||
}
|
||||
|
||||
|
|
@ -121,9 +126,10 @@ namespace fc { namespace json {
|
|||
namespace detail {
|
||||
|
||||
template<typename InterfaceType>
|
||||
template<typename R, typename Args>
|
||||
void add_method_visitor<InterfaceType>::operator()( const char* name, fc::function<R,Args>& meth) {
|
||||
_con.add_method( name, rpc_server_method::ptr( new rpc_server_method_impl<R,Args>(meth) ) );
|
||||
template<typename R, typename... Args>
|
||||
void add_method_visitor<InterfaceType>::operator()( const char* name, fc::function<R,Args...>& meth) {
|
||||
_con.add_method( name, rpc_server_method::ptr(
|
||||
new rpc_server_method_impl<R,Args...>(meth) ) );
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ namespace fc {
|
|||
#define ILIST_PARAMS(z,n,data) BOOST_PP_CAT(a,n)( fc::forward<BOOST_PP_CAT(AA,n)>( BOOST_PP_CAT(a,n) ) )
|
||||
#define ILIST_PARAMS_COPY(z,n,data) BOOST_PP_CAT(a,n)( t.BOOST_PP_CAT(a,n) )
|
||||
#define VISIT_PARAMS(z,n,data) v(BOOST_PP_CAT(a,n));
|
||||
#define LIST_MEMBERS_ON(z,n,data) data.BOOST_PP_CAT(a,n)
|
||||
#define FORWARD_PARAMS(z,n,data) fc::forward<BOOST_PP_CAT(AA,n)>(BOOST_PP_CAT(a,n))
|
||||
#define MEM_PARAMS(z,n,data) BOOST_PP_CAT(A,n) BOOST_PP_CAT(a,n);
|
||||
#define TUPLE(z,n,unused) \
|
||||
|
|
@ -77,13 +78,20 @@ namespace fc {
|
|||
template<BOOST_PP_ENUM_PARAMS( n, typename AA)> \
|
||||
tuple<BOOST_PP_ENUM_PARAMS(n,AA)> make_tuple( BOOST_PP_ENUM( n, RREF_PARAMS, unused) ) { \
|
||||
return tuple<BOOST_PP_ENUM_PARAMS(n,AA)>( BOOST_PP_ENUM( n, FORWARD_PARAMS,unused ) ); \
|
||||
}
|
||||
} \
|
||||
template<typename Functor, typename Tuple> \
|
||||
auto call_fused( Functor f, Tuple&& t ) \
|
||||
-> decltype( f( BOOST_PP_ENUM( n, LIST_MEMBERS_ON, t) ) ) { \
|
||||
return f( BOOST_PP_ENUM( n, LIST_MEMBERS_ON, t) ); \
|
||||
}
|
||||
|
||||
template<BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(9, typename A, void)> struct tuple{};
|
||||
BOOST_PP_REPEAT_FROM_TO( 1, 8, TUPLE, unused )
|
||||
|
||||
|
||||
#undef FORWARD_PARAMS
|
||||
#undef RREF_PARAMS
|
||||
#undef LIST_MEMBERS_ON
|
||||
#undef ILIST_PARAMS
|
||||
#undef ILIST_PARAMS_COPY
|
||||
#undef VISIT_PARAMS
|
||||
|
|
@ -99,6 +107,18 @@ namespace fc {
|
|||
|
||||
inline tuple<> make_tuple(){ return tuple<>(); }
|
||||
|
||||
template<typename T>
|
||||
struct is_tuple {
|
||||
typedef fc::false_type type;
|
||||
};
|
||||
|
||||
template<typename... T>
|
||||
struct is_tuple<fc::tuple<T...> > {
|
||||
typedef fc::true_type type;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*
|
||||
template<typename A>
|
||||
struct tuple<A,void> {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,9 @@
|
|||
#include <fc/lexical_cast.hpp>
|
||||
#include <fc/numeric_cast.hpp>
|
||||
#include <fc/value_io.hpp>
|
||||
#include <fc/tuple.hpp>
|
||||
|
||||
#include <typeinfo>
|
||||
|
||||
namespace fc {
|
||||
|
||||
|
|
@ -26,9 +29,9 @@ namespace fc {
|
|||
virtual void operator()( const double& v ){ m_out = fc::numeric_cast<T>(v); }
|
||||
virtual void operator()( const bool& v ){ m_out = fc::numeric_cast<T>(v); }
|
||||
virtual void operator()( const fc::string& v ) { m_out = fc::lexical_cast<T>(v); }
|
||||
virtual void operator()( const value::object& ) { FC_THROW_MSG("bad cast"); }
|
||||
virtual void operator()( const value::array& ) { FC_THROW_MSG("bad cast"); }
|
||||
virtual void operator()( ) { FC_THROW_MSG("bad cast"); }
|
||||
virtual void operator()( const value::object& ) { FC_THROW_MSG("bad cast"); }
|
||||
virtual void operator()( const value::array& ) { FC_THROW_MSG("bad cast"); }
|
||||
virtual void operator()( ) { FC_THROW_MSG("bad cast"); }
|
||||
private:
|
||||
T& m_out;
|
||||
};
|
||||
|
|
@ -48,10 +51,10 @@ namespace fc {
|
|||
virtual void operator()( const float& v ){ m_out = fc::lexical_cast<fc::string>(v); }
|
||||
virtual void operator()( const double& v ){ m_out = fc::lexical_cast<fc::string>(v); }
|
||||
virtual void operator()( const bool& v ){ m_out = fc::lexical_cast<fc::string>(v); }
|
||||
virtual void operator()( const fc::string& v ){ m_out = v; }
|
||||
virtual void operator()( const value::object& ) { FC_THROW_MSG("bad cast"); }
|
||||
virtual void operator()( const value::array& ) { FC_THROW_MSG("bad cast"); }
|
||||
virtual void operator()( ) { FC_THROW_MSG("bad cast"); }
|
||||
virtual void operator()( const fc::string& v ){ m_out = v; }
|
||||
virtual void operator()( const value::object& ) { FC_THROW_MSG("bad cast"); }
|
||||
virtual void operator()( const value::array& ) { FC_THROW_MSG("bad cast"); }
|
||||
virtual void operator()( ) { FC_THROW_MSG("bad cast"); }
|
||||
|
||||
private:
|
||||
fc::string& m_out;
|
||||
|
|
@ -122,14 +125,45 @@ namespace fc {
|
|||
virtual void operator()( const value::array& ) { FC_THROW_MSG("bad cast");}
|
||||
virtual void operator()( ) { }
|
||||
};
|
||||
template<typename IsTuple=fc::false_type>
|
||||
struct cast_if_tuple {
|
||||
template<typename T>
|
||||
static T cast( const value& v ) {
|
||||
slog( "cast non tuple %s", typeid(T).name() );
|
||||
T out;
|
||||
v.visit(cast_visitor<T>(out));
|
||||
return out;
|
||||
}
|
||||
};
|
||||
template<>
|
||||
struct cast_if_tuple<fc::true_type> {
|
||||
struct member_visitor {
|
||||
member_visitor( const value& v )
|
||||
:_val(v),idx(0){}
|
||||
template<typename Member>
|
||||
void operator()( Member& m ) {
|
||||
m = value_cast<Member>(_val[idx]);
|
||||
++idx;
|
||||
}
|
||||
const value& _val;
|
||||
int idx;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
static T cast( const value& v ) {
|
||||
T out;
|
||||
out.visit( member_visitor(v) );
|
||||
slog( "cast tuple" );
|
||||
// v.visit(cast_visitor<T>(out));
|
||||
return out;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename IsReflected=fc::false_type>
|
||||
struct cast_if_reflected {
|
||||
template<typename T>
|
||||
static T cast( const value& v ) {
|
||||
T out;
|
||||
v.visit(cast_visitor<T>(out));
|
||||
return out;
|
||||
return cast_if_tuple<typename is_tuple<T>::type>::template cast<T>(v);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ namespace fc {
|
|||
}
|
||||
else {
|
||||
if( !is_optional< typename fc::remove_reference<decltype(c.*p)>::type >::type::value ) {
|
||||
wlog( "unable to find name: '%1%'",name);
|
||||
wlog( "unable to find name: '%s'",name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -587,7 +587,7 @@ char* read_key_val( value::object& obj, bool sc, char* in, char* end, fc::json::
|
|||
if( sc ) { // if we expect a ,
|
||||
if( *name != ',' ) { // but didn't get one
|
||||
if( *name != '}' )
|
||||
wlog( "expected ',' or '}' but got %1%", name ); // warn and accept name
|
||||
wlog( "expected ',' or '}' but got '%s'", name ); // warn and accept name
|
||||
} else { // we got the exepcted , read the expected name
|
||||
name = fc::json::read_value( name_end, end, name_end );
|
||||
}
|
||||
|
|
@ -757,15 +757,15 @@ fc::value to_value( char* start, char* end, error_collector& ec ) {
|
|||
}
|
||||
case 'n': {
|
||||
temp_set move_end(ve,'\0');
|
||||
if( strcmp(s,"null" ) ) return value();
|
||||
if( strcmp(s,"null" ) == 0) return value();
|
||||
}
|
||||
case 't': {
|
||||
temp_set move_end(ve,'\0');
|
||||
if( strcmp(s,"true" ) ) return true;
|
||||
if( strcmp(s,"true" ) == 0) return true;
|
||||
}
|
||||
case 'f': {
|
||||
temp_set move_end(ve,'\0');
|
||||
if( strcmp(s,"false" ) ) return false;
|
||||
if( strcmp(s,"false" ) == 0) return false;
|
||||
}
|
||||
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ namespace fc { namespace json {
|
|||
|
||||
value nul;
|
||||
const value& params = (p_itr != end) ? p_itr->val : nul;
|
||||
slog( "params '%s'", to_string( params ).c_str() );
|
||||
|
||||
if( id_itr != end ) { // capture reply
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -33,11 +33,9 @@ namespace fc {
|
|||
return *this;
|
||||
}
|
||||
size_t stringstream::readsome( char* buf, size_t len ) {
|
||||
slog("");
|
||||
return my->ss.readsome(buf,len);
|
||||
}
|
||||
istream& stringstream::read( char* buf, size_t len ) {
|
||||
slog("");
|
||||
my->ss.read(buf,len);
|
||||
return *this;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,9 +9,8 @@ namespace fc {
|
|||
|
||||
class tcp_socket::impl {
|
||||
public:
|
||||
impl():_sock( fc::asio::default_io_service() ){ slog( "sock %p", this); }
|
||||
impl():_sock( fc::asio::default_io_service() ){ }
|
||||
~impl(){
|
||||
slog( "~sock %p", this );
|
||||
if( _sock.is_open() ) _sock.close();
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue