1 module dls.protocol.jsonrpc; 2 3 import std.json : JSONValue; 4 import std.typecons; 5 6 private enum jsonrpcVersion = "2.0"; 7 private enum eol = "\r\n"; 8 9 abstract class Message 10 { 11 string jsonrpc = jsonrpcVersion; 12 } 13 14 void send(T : Message)(T m) 15 { 16 import dls.util.json : convertToJSON; 17 import std.conv : to; 18 import std.stdio : stdout; 19 import std.utf : toUTF8; 20 21 auto message = convertToJSON(m); 22 auto messageString = message.get().toString(); 23 24 foreach (chunk; ["Content-Length: ", messageString.length.to!string, eol, eol, messageString]) 25 { 26 stdout.rawWrite(chunk.toUTF8()); 27 stdout.flush(); 28 } 29 } 30 31 class RequestMessage : Message 32 { 33 JSONValue id; 34 string method; 35 Nullable!JSONValue params; 36 } 37 38 class ResponseMessage : Message 39 { 40 JSONValue id; 41 Nullable!JSONValue result; 42 Nullable!ResponseError error; 43 } 44 45 class ResponseError 46 { 47 int code; 48 string message; 49 Nullable!JSONValue data; 50 51 static auto fromErrorCode(ErrorCodes errorCode) 52 { 53 auto response = new ResponseError(); 54 response.code = errorCode[0]; 55 response.message = errorCode[1]; 56 return response.nullable; 57 } 58 59 static auto fromException(MessageException e) 60 { 61 auto response = new ResponseError(); 62 response.code = e.code; 63 response.message = e.msg; 64 return response.nullable; 65 } 66 } 67 68 class NotificationMessage : Message 69 { 70 string method; 71 Nullable!JSONValue params; 72 } 73 74 enum ErrorCodes : Tuple!(int, string) 75 { 76 parseError = tuple(-32_700, "Parse error"), 77 invalidRequest = tuple(-32_600, 78 "Invalid Request"), 79 methodNotFound = tuple( 80 -32_601, "Method not found"), 81 invalidParams = tuple(-32_602, 82 "Invalid params"), 83 internalError = tuple(-32_603, 84 "Internal error"), 85 serverNotInitialized = tuple(-32_202, 86 "Server not initialized"), 87 unknownErrorCode = tuple(-32_201, 88 "Unknown error"), 89 requestCancelled = tuple(-32_800, "Request cancelled") 90 } 91 92 class MessageException : Exception 93 { 94 immutable int code; 95 96 this(string message, int code) 97 { 98 super(message); 99 this.code = code; 100 } 101 } 102 103 class CancelParams 104 { 105 JSONValue id; 106 }