yum-mirror/slang

Making it easier to work with shaders

git clone https://git.yummers.dev/yum-mirror/slang

Ellie Hermaszewskaformatf65d756bf

master
6.0 KiB198 linesraw
1#include "slang-json-rpc.h"
2
3#include "slang-com-helper.h"
4#include "slang-json-native.h"
5
6namespace Slang
7{
8
9// https://www.jsonrpc.org/specification
10
11
12/* static */ const UnownedStringSlice JSONRPC::jsonRpc = UnownedStringSlice::fromLiteral("jsonrpc");
13/* static */ const UnownedStringSlice JSONRPC::jsonRpcVersion =
14    UnownedStringSlice::fromLiteral("2.0");
15/* static */ const UnownedStringSlice JSONRPC::id = UnownedStringSlice::fromLiteral("id");
16
17static const auto g_result = UnownedStringSlice::fromLiteral("result");
18static const auto g_error = UnownedStringSlice::fromLiteral("error");
19static const auto g_method = UnownedStringSlice::fromLiteral("method");
20
21// Add the fields.
22// TODO(JS): This is a little verbose, and could be improved on with something like
23// * Tool that automatically generated from C++ (say via the C++ extractor)
24// * Macro magic to simplify the construction
25static const StructRttiInfo _makeJSONRPCErrorResponse_ErrorRtti()
26{
27    JSONRPCErrorResponse::Error obj;
28    StructRttiBuilder builder(&obj, "JSONRPCErrorResponse::Error", nullptr);
29    builder.addField("code", &obj.code);
30    builder.addField("message", &obj.message);
31    return builder.make();
32}
33/* static */ const StructRttiInfo JSONRPCErrorResponse::Error::g_rttiInfo =
34    _makeJSONRPCErrorResponse_ErrorRtti();
35
36static const StructRttiInfo _makeJSONRPCErrorResponseRtti()
37{
38    JSONRPCErrorResponse obj;
39    StructRttiBuilder builder(&obj, "JSONRPCErrorResponse", nullptr);
40
41    builder.addField("jsonrpc", &obj.jsonrpc);
42    builder.addField("error", &obj.error);
43    builder.addField("data", &obj.data, StructRttiInfo::Flag::Optional);
44    builder.addField("id", &obj.id, StructRttiInfo::Flag::Optional);
45
46    return builder.make();
47}
48/* static */ const StructRttiInfo JSONRPCErrorResponse::g_rttiInfo =
49    _makeJSONRPCErrorResponseRtti();
50
51static const StructRttiInfo _makeJSONRPCCallResponseRtti()
52{
53    JSONRPCCall obj;
54    StructRttiBuilder builder(&obj, "JSONRPCCall", nullptr);
55
56    builder.addField("jsonrpc", &obj.jsonrpc);
57    builder.addField("method", &obj.method);
58    builder.addField("params", &obj.params, StructRttiInfo::Flag::Optional);
59    builder.addField("id", &obj.id, StructRttiInfo::Flag::Optional);
60    builder.ignoreUnknownFields();
61
62    return builder.make();
63}
64/* static */ const StructRttiInfo JSONRPCCall::g_rttiInfo = _makeJSONRPCCallResponseRtti();
65
66static const StructRttiInfo _makeJSONResultResponseResponseRtti()
67{
68    JSONResultResponse obj;
69    StructRttiBuilder builder(&obj, "JSONResultResponse", nullptr);
70
71    builder.addField("jsonrpc", &obj.jsonrpc);
72    builder.addField("result", &obj.result);
73    builder.addField("id", &obj.id, StructRttiInfo::Flag::Optional);
74
75    return builder.make();
76}
77/* static */ const StructRttiInfo JSONResultResponse::g_rttiInfo =
78    _makeJSONResultResponseResponseRtti();
79
80/* static */ JSONRPCMessageType JSONRPCUtil::getMessageType(
81    JSONContainer* container,
82    const JSONValue& value)
83{
84    if (value.getKind() == JSONValue::Kind::Object)
85    {
86        const JSONKey resultKey = container->findKey(g_result);
87        const JSONKey errorKey = container->findKey(g_error);
88        const JSONKey methodKey = container->findKey(g_method);
89
90        auto pairs = container->getObject(value);
91
92        for (const auto& pair : pairs)
93        {
94            if (pair.key == resultKey)
95            {
96                return JSONRPCMessageType::Result;
97            }
98            else if (pair.key == errorKey)
99            {
100                return JSONRPCMessageType::Error;
101            }
102            else if (pair.key == methodKey)
103            {
104                return JSONRPCMessageType::Call;
105            }
106        }
107    }
108
109    return JSONRPCMessageType::Invalid;
110}
111
112/* static */ SlangResult JSONRPCUtil::parseJSON(
113    const UnownedStringSlice& slice,
114    JSONContainer* container,
115    DiagnosticSink* sink,
116    JSONValue& outValue)
117{
118    SourceManager* sourceManager = sink->getSourceManager();
119
120    // Now need to parse as JSON
121    String contents(slice);
122    SourceFile* sourceFile =
123        sourceManager->createSourceFileWithString(PathInfo::makeUnknown(), contents);
124    SourceView* sourceView = sourceManager->createSourceView(sourceFile, nullptr, SourceLoc());
125
126    JSONLexer lexer;
127    lexer.init(sourceView, sink);
128
129    JSONBuilder builder(container);
130
131    JSONParser parser;
132    SLANG_RETURN_ON_FAIL(parser.parse(&lexer, sourceView, &builder, sink));
133
134    outValue = builder.getRootValue();
135    return SLANG_OK;
136}
137
138/* static */ SlangResult JSONRPCUtil::convertToNative(
139    JSONContainer* container,
140    const JSONValue& value,
141    DiagnosticSink* sink,
142    const RttiInfo* rttiInfo,
143    void* out)
144{
145    auto typeMap = JSONNativeUtil::getTypeFuncsMap();
146
147    JSONToNativeConverter converter(container, &typeMap, sink);
148    SLANG_RETURN_ON_FAIL(converter.convert(value, rttiInfo, out));
149    return SLANG_OK;
150}
151
152/* static */ SlangResult JSONRPCUtil::convertToJSON(
153    const RttiInfo* rttiInfo,
154    const void* in,
155    DiagnosticSink* sink,
156    StringBuilder& out)
157{
158    SourceManager* sourceManager = sink->getSourceManager();
159    JSONContainer container(sourceManager);
160
161    auto typeMap = JSONNativeUtil::getTypeFuncsMap();
162
163    NativeToJSONConverter converter(&container, &typeMap, sink);
164
165    JSONValue value;
166    SLANG_RETURN_ON_FAIL(converter.convert(rttiInfo, in, value));
167
168    // Convert into a string
169    JSONWriter writer(JSONWriter::IndentationStyle::Allman);
170    container.traverseRecursively(value, &writer);
171
172    out = writer.getBuilder();
173    return SLANG_OK;
174}
175
176/* static */ JSONValue JSONRPCUtil::getId(JSONContainer* container, const JSONValue& root)
177{
178    if (root.getKind() == JSONValue::Kind::Object)
179    {
180        const JSONKey key = container->findKey(JSONRPC::id);
181
182        if (key != JSONKey(0))
183        {
184            auto obj = container->getObject(root);
185            Index index = obj.findFirstIndex(
186                [key](const JSONKeyValue& pair) -> bool { return pair.key == key; });
187
188            if (index >= 0)
189            {
190                return obj[index].value;
191            }
192        }
193    }
194    return JSONValue();
195}
196
197
198} // namespace Slang