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 }