yum-mirror/slang
Making it easier to work with shaders
git clone https://git.yummers.dev/yum-mirror/slang
f65d756bf
master
1#ifndef SLANG_COMPILER_CORE_JSON_RPC_CONNECTION_H 2#define SLANG_COMPILER_CORE_JSON_RPC_CONNECTION_H 3 4#include "../../source/core/slang-http.h" 5#include "../../source/core/slang-process.h" 6#include "slang-diagnostic-sink.h" 7#include "slang-json-diagnostics.h" 8#include "slang-json-rpc.h" 9#include "slang-json-value.h" 10#include "slang-source-loc.h" 11#include "slang-test-server-protocol.h" 12 13namespace Slang 14{ 15 16/* A type to handle communication via the JSON-RPC protocol. 17 18Uses Rtti to be able to convert between native and JSON types. 19Provides methods that work on the JSON-RPC protocol, these methods contain 'RPC' and can only 20use the JSON-RPC protocol types. These types will hold items that can vary (like parameters) 21in JSONValue parameters. Code can use regular JSON functions to access/process. 22 23Doing conversions to native types and JSON manually can be a fairly monotonous task. To avoid this 24effort Rtti and JSON<->Rtti conversions can be used. For example sendCall will send a JSON-RPC 25'call' method, with the parameters being converted from some native type. For this to work the type 26T must be determinable via GetRttiType<T>, and T must only contain types that JSON<->Rtti conversion 27supports. 28*/ 29class JSONRPCConnection :public RefObject 30{ 31public : 32enum class CallStyle 33 { 34Default ,///< The default 35Object ,///< Params are passed as an object 36Array ,///< Params are passed as an array 37 }; 38 39/// An init function must be called before use 40/// If a process is implementing the server it should be passed in if the process needs to shut 41/// down if the connection does 42SlangResult init ( 43HTTPPacketConnection * connection , 44CallStyle callStyle = CallStyle ::Default , 45Process * process = nullptr ); 46 47/// Initialize using stdin/out streams for input/output. 48SlangResult initWithStdStreams ( 49CallStyle callStyle = CallStyle ::Default , 50Process * process = nullptr ); 51 52/// Disconnect. May block while server shuts down 53void disconnect (); 54 55SlangResult checkArrayObjectWrap ( 56const JSONValue & srcArgs , 57const RttiInfo * dstArgsRttiInfo , 58void * dstArgs , 59const JSONValue & id ); 60 61/// Convert value to dst. Will write response on fails 62SlangResult toNativeOrSendError ( 63const JSONValue & value , 64const RttiInfo * info , 65void * dst , 66const JSONValue & id ); 67 68template < typename T > 69SlangResult toNativeOrSendError (const JSONValue & value ,T * data ,const JSONValue & id ) 70 { 71return toNativeOrSendError (value ,GetRttiInfo < T > ::get (),data ,id ); 72 } 73 74/// Convert value to dst. 75/// The 'Args' aspect here is to handle Args/Params in JSON-RPC which can be specified as an 76/// array or object style. This call will automatically handle either case. toNativeOrSendError 77/// does not assume the thing being converted is args, and so doesn't allow such a 78/// transformation. Will write error response on failure. 79SlangResult toNativeArgsOrSendError ( 80const JSONValue & srcArgs , 81const RttiInfo * dstArgsRttiInfo , 82void * dstArgs , 83const JSONValue & id ); 84 85template < typename T > 86SlangResult toNativeArgsOrSendError (const JSONValue & srcArgs ,T * dstArgs ,const JSONValue & id ) 87 { 88return toNativeArgsOrSendError (srcArgs ,GetRttiInfo < T > ::get (),dstArgs ,id ); 89 } 90 91template < typename T > 92SlangResult toValidNativeOrSendError (const JSONValue & value ,T * data ,const JSONValue & id ); 93 94/// Send a RPC response (ie should only be one of the JSONRPC classes) 95SlangResult sendRPC (const RttiInfo * info ,const void * data ); 96template < typename T > 97SlangResult sendRPC (const T * data ) 98 { 99return sendRPC (GetRttiInfo < T > ::get (), (const void * )data ); 100 } 101 102/// Send an error 103SlangResult sendError (JSONRPC ::ErrorCode code ,const JSONValue & id ); 104SlangResult sendError ( 105JSONRPC ::ErrorCode errorCode , 106const UnownedStringSlice & msg , 107const JSONValue & id ); 108 109/// Send a 'call' 110/// Uses the default CallStyle as set when init 111SlangResult sendCall ( 112const UnownedStringSlice & method , 113const RttiInfo * argsRttiInfo , 114const void * args , 115const JSONValue & id = JSONValue ()); 116template < typename T > 117SlangResult sendCall ( 118const UnownedStringSlice & method , 119const T * args , 120const JSONValue & id = JSONValue ()) 121 { 122return sendCall (method ,GetRttiInfo < T > ::get (), (const void * )args ,id ); 123 } 124 125/// Send a 'call' 126/// Uses the call mechanism specified in callStyle. It is valid to pass as Default. 127SlangResult sendCall ( 128CallStyle callStyle , 129const UnownedStringSlice & method , 130const RttiInfo * argsRttiInfo , 131const void * args , 132const JSONValue & id = JSONValue ()); 133template < typename T > 134SlangResult sendCall ( 135CallStyle callStyle , 136const UnownedStringSlice & method , 137const T * args , 138const JSONValue & id = JSONValue ()) 139 { 140return sendCall (callStyle ,method ,GetRttiInfo < T > ::get (), (const void * )args ,id ); 141 } 142 143/// Send a call, wheret there are no arguments 144SlangResult sendCall (const UnownedStringSlice & method ,const JSONValue & id = JSONValue ()); 145 146template < typename T > 147SlangResult sendResult (const T * result ,const JSONValue & id ) 148 { 149return sendResult (GetRttiInfo < T > ::get (), (const void * )result ,id ); 150 } 151SlangResult sendResult (const RttiInfo * rttiInfo ,const void * result ,const JSONValue & id ); 152 153/// Try to read a message. Will return if message is not available. 154SlangResult tryReadMessage (); 155 156/// Will block for message/result up to time 157SlangResult waitForResult (Int timeOutInMs = -1 ); 158 159/// If we have an JSON-RPC message m_jsonRoot the root. 160bool hasMessage ()const {return m_jsonRoot .isValid (); } 161 162/// If there is a message returns kind of JSON RPC message 163JSONRPCMessageType getMessageType (); 164 165/// Get JSON-RPC message (ie one of JSONRPC classes) 166template < typename T > 167SlangResult getRPC (T * out ) 168 { 169return getRPC (GetRttiInfo < T > ::get (), (void * )out ); 170 } 171SlangResult getRPC (const RttiInfo * rttiInfo ,void * out ); 172 173/// Get JSON-RPC message (ie one of JSONRPC prefixed classes) 174/// If there is a message and there is a failure, will send an error response 175template < typename T > 176SlangResult getRPCOrSendError (T * out ) 177 { 178return getRPCOrSendError (GetRttiInfo < T > ::get (), (void * )out ); 179 } 180SlangResult getRPCOrSendError (const RttiInfo * rttiInfo ,void * out ); 181 182/// Get message (has to be part of JSONRPCResultResponse) 183template < typename T > 184SlangResult getMessage (T * out ) 185 { 186return getMessage (GetRttiInfo < T > ::get (), (void * )out ); 187 } 188SlangResult getMessage (const RttiInfo * rttiInfo ,void * out ); 189 190/// If there is a message and there is a failure, will send an error response 191template < typename T > 192SlangResult getMessageOrSendError (T * out ) 193 { 194return getMessageOrSendError (GetRttiInfo < T > ::get (), (void * )out ); 195 } 196SlangResult getMessageOrSendError (const RttiInfo * rttiInfo ,void * out ); 197 198/// Clears all the internal buffers (for JSON/Source/etc). 199/// Happens automatically on tryReadMessage/readMessage 200void clearBuffers (); 201 202/// True if this connection is active 203bool isActive (); 204 205/// Get the id of the current message 206JSONValue getCurrentMessageId (); 207 208/// Get the diagnostic sink. Can queue up errors before sending an error 209DiagnosticSink * getSink () {return & m_diagnosticSink ; } 210 211/// Get the container 212JSONContainer * getContainer () {return & m_container ; } 213 214/// Turn a value into a persistant value. This will also remove any sourceLoc under the 215/// assumption that it's highly likely it will become invalid in most usage scenarios. 216PersistentJSONValue getPersistentValue (const JSONValue & value ) 217 { 218return PersistentJSONValue (value ,& m_container ,SourceLoc ()); 219 } 220 221HTTPPacketConnection * getUnderlyingConnection () {return m_connection .Ptr (); } 222 223/// Dtor 224 ~JSONRPCConnection () {disconnect (); } 225 226/// Ctor 227JSONRPCConnection (); 228 229protected : 230CallStyle _getCallStyle (CallStyle callStyle )const 231 { 232return (callStyle == CallStyle ::Default ) ?m_defaultCallStyle :callStyle ; 233 } 234 235RefPtr < Process > m_process ;///< Backing process (optional) 236RefPtr < HTTPPacketConnection > m_connection ;///< The underlying 'transport' connection, whilst 237///< HTTP currently doesn't have to be 238 239DiagnosticSink m_diagnosticSink ;///< Holds any diagnostics typically generated by parsing JSON, 240///< producing JSON from native types 241 242SourceManager 243m_sourceManager ;///< Holds the JSON text for current message/output. Is cleared regularly. 244JSONContainer m_container ;///< Holds the backing memory for jsonMemory, and used when 245///< converting input into output JSON 246 247JSONValue m_jsonRoot ;///< The root JSON value for the currently read message. 248 249CallStyle m_defaultCallStyle = CallStyle ::Array ;///< The default calling style 250 251RttiTypeFuncsMap m_typeMap ; 252 253Int m_terminationTimeOutInMs = 2541 * 1000 ;///< Time to wait for termination response. Default is 1 second 255}; 256 257// --------------------------------------------------------------------------- 258template < typename T > 259SlangResult JSONRPCConnection ::toValidNativeOrSendError ( 260const JSONValue & value , 261T * data , 262const JSONValue & id ) 263{ 264const RttiInfo * rttiInfo = GetRttiInfo < T > ::get (); 265 266SLANG_RETURN_ON_FAIL (toNativeOrSendError (value ,rttiInfo , (void * )data ,id )); 267if (!data -> isValid ()) 268 { 269// If it has a name add validation info 270if (rttiInfo -> isNamed ()) 271 { 272const NamedRttiInfo * namedRttiInfo = static_cast < const NamedRttiInfo *> (rttiInfo ); 273m_diagnosticSink .diagnose ( 274SourceLoc (), 275JSONDiagnostics ::argsAreInvalid , 276namedRttiInfo -> m_name ); 277 } 278 279return sendError (JSONRPC ::ErrorCode ::InvalidRequest ,id ); 280 } 281return SLANG_OK ; 282} 283 284}// namespace Slang 285 286#endif // SLANG_COMPILER_CORE_JSON_RPC_CONNECTION_H