#ifndef _JSON_RPC_CONNECTION_HPP_ #define _JSON_RPC_CONNECTION_HPP_ #include #include #include #include namespace fc { namespace json { namespace detail { struct pending_result : virtual public promise_base { typedef shared_ptr ptr; virtual void handle_result( const fc::string& ) = 0; void handle_error( const fc::string& ); int64_t id; pending_result::ptr next; protected: ~pending_result(){} }; template struct pending_result_impl : virtual public promise, virtual public pending_result { virtual void handle_result( const fc::string& s ) { set_value( fc::json::from_string(s) ); } protected: ~pending_result_impl(){} }; template<> struct pending_result_impl : virtual public promise, virtual public pending_result { virtual void handle_result( const fc::string& ) { set_value(); } protected: ~pending_result_impl(){} }; } /** This class is designed to be used like this: @code class my_api { future function( const string& arg, int arg2 ) { _con->invoke( "function", {&arg,&arg2} ); } private: rpc_connection* _con; }; @endcode */ class rpc_connection : virtual public retainable { public: rpc_connection(); rpc_connection( istream& i, ostream& o ); rpc_connection( rpc_connection&& c ); ~rpc_connection(); rpc_connection& operator=(rpc_connection&& m); void init( istream& i, ostream& o ); template future invoke( const fc::string& method, const cptr (¶ms)[N] ) { auto r = new detail::pending_result_impl(); invoke( detail::pending_result::ptr(r), method, N, params ); return promise::ptr( r, true ); } private: void invoke( detail::pending_result::ptr&& p, const fc::string& m, uint16_t nparam, const cptr* param ); class rpc_connection_d* my; }; } } // fc::json #endif // _JSON_RPC_CONNECTION_HPP_