skir-cc-gen 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +335 -0
- package/client/BUILD.bazel +33 -0
- package/client/MODULE.bazel +11 -0
- package/client/MODULE.bazel.lock +225 -0
- package/client/skir.cc +2687 -0
- package/client/skir.h +2946 -0
- package/client/skir.testing.h +282 -0
- package/dist/enum_field.d.ts +33 -0
- package/dist/enum_field.d.ts.map +1 -0
- package/dist/enum_field.js +85 -0
- package/dist/enum_field.js.map +1 -0
- package/dist/enum_variant.d.ts +31 -0
- package/dist/enum_variant.d.ts.map +1 -0
- package/dist/enum_variant.js +85 -0
- package/dist/enum_variant.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1627 -0
- package/dist/index.js.map +1 -0
- package/dist/keywords.d.ts +2 -0
- package/dist/keywords.d.ts.map +1 -0
- package/dist/keywords.js +101 -0
- package/dist/keywords.js.map +1 -0
- package/dist/recursivity_resolver.d.ts +58 -0
- package/dist/recursivity_resolver.d.ts.map +1 -0
- package/dist/recursivity_resolver.js +142 -0
- package/dist/recursivity_resolver.js.map +1 -0
- package/dist/type_speller.d.ts +17 -0
- package/dist/type_speller.d.ts.map +1 -0
- package/dist/type_speller.js +87 -0
- package/dist/type_speller.js.map +1 -0
- package/package.json +55 -0
- package/src/enum_variant.ts +126 -0
- package/src/index.ts +2089 -0
- package/src/keywords.ts +100 -0
- package/src/recursivity_resolver.ts +161 -0
- package/src/type_speller.ts +100 -0
package/client/skir.cc
ADDED
|
@@ -0,0 +1,2687 @@
|
|
|
1
|
+
#include "skir.h"
|
|
2
|
+
|
|
3
|
+
#include <algorithm>
|
|
4
|
+
#include <cstdint>
|
|
5
|
+
#include <cstring>
|
|
6
|
+
#include <limits>
|
|
7
|
+
#include <string>
|
|
8
|
+
#include <type_traits>
|
|
9
|
+
#include <utility>
|
|
10
|
+
#include <variant>
|
|
11
|
+
|
|
12
|
+
#include "absl/log/die_if_null.h"
|
|
13
|
+
#include "absl/log/log.h"
|
|
14
|
+
#include "absl/status/status.h"
|
|
15
|
+
#include "absl/strings/ascii.h"
|
|
16
|
+
#include "absl/strings/escaping.h"
|
|
17
|
+
#include "absl/strings/numbers.h"
|
|
18
|
+
#include "absl/strings/str_cat.h"
|
|
19
|
+
#include "absl/strings/str_join.h"
|
|
20
|
+
#include "absl/strings/str_split.h"
|
|
21
|
+
#include "absl/strings/string_view.h"
|
|
22
|
+
#include "absl/time/time.h"
|
|
23
|
+
|
|
24
|
+
namespace skir_internal {
|
|
25
|
+
namespace {
|
|
26
|
+
|
|
27
|
+
inline const char* cast(const uint8_t* ptr) { return (const char*)ptr; }
|
|
28
|
+
|
|
29
|
+
inline const uint8_t* cast(const char* ptr) { return (const uint8_t*)ptr; }
|
|
30
|
+
|
|
31
|
+
inline int64_t ClampUnixMillis(int64_t unix_millis) {
|
|
32
|
+
return std::min<int64_t>(std::max<int64_t>(unix_millis, -8640000000000000),
|
|
33
|
+
8640000000000000);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
static constexpr char kHexDigits[] = "0123456789ABCDEF";
|
|
37
|
+
|
|
38
|
+
enum class NullTerminated { kFalse = false, kTrue = true };
|
|
39
|
+
|
|
40
|
+
namespace copy_utf8_codepoint {
|
|
41
|
+
struct ToString {
|
|
42
|
+
template <typename Char>
|
|
43
|
+
inline static void Push(Char c, std::string& out) {
|
|
44
|
+
out += static_cast<char>(c);
|
|
45
|
+
}
|
|
46
|
+
inline static void PopN(size_t n, std::string& out) {
|
|
47
|
+
out.resize(out.length() - n);
|
|
48
|
+
}
|
|
49
|
+
inline static void OnError(const char* pos, const char* end,
|
|
50
|
+
size_t continuation_bytes, std::string& out) {
|
|
51
|
+
// Push the replacement character: � (u+FFFD)
|
|
52
|
+
out += "�";
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
struct ToDebugString {
|
|
57
|
+
template <typename Char>
|
|
58
|
+
inline static void Push(Char c, std::string& out) {
|
|
59
|
+
out += static_cast<char>(c);
|
|
60
|
+
}
|
|
61
|
+
inline static void PopN(size_t n, std::string& out) {
|
|
62
|
+
out.resize(out.length() - n);
|
|
63
|
+
}
|
|
64
|
+
inline static void OnError(const char* pos, const char* end,
|
|
65
|
+
size_t continuation_bytes, std::string& out) {
|
|
66
|
+
// Escape all the chars in the invalid sequence.
|
|
67
|
+
for (const char* back_pos = pos - continuation_bytes - 1; back_pos < pos;
|
|
68
|
+
++back_pos) {
|
|
69
|
+
const uint8_t back_byte = static_cast<uint8_t>(*back_pos);
|
|
70
|
+
out += {'\\', 'x', kHexDigits[(back_byte >> 4) & 0x0F],
|
|
71
|
+
kHexDigits[back_byte & 0x0F]};
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
struct ToByteSink {
|
|
77
|
+
template <typename Char>
|
|
78
|
+
inline static void Push(Char c, ByteSink& out) {
|
|
79
|
+
out.PushUnsafe(static_cast<uint8_t>(c));
|
|
80
|
+
}
|
|
81
|
+
inline static void PopN(size_t n, ByteSink& out) { out.PopN(n); }
|
|
82
|
+
inline static void OnError(const char* pos, const char* end,
|
|
83
|
+
size_t continuation_bytes, ByteSink& out) {
|
|
84
|
+
// Push the replacement character: � (u+FFFD). It's possible that we need
|
|
85
|
+
// more capacity.
|
|
86
|
+
out.Prepare((end - pos) + 3);
|
|
87
|
+
out.PushUnsafe(0xEF);
|
|
88
|
+
out.PushUnsafe(0xBF);
|
|
89
|
+
out.PushUnsafe(0xBD);
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
} // namespace copy_utf8_codepoint
|
|
93
|
+
|
|
94
|
+
// Copy the non-ASCII-7 codepoint at pos - 1 to out.
|
|
95
|
+
// The first_byte is expected to be greater than 127.
|
|
96
|
+
template <typename Sink, NullTerminated kNullTerminated, typename Out>
|
|
97
|
+
inline void CopyUtf8Codepoint(uint8_t first_byte, const char*& pos,
|
|
98
|
+
const char* end, Out& out) {
|
|
99
|
+
// The first byte of the UTF-8 sequence for a non-ASCII-7 codepoint,
|
|
100
|
+
// assuming the input string is a well-formed UTF-8 string.
|
|
101
|
+
|
|
102
|
+
// Push byte and all the continuation bytes that follow. If the input
|
|
103
|
+
// string happens to not be a well-formed UTF-8 string, we'll remove the
|
|
104
|
+
// chars we have pushed.
|
|
105
|
+
Sink::Push(first_byte, out);
|
|
106
|
+
|
|
107
|
+
// Total number of continuation bytes actually read.
|
|
108
|
+
size_t continuation_bytes = 0;
|
|
109
|
+
|
|
110
|
+
// From https://github.com/chansen/c-utf8-valid/blob/master/utf8_valid.h
|
|
111
|
+
uint32_t v = first_byte;
|
|
112
|
+
|
|
113
|
+
for (;;) {
|
|
114
|
+
if (kNullTerminated == NullTerminated::kFalse && pos == end) {
|
|
115
|
+
break;
|
|
116
|
+
}
|
|
117
|
+
const uint8_t continuation_byte = static_cast<uint8_t>(*pos);
|
|
118
|
+
if ((continuation_byte & 0xC0) == 0x80) {
|
|
119
|
+
Sink::Push(continuation_byte, out);
|
|
120
|
+
++continuation_bytes;
|
|
121
|
+
v = (v << 8) | continuation_byte;
|
|
122
|
+
++pos;
|
|
123
|
+
} else {
|
|
124
|
+
// Not a continuation byte.
|
|
125
|
+
break;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Validate the UTF-8 sequence we just read.
|
|
130
|
+
if ((first_byte & 0xE0) == 0xC0) {
|
|
131
|
+
// 1 continuation byte expected
|
|
132
|
+
if (continuation_bytes != 1) goto utf8_error;
|
|
133
|
+
// Ensure that the top 4 bits is not zero
|
|
134
|
+
v = v & 0x1E00;
|
|
135
|
+
if (v == 0) goto utf8_error;
|
|
136
|
+
} else if ((first_byte & 0xF0) == 0xE0) {
|
|
137
|
+
// 2 continuation bytes expected
|
|
138
|
+
if (continuation_bytes != 2) goto utf8_error;
|
|
139
|
+
// Ensure that the top 5 bits is not zero and not a surrogate
|
|
140
|
+
v = v & 0x0F2000;
|
|
141
|
+
if (v == 0 || v == 0x0D2000) goto utf8_error;
|
|
142
|
+
} else if ((first_byte & 0xF8) == 0xF0) {
|
|
143
|
+
// 3 continuation bytes expected
|
|
144
|
+
if (continuation_bytes != 3) goto utf8_error;
|
|
145
|
+
// Ensure that the top 5 bits is not zero and not out of range
|
|
146
|
+
v = v & 0x07300000;
|
|
147
|
+
if (v == 0 || v > 0x04000000) goto utf8_error;
|
|
148
|
+
} else {
|
|
149
|
+
goto utf8_error;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return;
|
|
153
|
+
|
|
154
|
+
utf8_error:
|
|
155
|
+
// Remove the last (continuation_bytes + 1) chars from the output.
|
|
156
|
+
Sink::PopN(continuation_bytes + 1, out);
|
|
157
|
+
Sink::OnError(pos, end, continuation_bytes, out);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
template <NullTerminated kNullTerminated>
|
|
161
|
+
inline void EscapeJsonString(const char* pos, const char* end,
|
|
162
|
+
std::string& out) {
|
|
163
|
+
while (kNullTerminated == NullTerminated::kTrue || pos < end) {
|
|
164
|
+
const uint8_t byte = static_cast<uint8_t>(*pos++);
|
|
165
|
+
if (byte < 0x80) {
|
|
166
|
+
if (byte < 0x20) {
|
|
167
|
+
// A non-printable character.
|
|
168
|
+
switch (byte) {
|
|
169
|
+
case '\0':
|
|
170
|
+
// \0 may indicate the end of the string, but it can also be part of
|
|
171
|
+
// the string's contents.
|
|
172
|
+
if (kNullTerminated == NullTerminated::kTrue && pos > end) {
|
|
173
|
+
// The end of the input string was reached.
|
|
174
|
+
return;
|
|
175
|
+
} else {
|
|
176
|
+
out += {'\\', 'u', '0', '0', '0', '0'};
|
|
177
|
+
break;
|
|
178
|
+
}
|
|
179
|
+
case '\b':
|
|
180
|
+
out += {'\\', 'b'};
|
|
181
|
+
break;
|
|
182
|
+
case '\f':
|
|
183
|
+
out += {'\\', 'f'};
|
|
184
|
+
break;
|
|
185
|
+
case '\n':
|
|
186
|
+
out += {'\\', 'n'};
|
|
187
|
+
break;
|
|
188
|
+
case '\r':
|
|
189
|
+
out += {'\\', 'r'};
|
|
190
|
+
break;
|
|
191
|
+
case '\t':
|
|
192
|
+
out += {'\\', 't'};
|
|
193
|
+
break;
|
|
194
|
+
default:
|
|
195
|
+
out += {'\\',
|
|
196
|
+
'u',
|
|
197
|
+
'0',
|
|
198
|
+
'0',
|
|
199
|
+
kHexDigits[(byte >> 4) & 0x0F],
|
|
200
|
+
kHexDigits[byte & 0x0F]};
|
|
201
|
+
}
|
|
202
|
+
} else {
|
|
203
|
+
// A printable character.
|
|
204
|
+
switch (byte) {
|
|
205
|
+
case '"':
|
|
206
|
+
out += {'\\', '"'};
|
|
207
|
+
break;
|
|
208
|
+
case '\\':
|
|
209
|
+
out += {'\\', '\\'};
|
|
210
|
+
break;
|
|
211
|
+
default:
|
|
212
|
+
out += byte;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
} else {
|
|
216
|
+
CopyUtf8Codepoint<copy_utf8_codepoint::ToString, kNullTerminated>(
|
|
217
|
+
byte, pos, end, out);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
inline void EscapeJsonString(const std::string& input, std::string& out) {
|
|
223
|
+
const char* c_str = input.c_str();
|
|
224
|
+
EscapeJsonString<NullTerminated::kTrue>(c_str, c_str + input.length(), out);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
inline void CopyUtf8String(const std::string& input, ByteSink& out) {
|
|
228
|
+
const char* input_pos = input.c_str();
|
|
229
|
+
const char* input_end = input_pos + input.length();
|
|
230
|
+
uint8_t* out_pos = out.pos();
|
|
231
|
+
for (;;) {
|
|
232
|
+
const int8_t c = static_cast<int8_t>(*(input_pos++));
|
|
233
|
+
if (c <= 0) {
|
|
234
|
+
if (c == 0) {
|
|
235
|
+
// The input string is guaranteed to end with \0, but \0 can also be
|
|
236
|
+
// found within the string.
|
|
237
|
+
if (input_pos > input_end) {
|
|
238
|
+
// The end of the input string was reached.
|
|
239
|
+
out.set_pos(out_pos);
|
|
240
|
+
return;
|
|
241
|
+
} else {
|
|
242
|
+
*(out_pos++) = 0;
|
|
243
|
+
out.PushUnsafe(0);
|
|
244
|
+
}
|
|
245
|
+
} else {
|
|
246
|
+
out.set_pos(out_pos);
|
|
247
|
+
CopyUtf8Codepoint<copy_utf8_codepoint::ToByteSink,
|
|
248
|
+
NullTerminated::kTrue>(c, input_pos, input_end, out);
|
|
249
|
+
out_pos = out.pos();
|
|
250
|
+
}
|
|
251
|
+
} else {
|
|
252
|
+
*(out_pos++) = c;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
inline void EscapeDebugString(const std::string& input, std::string& out) {
|
|
258
|
+
const char* pos = input.c_str();
|
|
259
|
+
const char* input_end = pos + input.length() + 1;
|
|
260
|
+
for (;;) {
|
|
261
|
+
const uint8_t byte = static_cast<uint8_t>(*(pos++));
|
|
262
|
+
if (byte < 0x80) {
|
|
263
|
+
if (byte < 0x20) {
|
|
264
|
+
// A non-printable character.
|
|
265
|
+
switch (byte) {
|
|
266
|
+
case '\0':
|
|
267
|
+
// The input string is guaranteed to end with \0, but \0 can also be
|
|
268
|
+
// found within the string.
|
|
269
|
+
if (pos == input_end) {
|
|
270
|
+
// The end of the input string was reached.
|
|
271
|
+
return;
|
|
272
|
+
} else {
|
|
273
|
+
out += {'\\', '0'};
|
|
274
|
+
break;
|
|
275
|
+
}
|
|
276
|
+
case '\a':
|
|
277
|
+
out += {'\\', 'a'};
|
|
278
|
+
break;
|
|
279
|
+
case '\b':
|
|
280
|
+
out += {'\\', 'b'};
|
|
281
|
+
break;
|
|
282
|
+
case '\f':
|
|
283
|
+
out += {'\\', 'f'};
|
|
284
|
+
break;
|
|
285
|
+
case '\n':
|
|
286
|
+
out += {'\\', 'n'};
|
|
287
|
+
break;
|
|
288
|
+
case '\r':
|
|
289
|
+
out += {'\\', 'r'};
|
|
290
|
+
break;
|
|
291
|
+
case '\t':
|
|
292
|
+
out += {'\\', 't'};
|
|
293
|
+
break;
|
|
294
|
+
case '\v':
|
|
295
|
+
out += {'\\', 'v'};
|
|
296
|
+
break;
|
|
297
|
+
default:
|
|
298
|
+
out += {'\\', 'x', kHexDigits[(byte >> 4) & 0x0F],
|
|
299
|
+
kHexDigits[byte & 0x0F]};
|
|
300
|
+
}
|
|
301
|
+
} else {
|
|
302
|
+
// A printable character.
|
|
303
|
+
switch (byte) {
|
|
304
|
+
case '"':
|
|
305
|
+
out += {'\\', '"'};
|
|
306
|
+
break;
|
|
307
|
+
case '\\':
|
|
308
|
+
out += {'\\', '\\'};
|
|
309
|
+
break;
|
|
310
|
+
default:
|
|
311
|
+
out += byte;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
} else {
|
|
315
|
+
CopyUtf8Codepoint<copy_utf8_codepoint::ToDebugString,
|
|
316
|
+
NullTerminated::kTrue>(byte, pos, input_end, out);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
inline bool IsDigit(char c) { return '0' <= c && c <= '9'; }
|
|
322
|
+
|
|
323
|
+
int HexDigitToInt(char c) {
|
|
324
|
+
if ('0' <= c && c <= '9') {
|
|
325
|
+
return c - '0';
|
|
326
|
+
} else if ('A' <= c && c <= 'F') {
|
|
327
|
+
return c - 'A' + 10;
|
|
328
|
+
} else if ('a' <= c && c <= 'f') {
|
|
329
|
+
return c - 'a' + 10;
|
|
330
|
+
}
|
|
331
|
+
return -1;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
inline absl::Status ParseIntStatus(const char* str, const char* str_end) {
|
|
335
|
+
return *str_end == '\0' && str_end != str
|
|
336
|
+
? absl::OkStatus()
|
|
337
|
+
: absl::UnknownError("can't parse number from JSON string");
|
|
338
|
+
}
|
|
339
|
+
template <typename number>
|
|
340
|
+
inline absl::Status TryParseNumber(const char* str, number& out) {
|
|
341
|
+
int64_t n = 0;
|
|
342
|
+
const absl::Status status = TryParseNumber(str, n);
|
|
343
|
+
out = static_cast<number>(n);
|
|
344
|
+
return status;
|
|
345
|
+
}
|
|
346
|
+
template <>
|
|
347
|
+
inline absl::Status TryParseNumber<long>(const char* str, long& out) {
|
|
348
|
+
char* str_end = nullptr;
|
|
349
|
+
out = std::strtol(str, &str_end, 10);
|
|
350
|
+
return ParseIntStatus(str, str_end);
|
|
351
|
+
}
|
|
352
|
+
template <>
|
|
353
|
+
inline absl::Status TryParseNumber<long long>(const char* str, long long& out) {
|
|
354
|
+
char* str_end = nullptr;
|
|
355
|
+
out = std::strtoll(str, &str_end, 10);
|
|
356
|
+
return ParseIntStatus(str, str_end);
|
|
357
|
+
}
|
|
358
|
+
template <>
|
|
359
|
+
inline absl::Status TryParseNumber<unsigned long>(const char* str,
|
|
360
|
+
unsigned long& out) {
|
|
361
|
+
char* str_end = nullptr;
|
|
362
|
+
out = std::strtoul(str, &str_end, 10);
|
|
363
|
+
return ParseIntStatus(str, str_end);
|
|
364
|
+
}
|
|
365
|
+
template <>
|
|
366
|
+
inline absl::Status TryParseNumber<unsigned long long>(
|
|
367
|
+
const char* str, unsigned long long& out) {
|
|
368
|
+
char* str_end = nullptr;
|
|
369
|
+
out = std::strtoull(str, &str_end, 10);
|
|
370
|
+
return ParseIntStatus(str, str_end);
|
|
371
|
+
}
|
|
372
|
+
template <typename number>
|
|
373
|
+
inline bool TryParseSpecialNumber(const std::string& str, number& out) {
|
|
374
|
+
constexpr bool kIsFloatOrDouble =
|
|
375
|
+
std::is_same<number, float>::value || std::is_same<number, double>::value;
|
|
376
|
+
if (kIsFloatOrDouble) {
|
|
377
|
+
if (str == "NaN") {
|
|
378
|
+
out = std::numeric_limits<number>::quiet_NaN();
|
|
379
|
+
return true;
|
|
380
|
+
} else if (str == "Infinity") {
|
|
381
|
+
out = std::numeric_limits<number>::infinity();
|
|
382
|
+
return true;
|
|
383
|
+
} else if (str == "-Infinity") {
|
|
384
|
+
out = -std::numeric_limits<number>::infinity();
|
|
385
|
+
return true;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
return false;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
template <char kSign>
|
|
392
|
+
inline JsonTokenType ParseFractionalPart(char c, const char* token_start,
|
|
393
|
+
JsonTokenizer::State& s,
|
|
394
|
+
uint64_t integral_part) {
|
|
395
|
+
switch (c) {
|
|
396
|
+
case '.': {
|
|
397
|
+
if (!IsDigit(s.NextCharOrNull())) {
|
|
398
|
+
s.PushErrorAtPosition("digit");
|
|
399
|
+
return JsonTokenType::kError;
|
|
400
|
+
}
|
|
401
|
+
while (IsDigit(c = s.NextCharOrNull())) {
|
|
402
|
+
}
|
|
403
|
+
break;
|
|
404
|
+
}
|
|
405
|
+
case 'E':
|
|
406
|
+
case 'e': {
|
|
407
|
+
c = s.NextCharOrNull();
|
|
408
|
+
goto parse_exponential_part;
|
|
409
|
+
}
|
|
410
|
+
default:
|
|
411
|
+
if (integral_part == 0) {
|
|
412
|
+
return JsonTokenType::kZero;
|
|
413
|
+
}
|
|
414
|
+
if (kSign == '-') {
|
|
415
|
+
s.int_value = -integral_part;
|
|
416
|
+
return JsonTokenType::kSignedInteger;
|
|
417
|
+
} else {
|
|
418
|
+
s.uint_value = integral_part;
|
|
419
|
+
return JsonTokenType::kUnsignedInteger;
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
switch (c) {
|
|
423
|
+
case 'E':
|
|
424
|
+
case 'e': {
|
|
425
|
+
c = s.NextCharOrNull();
|
|
426
|
+
break;
|
|
427
|
+
}
|
|
428
|
+
default:
|
|
429
|
+
goto parse_float;
|
|
430
|
+
}
|
|
431
|
+
parse_exponential_part:
|
|
432
|
+
switch (c) {
|
|
433
|
+
case '+':
|
|
434
|
+
case '-':
|
|
435
|
+
c = s.NextCharOrNull();
|
|
436
|
+
}
|
|
437
|
+
if (!IsDigit(c)) {
|
|
438
|
+
s.PushErrorAtPosition("digit");
|
|
439
|
+
return JsonTokenType::kError;
|
|
440
|
+
}
|
|
441
|
+
while (IsDigit(s.NextCharOrNull())) {
|
|
442
|
+
}
|
|
443
|
+
parse_float:
|
|
444
|
+
const absl::string_view substr(token_start, s.pos - token_start);
|
|
445
|
+
if (!absl::SimpleAtod(substr, &s.float_value)) {
|
|
446
|
+
LOG(ERROR) << "can't parse \"" << substr << "\" as float";
|
|
447
|
+
}
|
|
448
|
+
return JsonTokenType::kFloat;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
inline bool ParseUnicodeEscapeSequence(JsonTokenizer::State& s,
|
|
452
|
+
std::string& out) {
|
|
453
|
+
int codepoint = 0;
|
|
454
|
+
if (s.chars_left() < 4) return false;
|
|
455
|
+
for (int i = 0; i < 4; ++i) {
|
|
456
|
+
codepoint = (codepoint << 4) | HexDigitToInt(s.pos[i]);
|
|
457
|
+
if (codepoint < 0) {
|
|
458
|
+
return false;
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
s.pos += 4;
|
|
462
|
+
|
|
463
|
+
if (0xD800 <= codepoint && codepoint <= 0xDBFF) {
|
|
464
|
+
// We got a high surrogate. Read the low surrogate.
|
|
465
|
+
if (s.chars_left() < 6 || s.pos[0] != '\\' || s.pos[1] != 'u') {
|
|
466
|
+
return false;
|
|
467
|
+
}
|
|
468
|
+
int lo_code_unit = 0;
|
|
469
|
+
for (int i = 2; i < 6; ++i) {
|
|
470
|
+
lo_code_unit = (lo_code_unit << 4) | HexDigitToInt(s.pos[i]);
|
|
471
|
+
if (lo_code_unit < 0) {
|
|
472
|
+
return false;
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
s.pos += 6;
|
|
476
|
+
codepoint =
|
|
477
|
+
((codepoint - 0xD800) << 10) + (lo_code_unit - 0xDC00) + 0x10000;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
// Now write the codepoint in UTF-8.
|
|
481
|
+
if (codepoint <= 0x7F) {
|
|
482
|
+
out += static_cast<char>(codepoint);
|
|
483
|
+
} else if (codepoint <= 0x7FF) {
|
|
484
|
+
out += 0xC0 | (codepoint >> 6);
|
|
485
|
+
out += 0x80 | (codepoint & 0x3F);
|
|
486
|
+
} else if (codepoint <= 0xFFFF) {
|
|
487
|
+
if (0xD800 <= codepoint && codepoint <= 0xDFFF) {
|
|
488
|
+
return false;
|
|
489
|
+
}
|
|
490
|
+
out += 0xE0 | (codepoint >> 12);
|
|
491
|
+
out += 0x80 | ((codepoint >> 6) & 0x3F);
|
|
492
|
+
out += 0x80 | (codepoint & 0x3F);
|
|
493
|
+
} else if (codepoint <= 0x10FFFF) {
|
|
494
|
+
// Four-byte encoding
|
|
495
|
+
out += 0xF0 | (codepoint >> 18);
|
|
496
|
+
out += 0x80 | ((codepoint >> 12) & 0x3F);
|
|
497
|
+
out += 0x80 | ((codepoint >> 6) & 0x3F);
|
|
498
|
+
out += 0x80 | (codepoint & 0x3F);
|
|
499
|
+
} else {
|
|
500
|
+
return false;
|
|
501
|
+
}
|
|
502
|
+
return true;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
inline JsonTokenType ParseString(JsonTokenizer::State& s) {
|
|
506
|
+
// pos[0] == '"'
|
|
507
|
+
++s.pos;
|
|
508
|
+
std::string value;
|
|
509
|
+
for (;;) {
|
|
510
|
+
if (s.pos == s.end) {
|
|
511
|
+
s.PushError("error while parsing JSON: unterminated string literal");
|
|
512
|
+
return JsonTokenType::kError;
|
|
513
|
+
}
|
|
514
|
+
const uint8_t byte = static_cast<uint8_t>(*s.pos++);
|
|
515
|
+
if (byte < 0x80) {
|
|
516
|
+
// ASCII-7 codepoint.
|
|
517
|
+
switch (byte) {
|
|
518
|
+
case '"': {
|
|
519
|
+
s.string_value = std::move(value);
|
|
520
|
+
return JsonTokenType::kString;
|
|
521
|
+
}
|
|
522
|
+
case '\\': {
|
|
523
|
+
if (s.pos == s.end) {
|
|
524
|
+
s.PushErrorAtPosition("escape sequence");
|
|
525
|
+
return JsonTokenType::kError;
|
|
526
|
+
}
|
|
527
|
+
const char escape_char = *s.pos++;
|
|
528
|
+
switch (escape_char) {
|
|
529
|
+
case '"':
|
|
530
|
+
case '\'':
|
|
531
|
+
case '\\':
|
|
532
|
+
case '/': {
|
|
533
|
+
value += escape_char;
|
|
534
|
+
break;
|
|
535
|
+
}
|
|
536
|
+
case 'b': {
|
|
537
|
+
value += '\b';
|
|
538
|
+
break;
|
|
539
|
+
}
|
|
540
|
+
case 'f': {
|
|
541
|
+
value += '\f';
|
|
542
|
+
break;
|
|
543
|
+
}
|
|
544
|
+
case 'n': {
|
|
545
|
+
value += '\n';
|
|
546
|
+
break;
|
|
547
|
+
}
|
|
548
|
+
case 'r': {
|
|
549
|
+
value += '\r';
|
|
550
|
+
break;
|
|
551
|
+
}
|
|
552
|
+
case 't': {
|
|
553
|
+
value += '\t';
|
|
554
|
+
break;
|
|
555
|
+
}
|
|
556
|
+
case 'u': {
|
|
557
|
+
if (!ParseUnicodeEscapeSequence(s, value)) {
|
|
558
|
+
s.PushError(
|
|
559
|
+
"error while parsing JSON: invalid unicode escape "
|
|
560
|
+
"sequence");
|
|
561
|
+
return JsonTokenType::kError;
|
|
562
|
+
}
|
|
563
|
+
break;
|
|
564
|
+
}
|
|
565
|
+
default: {
|
|
566
|
+
s.PushError("error while parsing JSON: invalid escape sequence");
|
|
567
|
+
return JsonTokenType::kError;
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
break;
|
|
571
|
+
}
|
|
572
|
+
default: {
|
|
573
|
+
value += byte;
|
|
574
|
+
break;
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
} else {
|
|
578
|
+
CopyUtf8Codepoint<copy_utf8_codepoint::ToString, NullTerminated::kFalse>(
|
|
579
|
+
byte, s.pos, s.end, value);
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
inline JsonTokenType NextImpl(JsonTokenizer::State& state) {
|
|
585
|
+
for (;;) {
|
|
586
|
+
if (state.pos == state.end) {
|
|
587
|
+
return JsonTokenType::kStrEnd;
|
|
588
|
+
}
|
|
589
|
+
switch (*state.pos) {
|
|
590
|
+
case '\t':
|
|
591
|
+
case '\n':
|
|
592
|
+
case '\r': {
|
|
593
|
+
++state.pos;
|
|
594
|
+
break;
|
|
595
|
+
}
|
|
596
|
+
case ' ': {
|
|
597
|
+
// Very common for whitespaces to come together.
|
|
598
|
+
while (*(++state.pos) == ' ') {
|
|
599
|
+
}
|
|
600
|
+
break;
|
|
601
|
+
}
|
|
602
|
+
case '[':
|
|
603
|
+
case ']':
|
|
604
|
+
case '{':
|
|
605
|
+
case '}':
|
|
606
|
+
case ',':
|
|
607
|
+
case ':': {
|
|
608
|
+
state.token_begin = state.pos;
|
|
609
|
+
return static_cast<JsonTokenType>(*state.pos++);
|
|
610
|
+
}
|
|
611
|
+
case 't': {
|
|
612
|
+
state.token_begin = state.pos;
|
|
613
|
+
if (state.chars_left() < 4 || state.pos[1] != 'r' ||
|
|
614
|
+
state.pos[2] != 'u' || state.pos[3] != 'e') {
|
|
615
|
+
state.PushErrorAtPosition("JSON token");
|
|
616
|
+
return JsonTokenType::kError;
|
|
617
|
+
}
|
|
618
|
+
state.pos += 4;
|
|
619
|
+
return JsonTokenType::kTrue;
|
|
620
|
+
}
|
|
621
|
+
case 'f': {
|
|
622
|
+
state.token_begin = state.pos;
|
|
623
|
+
if (state.chars_left() < 5 || state.pos[1] != 'a' ||
|
|
624
|
+
state.pos[2] != 'l' || state.pos[3] != 's' || state.pos[4] != 'e') {
|
|
625
|
+
state.PushErrorAtPosition("JSON token");
|
|
626
|
+
return JsonTokenType::kError;
|
|
627
|
+
}
|
|
628
|
+
state.pos += 5;
|
|
629
|
+
return JsonTokenType::kFalse;
|
|
630
|
+
}
|
|
631
|
+
case 'n': {
|
|
632
|
+
state.token_begin = state.pos;
|
|
633
|
+
if (state.chars_left() < 4 || state.pos[1] != 'u' ||
|
|
634
|
+
state.pos[2] != 'l' || state.pos[3] != 'l') {
|
|
635
|
+
state.PushErrorAtPosition("JSON token");
|
|
636
|
+
return JsonTokenType::kError;
|
|
637
|
+
}
|
|
638
|
+
state.pos += 4;
|
|
639
|
+
return JsonTokenType::kNull;
|
|
640
|
+
}
|
|
641
|
+
case '-': {
|
|
642
|
+
state.token_begin = state.pos;
|
|
643
|
+
const char* token_start = state.pos;
|
|
644
|
+
char digit = state.NextCharOrNull();
|
|
645
|
+
if (!IsDigit(digit)) {
|
|
646
|
+
state.PushErrorAtPosition("digit");
|
|
647
|
+
return JsonTokenType::kError;
|
|
648
|
+
}
|
|
649
|
+
uint64_t integral_part = digit - '0';
|
|
650
|
+
while (IsDigit(digit = state.NextCharOrNull())) {
|
|
651
|
+
integral_part = integral_part * 10 + (digit - '0');
|
|
652
|
+
}
|
|
653
|
+
return ParseFractionalPart<'-'>(digit, token_start, state,
|
|
654
|
+
integral_part);
|
|
655
|
+
}
|
|
656
|
+
case '0':
|
|
657
|
+
case '1':
|
|
658
|
+
case '2':
|
|
659
|
+
case '3':
|
|
660
|
+
case '4':
|
|
661
|
+
case '5':
|
|
662
|
+
case '6':
|
|
663
|
+
case '7':
|
|
664
|
+
case '8':
|
|
665
|
+
case '9': {
|
|
666
|
+
state.token_begin = state.pos;
|
|
667
|
+
const char* token_start = state.pos;
|
|
668
|
+
char digit = *token_start;
|
|
669
|
+
uint64_t integral_part = digit - '0';
|
|
670
|
+
while (IsDigit(digit = state.NextCharOrNull())) {
|
|
671
|
+
integral_part = integral_part * 10 + (digit - '0');
|
|
672
|
+
}
|
|
673
|
+
return ParseFractionalPart<'+'>(digit, token_start, state,
|
|
674
|
+
integral_part);
|
|
675
|
+
}
|
|
676
|
+
case '"': {
|
|
677
|
+
state.token_begin = state.pos;
|
|
678
|
+
return ParseString(state);
|
|
679
|
+
}
|
|
680
|
+
case '\0': {
|
|
681
|
+
return JsonTokenType::kStrEnd;
|
|
682
|
+
}
|
|
683
|
+
default: {
|
|
684
|
+
state.PushErrorAtPosition("JSON token");
|
|
685
|
+
return JsonTokenType::kError;
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
template <typename number>
|
|
692
|
+
inline void ParseJsonNumber(JsonTokenizer& tokenizer, number& out) {
|
|
693
|
+
switch (tokenizer.state().token_type) {
|
|
694
|
+
case JsonTokenType::kTrue:
|
|
695
|
+
tokenizer.Next();
|
|
696
|
+
out = static_cast<number>(true);
|
|
697
|
+
break;
|
|
698
|
+
case JsonTokenType::kFalse:
|
|
699
|
+
case JsonTokenType::kZero:
|
|
700
|
+
tokenizer.Next();
|
|
701
|
+
// Zero is the default for any numeric type.
|
|
702
|
+
break;
|
|
703
|
+
case JsonTokenType::kUnsignedInteger:
|
|
704
|
+
out = static_cast<number>(tokenizer.state().uint_value);
|
|
705
|
+
tokenizer.Next();
|
|
706
|
+
break;
|
|
707
|
+
case JsonTokenType::kSignedInteger:
|
|
708
|
+
out = static_cast<number>(tokenizer.state().int_value);
|
|
709
|
+
tokenizer.Next();
|
|
710
|
+
break;
|
|
711
|
+
case JsonTokenType::kFloat:
|
|
712
|
+
out = static_cast<number>(tokenizer.state().float_value);
|
|
713
|
+
tokenizer.Next();
|
|
714
|
+
break;
|
|
715
|
+
case JsonTokenType::kString: {
|
|
716
|
+
const std::string& string_value = tokenizer.state().string_value;
|
|
717
|
+
if (TryParseSpecialNumber(string_value, out)) {
|
|
718
|
+
tokenizer.Next();
|
|
719
|
+
break;
|
|
720
|
+
}
|
|
721
|
+
if (false) {
|
|
722
|
+
// To remove the "unused function" warnings.
|
|
723
|
+
(void)TryParseNumber<long>;
|
|
724
|
+
(void)TryParseNumber<long long>;
|
|
725
|
+
(void)TryParseNumber<unsigned long>;
|
|
726
|
+
(void)TryParseNumber<unsigned long long>;
|
|
727
|
+
}
|
|
728
|
+
const absl::Status status = TryParseNumber(string_value.c_str(), out);
|
|
729
|
+
if (!status.ok()) {
|
|
730
|
+
tokenizer.mutable_state().status = status;
|
|
731
|
+
}
|
|
732
|
+
tokenizer.Next();
|
|
733
|
+
break;
|
|
734
|
+
}
|
|
735
|
+
default:
|
|
736
|
+
tokenizer.mutable_state().PushUnexpectedTokenError("number");
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
inline void AppendWiredUint8(uint8_t value, ByteSink& out) {
|
|
741
|
+
out.Push(235, value);
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
template <int kWire = 232>
|
|
745
|
+
inline void AppendWiredUint16(uint16_t value, ByteSink& out) {
|
|
746
|
+
static_assert(kWire == 232 || kWire == 236);
|
|
747
|
+
out.Push(kWire, value & 0xFF, value >> 8);
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
template <int kWire = 233>
|
|
751
|
+
inline void AppendWiredUint32(uint32_t value, ByteSink& out) {
|
|
752
|
+
static_assert(kWire == 233 || kWire == 237 || kWire == 240);
|
|
753
|
+
out.Push(kWire, value & 0xFF, value >> 8, value >> 16, value >> 24);
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
inline void AppendWiredInt32(int32_t value, ByteSink& out) {
|
|
757
|
+
AppendWiredUint32<237>(static_cast<uint32_t>(value), out);
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
inline void AppendWiredFloat32(float value, ByteSink& out) {
|
|
761
|
+
union {
|
|
762
|
+
float f;
|
|
763
|
+
uint32_t i;
|
|
764
|
+
} u;
|
|
765
|
+
u.f = value;
|
|
766
|
+
AppendWiredUint32<240>(u.i, out);
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
template <int kWire = 234>
|
|
770
|
+
inline void AppendWiredUint64(uint64_t value, ByteSink& out) {
|
|
771
|
+
static_assert(kWire == 234 || kWire == 238 || kWire == 239 || kWire == 241);
|
|
772
|
+
out.Push(kWire, value & 0xFF, value >> 8, value >> 16, value >> 24,
|
|
773
|
+
value >> 32, value >> 40, value >> 48, value >> 56);
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
template <int kWire = 238>
|
|
777
|
+
inline void AppendWiredInt64(int64_t value, ByteSink& out) {
|
|
778
|
+
AppendWiredUint64<kWire>(static_cast<uint64_t>(value), out);
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
inline void AppendWiredFloat64(double value, ByteSink& out) {
|
|
782
|
+
union {
|
|
783
|
+
double f;
|
|
784
|
+
uint64_t i;
|
|
785
|
+
} u;
|
|
786
|
+
u.f = value;
|
|
787
|
+
AppendWiredUint64<241>(u.i, out);
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
template <int kWire>
|
|
791
|
+
inline void AppendLengthPrefix(size_t length, ByteSink& out) {
|
|
792
|
+
static_assert(kWire == 245 || kWire == 250);
|
|
793
|
+
constexpr bool kPrepareLengthBytes = (kWire == 245);
|
|
794
|
+
if (kWire == 250 && length < 4) {
|
|
795
|
+
out.Prepare(1 + (kPrepareLengthBytes ? length : 0));
|
|
796
|
+
out.PushUnsafe((kWire - 4) + length);
|
|
797
|
+
} else if (length < 232) {
|
|
798
|
+
out.Prepare(2 + (kPrepareLengthBytes ? length : 0));
|
|
799
|
+
out.PushUnsafe(kWire, length);
|
|
800
|
+
} else if (length < 65536) {
|
|
801
|
+
out.Prepare(4 + (kPrepareLengthBytes ? length : 0));
|
|
802
|
+
out.PushUnsafe(kWire, 232, length & 0xFF, length >> 8);
|
|
803
|
+
} else if (length < 4294967296) {
|
|
804
|
+
out.Prepare(6 + (kPrepareLengthBytes ? length : 0));
|
|
805
|
+
out.PushUnsafe(kWire, 233, length & 0xFF, length >> 8, length >> 16,
|
|
806
|
+
length >> 24);
|
|
807
|
+
} else {
|
|
808
|
+
LOG(FATAL) << "overflow error while encoding skir value; length: "
|
|
809
|
+
<< length;
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
inline uint16_t ReadUint16(ByteSource& source) {
|
|
814
|
+
const uint8_t* pos = source.pos;
|
|
815
|
+
const uint16_t result =
|
|
816
|
+
static_cast<uint16_t>(pos[0]) | static_cast<uint16_t>(pos[1] << 8);
|
|
817
|
+
source.pos += 2;
|
|
818
|
+
return result;
|
|
819
|
+
};
|
|
820
|
+
|
|
821
|
+
inline uint32_t ReadUint32(ByteSource& source) {
|
|
822
|
+
const uint8_t* pos = source.pos;
|
|
823
|
+
const uint32_t result = static_cast<uint32_t>(pos[0]) | //
|
|
824
|
+
static_cast<uint32_t>(pos[1]) << 8 | //
|
|
825
|
+
static_cast<uint32_t>(pos[2]) << 16 | //
|
|
826
|
+
static_cast<uint32_t>(pos[3]) << 24;
|
|
827
|
+
source.pos = pos + 4;
|
|
828
|
+
return result;
|
|
829
|
+
};
|
|
830
|
+
|
|
831
|
+
inline uint64_t ReadUint64(ByteSource& source) {
|
|
832
|
+
const uint8_t* pos = source.pos;
|
|
833
|
+
const uint64_t result = static_cast<uint64_t>(pos[0]) | //
|
|
834
|
+
static_cast<uint64_t>(pos[1]) << 8 | //
|
|
835
|
+
static_cast<uint64_t>(pos[2]) << 16 | //
|
|
836
|
+
static_cast<uint64_t>(pos[3]) << 24 | //
|
|
837
|
+
static_cast<uint64_t>(pos[4]) << 32 | //
|
|
838
|
+
static_cast<uint64_t>(pos[5]) << 40 | //
|
|
839
|
+
static_cast<uint64_t>(pos[6]) << 48 | //
|
|
840
|
+
static_cast<uint64_t>(pos[7]) << 56;
|
|
841
|
+
source.pos += 8;
|
|
842
|
+
return result;
|
|
843
|
+
};
|
|
844
|
+
|
|
845
|
+
template <typename number>
|
|
846
|
+
inline void ParseNumberWithWire(uint8_t wire, ByteSource& source, number& out) {
|
|
847
|
+
constexpr bool kIsFloatOrDouble =
|
|
848
|
+
std::is_same<number, float>::value || std::is_same<number, double>::value;
|
|
849
|
+
if (wire < 232) {
|
|
850
|
+
if (wire != 0) {
|
|
851
|
+
out = static_cast<number>(wire);
|
|
852
|
+
}
|
|
853
|
+
return;
|
|
854
|
+
}
|
|
855
|
+
switch (static_cast<uint8_t>(wire - 232)) {
|
|
856
|
+
case 0: {
|
|
857
|
+
// 232
|
|
858
|
+
if (source.num_bytes_left() < 2) {
|
|
859
|
+
return source.RaiseError();
|
|
860
|
+
}
|
|
861
|
+
out = static_cast<number>(ReadUint16(source));
|
|
862
|
+
break;
|
|
863
|
+
}
|
|
864
|
+
case 1: {
|
|
865
|
+
// 233
|
|
866
|
+
if (source.num_bytes_left() < 4) {
|
|
867
|
+
return source.RaiseError();
|
|
868
|
+
}
|
|
869
|
+
out = static_cast<number>(ReadUint32(source));
|
|
870
|
+
break;
|
|
871
|
+
}
|
|
872
|
+
case 2: {
|
|
873
|
+
// 234
|
|
874
|
+
if (source.num_bytes_left() < 8) {
|
|
875
|
+
return source.RaiseError();
|
|
876
|
+
}
|
|
877
|
+
out = static_cast<number>(ReadUint64(source));
|
|
878
|
+
break;
|
|
879
|
+
}
|
|
880
|
+
case 3: {
|
|
881
|
+
// 235
|
|
882
|
+
if (source.num_bytes_left() < 1) {
|
|
883
|
+
return source.RaiseError();
|
|
884
|
+
}
|
|
885
|
+
out = static_cast<number>(*(source.pos++) - 256);
|
|
886
|
+
break;
|
|
887
|
+
}
|
|
888
|
+
case 4: {
|
|
889
|
+
// 236
|
|
890
|
+
if (source.num_bytes_left() < 2) {
|
|
891
|
+
return source.RaiseError();
|
|
892
|
+
}
|
|
893
|
+
out = static_cast<number>(ReadUint16(source) - 65536);
|
|
894
|
+
break;
|
|
895
|
+
}
|
|
896
|
+
case 5: {
|
|
897
|
+
// 237
|
|
898
|
+
if (source.num_bytes_left() < 4) {
|
|
899
|
+
return source.RaiseError();
|
|
900
|
+
}
|
|
901
|
+
out = static_cast<number>(static_cast<int32_t>(ReadUint32(source)));
|
|
902
|
+
break;
|
|
903
|
+
}
|
|
904
|
+
case 6:
|
|
905
|
+
case 7: {
|
|
906
|
+
// 238, 239
|
|
907
|
+
if (source.num_bytes_left() < 8) {
|
|
908
|
+
return source.RaiseError();
|
|
909
|
+
}
|
|
910
|
+
out = static_cast<number>(static_cast<int64_t>(ReadUint64(source)));
|
|
911
|
+
break;
|
|
912
|
+
}
|
|
913
|
+
case 8: {
|
|
914
|
+
// 240
|
|
915
|
+
if (source.num_bytes_left() < 4) {
|
|
916
|
+
return source.RaiseError();
|
|
917
|
+
}
|
|
918
|
+
union {
|
|
919
|
+
float f;
|
|
920
|
+
uint32_t i;
|
|
921
|
+
} u;
|
|
922
|
+
u.i = ReadUint32(source);
|
|
923
|
+
if (!kIsFloatOrDouble && !std::isfinite(u.f)) {
|
|
924
|
+
return source.RaiseError();
|
|
925
|
+
}
|
|
926
|
+
out = static_cast<number>(u.f);
|
|
927
|
+
break;
|
|
928
|
+
}
|
|
929
|
+
case 9: {
|
|
930
|
+
// 241
|
|
931
|
+
if (source.num_bytes_left() < 8) {
|
|
932
|
+
return source.RaiseError();
|
|
933
|
+
}
|
|
934
|
+
union {
|
|
935
|
+
double f;
|
|
936
|
+
uint64_t i;
|
|
937
|
+
} u;
|
|
938
|
+
u.i = ReadUint64(source);
|
|
939
|
+
if (!kIsFloatOrDouble && !std::isfinite(u.f)) {
|
|
940
|
+
return source.RaiseError();
|
|
941
|
+
}
|
|
942
|
+
out = static_cast<number>(u.f);
|
|
943
|
+
break;
|
|
944
|
+
}
|
|
945
|
+
default: {
|
|
946
|
+
source.RaiseError();
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
|
|
951
|
+
template <typename number>
|
|
952
|
+
inline void ParseNumber(ByteSource& source, number& out) {
|
|
953
|
+
return ParseNumberWithWire(source.ReadWire(), source, out);
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
inline void SkipValues(ByteSource& source, size_t n) {
|
|
957
|
+
for (size_t i = 0; i < n; ++i) {
|
|
958
|
+
if (source.error) return;
|
|
959
|
+
SkipValue(source);
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
struct ReflectionStructOrEnum {
|
|
964
|
+
std::string kind;
|
|
965
|
+
std::string id;
|
|
966
|
+
std::string doc;
|
|
967
|
+
skir::keyed_items<::skir::reflection::Field, ::skir::reflection::get_name>
|
|
968
|
+
fields;
|
|
969
|
+
skir::keyed_items<::skir::reflection::Variant, ::skir::reflection::get_name>
|
|
970
|
+
variants;
|
|
971
|
+
std::vector<int> removed_numbers;
|
|
972
|
+
};
|
|
973
|
+
|
|
974
|
+
template <typename FieldOrVariant>
|
|
975
|
+
void AppendFieldOrVariant(const FieldOrVariant& input, ReadableJson& out) {
|
|
976
|
+
JsonObjectWriter(&out)
|
|
977
|
+
.Write("name", input.name)
|
|
978
|
+
.WriteEvenIfDefault("number", input.number)
|
|
979
|
+
.Write("type", input.type)
|
|
980
|
+
.Write("doc", input.doc);
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
template <typename FieldOrVariant>
|
|
984
|
+
void ParseFieldOrVariant(JsonTokenizer& tokenizer, FieldOrVariant& out) {
|
|
985
|
+
if (tokenizer.state().token_type == JsonTokenType::kLeftCurlyBracket) {
|
|
986
|
+
static const auto* kParser =
|
|
987
|
+
(new StructJsonObjectParser<FieldOrVariant>())
|
|
988
|
+
->AddField("name", &FieldOrVariant::name)
|
|
989
|
+
->AddField("number", &FieldOrVariant::number)
|
|
990
|
+
->AddField("type", &FieldOrVariant::type)
|
|
991
|
+
->AddField("doc", &FieldOrVariant::doc);
|
|
992
|
+
kParser->Parse(tokenizer, out);
|
|
993
|
+
return;
|
|
994
|
+
}
|
|
995
|
+
tokenizer.mutable_state().PushUnexpectedTokenError("'{'");
|
|
996
|
+
}
|
|
997
|
+
} // namespace
|
|
998
|
+
|
|
999
|
+
JsonTokenType JsonTokenizer::Next() {
|
|
1000
|
+
if (!state_.status.ok()) return JsonTokenType::kError;
|
|
1001
|
+
return state_.token_type = NextImpl(state_);
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
void JsonTokenizer::State::PushError(absl::string_view message) {
|
|
1005
|
+
// Only keep the first error pushed.
|
|
1006
|
+
if (status.ok()) {
|
|
1007
|
+
status = absl::UnknownError(message);
|
|
1008
|
+
token_type = JsonTokenType::kError;
|
|
1009
|
+
}
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
void JsonTokenizer::State::PushErrorAtPosition(absl::string_view expected) {
|
|
1013
|
+
const size_t position = pos - begin;
|
|
1014
|
+
PushError(absl::StrCat("error while parsing JSON at position ", position,
|
|
1015
|
+
": expected: ", expected));
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
void JsonTokenizer::State::PushUnexpectedTokenError(
|
|
1019
|
+
absl::string_view expected) {
|
|
1020
|
+
std::string actual_str;
|
|
1021
|
+
switch (token_type) {
|
|
1022
|
+
case JsonTokenType::kError:
|
|
1023
|
+
// Should not happen
|
|
1024
|
+
actual_str = "ERROR";
|
|
1025
|
+
break;
|
|
1026
|
+
case JsonTokenType::kTrue:
|
|
1027
|
+
actual_str = "true";
|
|
1028
|
+
break;
|
|
1029
|
+
case JsonTokenType::kFalse:
|
|
1030
|
+
actual_str = "false";
|
|
1031
|
+
break;
|
|
1032
|
+
case JsonTokenType::kNull:
|
|
1033
|
+
actual_str = "null";
|
|
1034
|
+
break;
|
|
1035
|
+
case JsonTokenType::kZero:
|
|
1036
|
+
case JsonTokenType::kUnsignedInteger:
|
|
1037
|
+
case JsonTokenType::kSignedInteger:
|
|
1038
|
+
case JsonTokenType::kFloat:
|
|
1039
|
+
actual_str = "number";
|
|
1040
|
+
break;
|
|
1041
|
+
case JsonTokenType::kString:
|
|
1042
|
+
actual_str = "string";
|
|
1043
|
+
break;
|
|
1044
|
+
case JsonTokenType::kLeftSquareBracket:
|
|
1045
|
+
case JsonTokenType::kRightSquareBracket:
|
|
1046
|
+
case JsonTokenType::kLeftCurlyBracket:
|
|
1047
|
+
case JsonTokenType::kRightCurlyBracket:
|
|
1048
|
+
case JsonTokenType::kComma:
|
|
1049
|
+
case JsonTokenType::kColon:
|
|
1050
|
+
actual_str = {'\'', static_cast<char>(token_type), '\''};
|
|
1051
|
+
break;
|
|
1052
|
+
case JsonTokenType::kStrEnd:
|
|
1053
|
+
actual_str = "end";
|
|
1054
|
+
}
|
|
1055
|
+
PushError(absl::StrCat("error while parsing JSON: expected: ", expected,
|
|
1056
|
+
"; found: ", actual_str));
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
void SkipValue(JsonTokenizer& tokenizer) {
|
|
1060
|
+
// A stack of (']' | '}'). The element on the top of the stack corresponds to
|
|
1061
|
+
// the next expected closing bracket.
|
|
1062
|
+
std::string open_brackets;
|
|
1063
|
+
while (true) {
|
|
1064
|
+
if (!open_brackets.empty() && open_brackets.back() == '}') {
|
|
1065
|
+
if (tokenizer.state().token_type != JsonTokenType::kString) {
|
|
1066
|
+
tokenizer.mutable_state().PushUnexpectedTokenError("string");
|
|
1067
|
+
return;
|
|
1068
|
+
}
|
|
1069
|
+
if (tokenizer.Next() != JsonTokenType::kColon) {
|
|
1070
|
+
tokenizer.mutable_state().PushUnexpectedTokenError("':'");
|
|
1071
|
+
return;
|
|
1072
|
+
}
|
|
1073
|
+
tokenizer.Next();
|
|
1074
|
+
}
|
|
1075
|
+
switch (tokenizer.state().token_type) {
|
|
1076
|
+
case JsonTokenType::kTrue:
|
|
1077
|
+
case JsonTokenType::kFalse:
|
|
1078
|
+
case JsonTokenType::kNull:
|
|
1079
|
+
case JsonTokenType::kZero:
|
|
1080
|
+
case JsonTokenType::kUnsignedInteger:
|
|
1081
|
+
case JsonTokenType::kSignedInteger:
|
|
1082
|
+
case JsonTokenType::kFloat:
|
|
1083
|
+
case JsonTokenType::kString: {
|
|
1084
|
+
tokenizer.Next();
|
|
1085
|
+
break;
|
|
1086
|
+
}
|
|
1087
|
+
case JsonTokenType::kLeftSquareBracket: {
|
|
1088
|
+
if (tokenizer.Next() == JsonTokenType::kRightSquareBracket) {
|
|
1089
|
+
tokenizer.Next();
|
|
1090
|
+
break;
|
|
1091
|
+
}
|
|
1092
|
+
open_brackets += ']';
|
|
1093
|
+
continue;
|
|
1094
|
+
}
|
|
1095
|
+
case JsonTokenType::kLeftCurlyBracket: {
|
|
1096
|
+
if (tokenizer.Next() == JsonTokenType::kRightCurlyBracket) {
|
|
1097
|
+
tokenizer.Next();
|
|
1098
|
+
break;
|
|
1099
|
+
}
|
|
1100
|
+
open_brackets += '}';
|
|
1101
|
+
continue;
|
|
1102
|
+
}
|
|
1103
|
+
default: {
|
|
1104
|
+
tokenizer.mutable_state().PushUnexpectedTokenError("value");
|
|
1105
|
+
return;
|
|
1106
|
+
}
|
|
1107
|
+
}
|
|
1108
|
+
while (!open_brackets.empty() &&
|
|
1109
|
+
open_brackets.back() ==
|
|
1110
|
+
static_cast<char>(tokenizer.state().token_type)) {
|
|
1111
|
+
tokenizer.Next();
|
|
1112
|
+
open_brackets.pop_back();
|
|
1113
|
+
}
|
|
1114
|
+
if (open_brackets.empty()) return;
|
|
1115
|
+
if (tokenizer.state().token_type == JsonTokenType::kComma) {
|
|
1116
|
+
tokenizer.Next();
|
|
1117
|
+
} else {
|
|
1118
|
+
tokenizer.mutable_state().PushUnexpectedTokenError("','");
|
|
1119
|
+
return;
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
|
|
1124
|
+
JsonArrayReader::JsonArrayReader(JsonTokenizer* tokenizer)
|
|
1125
|
+
: tokenizer_(*ABSL_DIE_IF_NULL(tokenizer)) {}
|
|
1126
|
+
|
|
1127
|
+
bool JsonArrayReader::NextElement() {
|
|
1128
|
+
if (zero_state_) {
|
|
1129
|
+
zero_state_ = false;
|
|
1130
|
+
if (tokenizer_.Next() == JsonTokenType::kRightSquareBracket) {
|
|
1131
|
+
tokenizer_.Next();
|
|
1132
|
+
return false;
|
|
1133
|
+
} else {
|
|
1134
|
+
return true;
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1137
|
+
switch (tokenizer_.state().token_type) {
|
|
1138
|
+
case JsonTokenType::kComma: {
|
|
1139
|
+
tokenizer_.Next();
|
|
1140
|
+
return true;
|
|
1141
|
+
}
|
|
1142
|
+
case JsonTokenType::kRightSquareBracket: {
|
|
1143
|
+
tokenizer_.Next();
|
|
1144
|
+
return false;
|
|
1145
|
+
}
|
|
1146
|
+
default: {
|
|
1147
|
+
tokenizer_.mutable_state().PushUnexpectedTokenError("','");
|
|
1148
|
+
return false;
|
|
1149
|
+
}
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
1152
|
+
|
|
1153
|
+
JsonObjectReader::JsonObjectReader(JsonTokenizer* tokenizer)
|
|
1154
|
+
: tokenizer_(*ABSL_DIE_IF_NULL(tokenizer)) {}
|
|
1155
|
+
|
|
1156
|
+
bool JsonObjectReader::NextEntry() {
|
|
1157
|
+
if (zero_state_) {
|
|
1158
|
+
tokenizer_.Next();
|
|
1159
|
+
}
|
|
1160
|
+
switch (tokenizer_.state().token_type) {
|
|
1161
|
+
case JsonTokenType::kRightCurlyBracket: {
|
|
1162
|
+
tokenizer_.Next();
|
|
1163
|
+
return false;
|
|
1164
|
+
}
|
|
1165
|
+
case JsonTokenType::kComma: {
|
|
1166
|
+
if (zero_state_) {
|
|
1167
|
+
tokenizer_.mutable_state().PushUnexpectedTokenError("string");
|
|
1168
|
+
return false;
|
|
1169
|
+
}
|
|
1170
|
+
tokenizer_.Next();
|
|
1171
|
+
break;
|
|
1172
|
+
}
|
|
1173
|
+
default: {
|
|
1174
|
+
if (!zero_state_) {
|
|
1175
|
+
tokenizer_.mutable_state().PushUnexpectedTokenError("','");
|
|
1176
|
+
return false;
|
|
1177
|
+
}
|
|
1178
|
+
zero_state_ = false;
|
|
1179
|
+
}
|
|
1180
|
+
}
|
|
1181
|
+
if (tokenizer_.state().token_type != JsonTokenType::kString) {
|
|
1182
|
+
tokenizer_.mutable_state().PushUnexpectedTokenError("string");
|
|
1183
|
+
return false;
|
|
1184
|
+
}
|
|
1185
|
+
name_ = std::move(tokenizer_.mutable_state().string_value);
|
|
1186
|
+
if (tokenizer_.Next() != JsonTokenType::kColon) {
|
|
1187
|
+
tokenizer_.mutable_state().PushUnexpectedTokenError("':'");
|
|
1188
|
+
return false;
|
|
1189
|
+
}
|
|
1190
|
+
tokenizer_.Next();
|
|
1191
|
+
return true;
|
|
1192
|
+
}
|
|
1193
|
+
|
|
1194
|
+
void SkipValue(ByteSource& source) {
|
|
1195
|
+
for (size_t num_values_left = 1; num_values_left > 0; --num_values_left) {
|
|
1196
|
+
const uint8_t wire = source.ReadWire();
|
|
1197
|
+
if (source.error) return;
|
|
1198
|
+
if (wire < 232) continue;
|
|
1199
|
+
switch (static_cast<uint8_t>(wire - 232)) {
|
|
1200
|
+
case 0:
|
|
1201
|
+
case 4: {
|
|
1202
|
+
// 232, 236
|
|
1203
|
+
if (!source.TryAdvance(2)) return;
|
|
1204
|
+
break;
|
|
1205
|
+
}
|
|
1206
|
+
case 1:
|
|
1207
|
+
case 5:
|
|
1208
|
+
case 8: {
|
|
1209
|
+
// 233, 237, 240
|
|
1210
|
+
if (!source.TryAdvance(4)) return;
|
|
1211
|
+
break;
|
|
1212
|
+
}
|
|
1213
|
+
case 2:
|
|
1214
|
+
case 6:
|
|
1215
|
+
case 7:
|
|
1216
|
+
case 9: {
|
|
1217
|
+
// 234, 238, 239, 241
|
|
1218
|
+
if (!source.TryAdvance(8)) return;
|
|
1219
|
+
break;
|
|
1220
|
+
}
|
|
1221
|
+
case 3: {
|
|
1222
|
+
// 235
|
|
1223
|
+
if (!source.TryAdvance(1)) return;
|
|
1224
|
+
break;
|
|
1225
|
+
}
|
|
1226
|
+
case 11:
|
|
1227
|
+
case 13: {
|
|
1228
|
+
// 243, 245
|
|
1229
|
+
uint32_t length = 0;
|
|
1230
|
+
ParseNumber(source, length);
|
|
1231
|
+
if (!source.TryAdvance(length)) return;
|
|
1232
|
+
break;
|
|
1233
|
+
}
|
|
1234
|
+
case 15:
|
|
1235
|
+
case 16:
|
|
1236
|
+
case 17: {
|
|
1237
|
+
// 247-249
|
|
1238
|
+
num_values_left += wire - 246;
|
|
1239
|
+
break;
|
|
1240
|
+
}
|
|
1241
|
+
case 18: {
|
|
1242
|
+
// 250
|
|
1243
|
+
uint32_t array_len = 0;
|
|
1244
|
+
ParseNumber(source, array_len);
|
|
1245
|
+
num_values_left += array_len;
|
|
1246
|
+
break;
|
|
1247
|
+
}
|
|
1248
|
+
case 19:
|
|
1249
|
+
case 20:
|
|
1250
|
+
case 21:
|
|
1251
|
+
case 22: {
|
|
1252
|
+
// 251-254
|
|
1253
|
+
++num_values_left;
|
|
1254
|
+
break;
|
|
1255
|
+
}
|
|
1256
|
+
default:
|
|
1257
|
+
break;
|
|
1258
|
+
}
|
|
1259
|
+
}
|
|
1260
|
+
}
|
|
1261
|
+
|
|
1262
|
+
void AppendArrayPrefix(size_t length, ByteSink& out) {
|
|
1263
|
+
if (length < 4) {
|
|
1264
|
+
out.Push(246 + length);
|
|
1265
|
+
} else {
|
|
1266
|
+
AppendLengthPrefix<250>(length, out);
|
|
1267
|
+
}
|
|
1268
|
+
}
|
|
1269
|
+
|
|
1270
|
+
void ParseArrayPrefix(ByteSource& source, uint32_t& length) {
|
|
1271
|
+
const uint8_t byte = source.ReadWire();
|
|
1272
|
+
switch (static_cast<uint8_t>(byte - 246)) {
|
|
1273
|
+
case 0: {
|
|
1274
|
+
// 246
|
|
1275
|
+
break;
|
|
1276
|
+
}
|
|
1277
|
+
case 1: {
|
|
1278
|
+
// 247
|
|
1279
|
+
length = 1;
|
|
1280
|
+
break;
|
|
1281
|
+
}
|
|
1282
|
+
case 2: {
|
|
1283
|
+
// 248
|
|
1284
|
+
length = 2;
|
|
1285
|
+
break;
|
|
1286
|
+
}
|
|
1287
|
+
case 3: {
|
|
1288
|
+
// 249
|
|
1289
|
+
length = 3;
|
|
1290
|
+
break;
|
|
1291
|
+
}
|
|
1292
|
+
case 4: {
|
|
1293
|
+
// 250
|
|
1294
|
+
ParseNumber(source, length);
|
|
1295
|
+
break;
|
|
1296
|
+
}
|
|
1297
|
+
case 10: {
|
|
1298
|
+
// 0
|
|
1299
|
+
break;
|
|
1300
|
+
}
|
|
1301
|
+
default: {
|
|
1302
|
+
source.RaiseError();
|
|
1303
|
+
}
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1306
|
+
|
|
1307
|
+
void BoolAdapter::Parse(JsonTokenizer& tokenizer, bool& out) {
|
|
1308
|
+
ParseJsonNumber(tokenizer, out);
|
|
1309
|
+
}
|
|
1310
|
+
|
|
1311
|
+
void BoolAdapter::Parse(ByteSource& source, bool& out) {
|
|
1312
|
+
ParseNumber(source, out);
|
|
1313
|
+
}
|
|
1314
|
+
|
|
1315
|
+
void Int32Adapter::Append(int32_t input, ByteSink& out) {
|
|
1316
|
+
if (input < 0) {
|
|
1317
|
+
if (input >= -256) {
|
|
1318
|
+
AppendWiredUint8(input + 256, out);
|
|
1319
|
+
} else if (input >= -65536) {
|
|
1320
|
+
AppendWiredUint16<236>(input + 65536, out);
|
|
1321
|
+
} else {
|
|
1322
|
+
AppendWiredInt32(input, out);
|
|
1323
|
+
}
|
|
1324
|
+
} else if (input < 232) {
|
|
1325
|
+
out.Push(input);
|
|
1326
|
+
} else if (input < 65536) {
|
|
1327
|
+
AppendWiredUint16(input, out);
|
|
1328
|
+
} else {
|
|
1329
|
+
AppendWiredUint32(input, out);
|
|
1330
|
+
}
|
|
1331
|
+
}
|
|
1332
|
+
|
|
1333
|
+
void Int32Adapter::Parse(JsonTokenizer& tokenizer, int32_t& out) {
|
|
1334
|
+
ParseJsonNumber(tokenizer, out);
|
|
1335
|
+
}
|
|
1336
|
+
|
|
1337
|
+
void Int32Adapter::Parse(ByteSource& source, int32_t& out) {
|
|
1338
|
+
ParseNumber(source, out);
|
|
1339
|
+
}
|
|
1340
|
+
|
|
1341
|
+
void Int64Adapter::Append(int64_t input, ByteSink& out) {
|
|
1342
|
+
if (input < 0) {
|
|
1343
|
+
if (input >= -256) {
|
|
1344
|
+
AppendWiredUint8(input + 256, out);
|
|
1345
|
+
} else if (input >= -65536) {
|
|
1346
|
+
AppendWiredUint16<236>(input + 65536, out);
|
|
1347
|
+
} else if (input >= -2147483648) {
|
|
1348
|
+
AppendWiredInt32(input, out);
|
|
1349
|
+
} else {
|
|
1350
|
+
AppendWiredInt64(input, out);
|
|
1351
|
+
}
|
|
1352
|
+
} else if (input < 232) {
|
|
1353
|
+
out.Push(input);
|
|
1354
|
+
} else if (input < 65536) {
|
|
1355
|
+
AppendWiredUint16(input, out);
|
|
1356
|
+
} else if (input < 4294967296) {
|
|
1357
|
+
AppendWiredUint32(input, out);
|
|
1358
|
+
} else {
|
|
1359
|
+
AppendWiredInt64(input, out);
|
|
1360
|
+
}
|
|
1361
|
+
}
|
|
1362
|
+
|
|
1363
|
+
void Int64Adapter::Parse(JsonTokenizer& tokenizer, int64_t& out) {
|
|
1364
|
+
ParseJsonNumber(tokenizer, out);
|
|
1365
|
+
}
|
|
1366
|
+
|
|
1367
|
+
void Int64Adapter::Parse(ByteSource& source, int64_t& out) {
|
|
1368
|
+
ParseNumber(source, out);
|
|
1369
|
+
}
|
|
1370
|
+
|
|
1371
|
+
void Uint64Adapter::Append(uint64_t input, ByteSink& out) {
|
|
1372
|
+
if (input < 232) {
|
|
1373
|
+
out.Push(input);
|
|
1374
|
+
} else if (input < 4294967296) {
|
|
1375
|
+
if (input < 65536) {
|
|
1376
|
+
AppendWiredUint16(input, out);
|
|
1377
|
+
} else {
|
|
1378
|
+
AppendWiredUint32(input, out);
|
|
1379
|
+
}
|
|
1380
|
+
} else {
|
|
1381
|
+
AppendWiredUint64(input, out);
|
|
1382
|
+
}
|
|
1383
|
+
}
|
|
1384
|
+
|
|
1385
|
+
void Uint64Adapter::Parse(JsonTokenizer& tokenizer, uint64_t& out) {
|
|
1386
|
+
ParseJsonNumber(tokenizer, out);
|
|
1387
|
+
}
|
|
1388
|
+
|
|
1389
|
+
void Uint64Adapter::Parse(ByteSource& source, uint64_t& out) {
|
|
1390
|
+
ParseNumber(source, out);
|
|
1391
|
+
}
|
|
1392
|
+
|
|
1393
|
+
void Float32Adapter::Append(float input, ByteSink& out) {
|
|
1394
|
+
if (input == 0.0) {
|
|
1395
|
+
out.Push(0);
|
|
1396
|
+
} else {
|
|
1397
|
+
AppendWiredFloat32(input, out);
|
|
1398
|
+
}
|
|
1399
|
+
}
|
|
1400
|
+
|
|
1401
|
+
void Float32Adapter::Parse(JsonTokenizer& tokenizer, float& out) {
|
|
1402
|
+
ParseJsonNumber(tokenizer, out);
|
|
1403
|
+
}
|
|
1404
|
+
|
|
1405
|
+
void Float32Adapter::Parse(ByteSource& source, float& out) {
|
|
1406
|
+
ParseNumber(source, out);
|
|
1407
|
+
}
|
|
1408
|
+
|
|
1409
|
+
void Float64Adapter::Append(double input, ByteSink& out) {
|
|
1410
|
+
if (input == 0.0) {
|
|
1411
|
+
out.Push(0);
|
|
1412
|
+
} else {
|
|
1413
|
+
AppendWiredFloat64(input, out);
|
|
1414
|
+
}
|
|
1415
|
+
}
|
|
1416
|
+
|
|
1417
|
+
void Float64Adapter::Parse(JsonTokenizer& tokenizer, double& out) {
|
|
1418
|
+
ParseJsonNumber(tokenizer, out);
|
|
1419
|
+
}
|
|
1420
|
+
|
|
1421
|
+
void Float64Adapter::Parse(ByteSource& source, double& out) {
|
|
1422
|
+
ParseNumber(source, out);
|
|
1423
|
+
}
|
|
1424
|
+
|
|
1425
|
+
void TimestampAdapter::Append(absl::Time input, DenseJson& out) {
|
|
1426
|
+
absl::StrAppend(&out.out, ClampUnixMillis(absl::ToUnixMillis(input)));
|
|
1427
|
+
}
|
|
1428
|
+
|
|
1429
|
+
void TimestampAdapter::Append(absl::Time input, ReadableJson& out) {
|
|
1430
|
+
const int64_t unix_millis = ClampUnixMillis(absl::ToUnixMillis(input));
|
|
1431
|
+
input = absl::FromUnixMillis(unix_millis);
|
|
1432
|
+
absl::StrAppend(
|
|
1433
|
+
&out.out, "{", *out.new_line, " \"unix_millis\": ", unix_millis, ",",
|
|
1434
|
+
*out.new_line, " \"formatted\": \"",
|
|
1435
|
+
absl::FormatTime("%Y-%m-%dT%H:%M:%E3SZ", input, absl::UTCTimeZone()),
|
|
1436
|
+
"\"", *out.new_line, "}");
|
|
1437
|
+
}
|
|
1438
|
+
|
|
1439
|
+
void TimestampAdapter::Append(absl::Time input, DebugString& out) {
|
|
1440
|
+
const int64_t unix_millis = absl::ToUnixMillis(input); // Don't clamp
|
|
1441
|
+
input = absl::FromUnixMillis(unix_millis);
|
|
1442
|
+
absl::StrAppend(
|
|
1443
|
+
&out.out, "absl::FromUnixMillis(", unix_millis, " /* ",
|
|
1444
|
+
absl::FormatTime("%Y-%m-%dT%H:%M:%E3SZ", input, absl::UTCTimeZone()),
|
|
1445
|
+
" */)");
|
|
1446
|
+
}
|
|
1447
|
+
|
|
1448
|
+
void TimestampAdapter::Append(absl::Time input, ByteSink& out) {
|
|
1449
|
+
const int64_t unix_millis = ClampUnixMillis(absl::ToUnixMillis(input));
|
|
1450
|
+
if (unix_millis != 0) {
|
|
1451
|
+
AppendWiredInt64<239>(unix_millis, out);
|
|
1452
|
+
} else {
|
|
1453
|
+
out.Push(0);
|
|
1454
|
+
}
|
|
1455
|
+
}
|
|
1456
|
+
|
|
1457
|
+
void TimestampAdapter::Parse(JsonTokenizer& tokenizer, absl::Time& out) {
|
|
1458
|
+
if (tokenizer.state().token_type == JsonTokenType::kLeftCurlyBracket) {
|
|
1459
|
+
bool has_unix_millis = false;
|
|
1460
|
+
JsonObjectReader object_reader(&tokenizer);
|
|
1461
|
+
while (object_reader.NextEntry()) {
|
|
1462
|
+
if (object_reader.name() == "unix_millis") {
|
|
1463
|
+
has_unix_millis = true;
|
|
1464
|
+
int64_t unix_millis = 0;
|
|
1465
|
+
ParseJsonNumber(tokenizer, unix_millis);
|
|
1466
|
+
out = absl::FromUnixMillis(ClampUnixMillis(unix_millis));
|
|
1467
|
+
} else {
|
|
1468
|
+
SkipValue(tokenizer);
|
|
1469
|
+
}
|
|
1470
|
+
}
|
|
1471
|
+
if (!has_unix_millis) {
|
|
1472
|
+
tokenizer.mutable_state().PushError(
|
|
1473
|
+
"object missing entry with name 'unix_millis'");
|
|
1474
|
+
}
|
|
1475
|
+
} else {
|
|
1476
|
+
int64_t unix_millis = 0;
|
|
1477
|
+
ParseJsonNumber(tokenizer, unix_millis);
|
|
1478
|
+
out = absl::FromUnixMillis(ClampUnixMillis(unix_millis));
|
|
1479
|
+
}
|
|
1480
|
+
}
|
|
1481
|
+
|
|
1482
|
+
void TimestampAdapter::Parse(ByteSource& source, absl::Time& out) {
|
|
1483
|
+
int64_t unix_millis = 0;
|
|
1484
|
+
ParseNumber(source, unix_millis);
|
|
1485
|
+
out = absl::FromUnixMillis(ClampUnixMillis(unix_millis));
|
|
1486
|
+
}
|
|
1487
|
+
|
|
1488
|
+
void StringAdapter::AppendJson(const std::string& input, std::string& out) {
|
|
1489
|
+
if (input.empty()) {
|
|
1490
|
+
out += {'"', '"'};
|
|
1491
|
+
return;
|
|
1492
|
+
}
|
|
1493
|
+
out += '"';
|
|
1494
|
+
skir_internal::EscapeJsonString(input, out);
|
|
1495
|
+
out += '"';
|
|
1496
|
+
}
|
|
1497
|
+
|
|
1498
|
+
void StringAdapter::Append(const std::string& input, DebugString& out) {
|
|
1499
|
+
out.out += '"';
|
|
1500
|
+
EscapeDebugString(input, out.out);
|
|
1501
|
+
out.out += '"';
|
|
1502
|
+
}
|
|
1503
|
+
|
|
1504
|
+
void StringAdapter::Append(const std::string& input, ByteSink& out) {
|
|
1505
|
+
if (input.empty()) {
|
|
1506
|
+
out.Push(242);
|
|
1507
|
+
return;
|
|
1508
|
+
}
|
|
1509
|
+
// We don't know the length of the UTF-8 string until we actually encode the
|
|
1510
|
+
// string. We just know that it's at most 3 times the length of the input
|
|
1511
|
+
// string.
|
|
1512
|
+
const uint64_t max_encoded_length = input.length() * static_cast<uint64_t>(3);
|
|
1513
|
+
|
|
1514
|
+
const int prefix_length = max_encoded_length < 232 ? 2
|
|
1515
|
+
: max_encoded_length < 65536 ? 4
|
|
1516
|
+
: 6;
|
|
1517
|
+
|
|
1518
|
+
// Prepare for the most-likely scenario: the input string does not contain
|
|
1519
|
+
// invalid UTF-8 sequences. We will call Prepare again otherwise.
|
|
1520
|
+
out.Prepare(prefix_length + input.length());
|
|
1521
|
+
|
|
1522
|
+
// Write zero in place of the UTF-8 sequence length. We will override this
|
|
1523
|
+
// number later.
|
|
1524
|
+
if (max_encoded_length < 232) {
|
|
1525
|
+
out.Push(243, 0);
|
|
1526
|
+
} else if (max_encoded_length < 65536) {
|
|
1527
|
+
out.Push(243, 232, 0, 0);
|
|
1528
|
+
} else {
|
|
1529
|
+
out.Push(243, 233, 0, 0, 0, 0);
|
|
1530
|
+
}
|
|
1531
|
+
|
|
1532
|
+
const size_t prefix_end_offset = out.length();
|
|
1533
|
+
CopyUtf8String(input, out);
|
|
1534
|
+
const size_t encoded_length = out.length() - prefix_end_offset;
|
|
1535
|
+
|
|
1536
|
+
// Now we can actually write the encoded length to the prefix.
|
|
1537
|
+
uint8_t* data = out.data();
|
|
1538
|
+
if (max_encoded_length < 232) {
|
|
1539
|
+
data[prefix_end_offset - 1] = encoded_length;
|
|
1540
|
+
} else if (max_encoded_length < 65536) {
|
|
1541
|
+
data[prefix_end_offset - 2] = encoded_length & 0xFF;
|
|
1542
|
+
data[prefix_end_offset - 1] = encoded_length >> 8;
|
|
1543
|
+
} else {
|
|
1544
|
+
if (encoded_length < 4294967296) {
|
|
1545
|
+
data[prefix_end_offset - 4] = encoded_length & 0xFF;
|
|
1546
|
+
data[prefix_end_offset - 3] = encoded_length >> 8;
|
|
1547
|
+
data[prefix_end_offset - 2] = encoded_length >> 16;
|
|
1548
|
+
data[prefix_end_offset - 1] = encoded_length >> 24;
|
|
1549
|
+
} else {
|
|
1550
|
+
LOG(FATAL) << "overflow error while encoding skir value; length: "
|
|
1551
|
+
<< input.length();
|
|
1552
|
+
}
|
|
1553
|
+
}
|
|
1554
|
+
}
|
|
1555
|
+
|
|
1556
|
+
void StringAdapter::Parse(JsonTokenizer& tokenizer, std::string& out) {
|
|
1557
|
+
switch (tokenizer.state().token_type) {
|
|
1558
|
+
case JsonTokenType::kString:
|
|
1559
|
+
out = std::move(tokenizer.mutable_state().string_value);
|
|
1560
|
+
tokenizer.Next();
|
|
1561
|
+
break;
|
|
1562
|
+
case JsonTokenType::kZero:
|
|
1563
|
+
tokenizer.Next();
|
|
1564
|
+
break;
|
|
1565
|
+
default:
|
|
1566
|
+
tokenizer.mutable_state().PushUnexpectedTokenError("string");
|
|
1567
|
+
}
|
|
1568
|
+
}
|
|
1569
|
+
|
|
1570
|
+
void StringAdapter::Parse(ByteSource& source, std::string& out) {
|
|
1571
|
+
const uint8_t wire = source.ReadWire();
|
|
1572
|
+
if (wire == 243) {
|
|
1573
|
+
uint32_t length = 0;
|
|
1574
|
+
ParseNumber(source, length);
|
|
1575
|
+
if (source.num_bytes_left() < length) {
|
|
1576
|
+
return source.RaiseError();
|
|
1577
|
+
};
|
|
1578
|
+
out.reserve(length);
|
|
1579
|
+
out.append(cast(source.pos), length);
|
|
1580
|
+
source.pos += length;
|
|
1581
|
+
} else if (wire != 242 && wire != 0) {
|
|
1582
|
+
source.RaiseError();
|
|
1583
|
+
}
|
|
1584
|
+
}
|
|
1585
|
+
|
|
1586
|
+
void BytesAdapter::Append(const skir::ByteString& input, DenseJson& out) {
|
|
1587
|
+
absl::StrAppend(&out.out, "\"", absl::Base64Escape(input.as_string()), "\"");
|
|
1588
|
+
}
|
|
1589
|
+
|
|
1590
|
+
void BytesAdapter::Append(const skir::ByteString& input, ReadableJson& out) {
|
|
1591
|
+
absl::StrAppend(&out.out, "\"hex:", absl::BytesToHexString(input.as_string()),
|
|
1592
|
+
"\"");
|
|
1593
|
+
}
|
|
1594
|
+
|
|
1595
|
+
void BytesAdapter::Append(const skir::ByteString& input, DebugString& out) {
|
|
1596
|
+
out.out += "skir::ByteString({";
|
|
1597
|
+
const absl::string_view bytes = input.as_string();
|
|
1598
|
+
for (size_t i = 0; i < bytes.length(); ++i) {
|
|
1599
|
+
if (i != 0) {
|
|
1600
|
+
out.out += {',', ' '};
|
|
1601
|
+
}
|
|
1602
|
+
const uint8_t byte = static_cast<uint8_t>(bytes[i]);
|
|
1603
|
+
out.out += {'0', 'x', skir_internal::kHexDigits[byte >> 4],
|
|
1604
|
+
skir_internal::kHexDigits[byte & 0xf]};
|
|
1605
|
+
}
|
|
1606
|
+
out.out += "})";
|
|
1607
|
+
}
|
|
1608
|
+
|
|
1609
|
+
void BytesAdapter::Append(const skir::ByteString& input, ByteSink& out) {
|
|
1610
|
+
if (input.empty()) {
|
|
1611
|
+
out.Push(244);
|
|
1612
|
+
} else {
|
|
1613
|
+
AppendLengthPrefix<245>(input.length(), out);
|
|
1614
|
+
out.PushNUnsafe(cast(input.as_string().data()), input.length());
|
|
1615
|
+
}
|
|
1616
|
+
}
|
|
1617
|
+
|
|
1618
|
+
void BytesAdapter::Parse(JsonTokenizer& tokenizer, skir::ByteString& out) {
|
|
1619
|
+
switch (tokenizer.state().token_type) {
|
|
1620
|
+
case JsonTokenType::kString: {
|
|
1621
|
+
const std::string& string_value = tokenizer.state().string_value;
|
|
1622
|
+
std::string bytes;
|
|
1623
|
+
if (absl::StartsWith(string_value, "hex:")) {
|
|
1624
|
+
const absl::string_view hex_string =
|
|
1625
|
+
absl::string_view(string_value).substr(4);
|
|
1626
|
+
if (!absl::HexStringToBytes(hex_string, &bytes)) {
|
|
1627
|
+
tokenizer.mutable_state().PushError(
|
|
1628
|
+
"error while parsing JSON: not a hex string");
|
|
1629
|
+
}
|
|
1630
|
+
} else if (!absl::Base64Unescape(string_value, &bytes)) {
|
|
1631
|
+
tokenizer.mutable_state().PushError(
|
|
1632
|
+
"error while parsing JSON: not a Base64 string");
|
|
1633
|
+
}
|
|
1634
|
+
out = std::move(bytes);
|
|
1635
|
+
tokenizer.Next();
|
|
1636
|
+
break;
|
|
1637
|
+
}
|
|
1638
|
+
case JsonTokenType::kZero:
|
|
1639
|
+
tokenizer.Next();
|
|
1640
|
+
break;
|
|
1641
|
+
default:
|
|
1642
|
+
tokenizer.mutable_state().PushUnexpectedTokenError("Base64 string");
|
|
1643
|
+
}
|
|
1644
|
+
}
|
|
1645
|
+
|
|
1646
|
+
void BytesAdapter::Parse(ByteSource& source, skir::ByteString& out) {
|
|
1647
|
+
const uint8_t wire = source.ReadWire();
|
|
1648
|
+
switch (wire) {
|
|
1649
|
+
case 0:
|
|
1650
|
+
case 244:
|
|
1651
|
+
break;
|
|
1652
|
+
case 245: {
|
|
1653
|
+
uint32_t length = 0;
|
|
1654
|
+
ParseNumber(source, length);
|
|
1655
|
+
if (source.num_bytes_left() < length) {
|
|
1656
|
+
return source.RaiseError();
|
|
1657
|
+
}
|
|
1658
|
+
const char* begin = cast(source.pos);
|
|
1659
|
+
out = absl::string_view(begin, length);
|
|
1660
|
+
source.pos += length;
|
|
1661
|
+
break;
|
|
1662
|
+
}
|
|
1663
|
+
default: {
|
|
1664
|
+
source.RaiseError();
|
|
1665
|
+
}
|
|
1666
|
+
}
|
|
1667
|
+
}
|
|
1668
|
+
|
|
1669
|
+
// =============================================================================
|
|
1670
|
+
// BEGIN serialization of type descriptors
|
|
1671
|
+
// =============================================================================
|
|
1672
|
+
|
|
1673
|
+
void ReflectionTypeAdapter::Append(const skir::reflection::Type& input,
|
|
1674
|
+
ReadableJson& out) {
|
|
1675
|
+
absl::StrAppend(&out.out, "{", out.new_line.Indent());
|
|
1676
|
+
struct visitor {
|
|
1677
|
+
ReadableJson& out;
|
|
1678
|
+
void operator()(skir::reflection::PrimitiveType primitive) {
|
|
1679
|
+
absl::StrAppend(&out.out, "\"kind\": \"primitive\",", *out.new_line,
|
|
1680
|
+
"\"value\": ");
|
|
1681
|
+
skir_internal::Append(primitive, out);
|
|
1682
|
+
}
|
|
1683
|
+
void operator()(const skir::reflection::OptionalType& optional) {
|
|
1684
|
+
absl::StrAppend(&out.out, "\"kind\": \"optional\",", *out.new_line,
|
|
1685
|
+
"\"value\": ");
|
|
1686
|
+
skir_internal::Append(optional, out);
|
|
1687
|
+
}
|
|
1688
|
+
void operator()(const skir::reflection::ArrayType& array) {
|
|
1689
|
+
absl::StrAppend(&out.out, "\"kind\": \"array\",", *out.new_line,
|
|
1690
|
+
"\"value\": ");
|
|
1691
|
+
skir_internal::Append(array, out);
|
|
1692
|
+
}
|
|
1693
|
+
void operator()(const skir::reflection::RecordType& record) {
|
|
1694
|
+
absl::StrAppend(&out.out, "\"kind\": \"record\",", *out.new_line,
|
|
1695
|
+
"\"value\": ");
|
|
1696
|
+
skir_internal::Append(record, out);
|
|
1697
|
+
}
|
|
1698
|
+
};
|
|
1699
|
+
std::visit(visitor{out}, input);
|
|
1700
|
+
absl::StrAppend(&out.out, out.new_line.Dedent(), "}");
|
|
1701
|
+
}
|
|
1702
|
+
|
|
1703
|
+
void ReflectionTypeAdapter::Parse(JsonTokenizer& tokenizer,
|
|
1704
|
+
skir::reflection::Type& out) {
|
|
1705
|
+
if (tokenizer.state().token_type == JsonTokenType::kLeftCurlyBracket) {
|
|
1706
|
+
static const auto* kParser =
|
|
1707
|
+
(new EnumJsonObjectParser<skir::reflection::Type>())
|
|
1708
|
+
->AddVariantAsVariant<skir::reflection::PrimitiveType>("primitive")
|
|
1709
|
+
->AddVariantAsVariant<skir::reflection::OptionalType>("optional")
|
|
1710
|
+
->AddVariantAsVariant<skir::reflection::ArrayType>("array")
|
|
1711
|
+
->AddVariantAsVariant<skir::reflection::RecordType>("record");
|
|
1712
|
+
kParser->Parse(tokenizer, out);
|
|
1713
|
+
} else {
|
|
1714
|
+
tokenizer.mutable_state().PushUnexpectedTokenError("'}'");
|
|
1715
|
+
}
|
|
1716
|
+
}
|
|
1717
|
+
|
|
1718
|
+
void ReflectionPrimitiveTypeAdapter::Append(
|
|
1719
|
+
skir::reflection::PrimitiveType input, ReadableJson& out) {
|
|
1720
|
+
switch (input) {
|
|
1721
|
+
case skir::reflection::PrimitiveType::kBool: {
|
|
1722
|
+
out.out += "\"bool\"";
|
|
1723
|
+
break;
|
|
1724
|
+
}
|
|
1725
|
+
case skir::reflection::PrimitiveType::kInt32: {
|
|
1726
|
+
out.out += "\"int32\"";
|
|
1727
|
+
break;
|
|
1728
|
+
}
|
|
1729
|
+
case skir::reflection::PrimitiveType::kInt64: {
|
|
1730
|
+
out.out += "\"int64\"";
|
|
1731
|
+
break;
|
|
1732
|
+
}
|
|
1733
|
+
case skir::reflection::PrimitiveType::kUint64: {
|
|
1734
|
+
out.out += "\"uint64\"";
|
|
1735
|
+
break;
|
|
1736
|
+
}
|
|
1737
|
+
case skir::reflection::PrimitiveType::kFloat32: {
|
|
1738
|
+
out.out += "\"float32\"";
|
|
1739
|
+
break;
|
|
1740
|
+
}
|
|
1741
|
+
case skir::reflection::PrimitiveType::kFloat64: {
|
|
1742
|
+
out.out += "\"float64\"";
|
|
1743
|
+
break;
|
|
1744
|
+
}
|
|
1745
|
+
case skir::reflection::PrimitiveType::kTimestamp: {
|
|
1746
|
+
out.out += "\"timestamp\"";
|
|
1747
|
+
break;
|
|
1748
|
+
}
|
|
1749
|
+
case skir::reflection::PrimitiveType::kString: {
|
|
1750
|
+
out.out += "\"string\"";
|
|
1751
|
+
break;
|
|
1752
|
+
}
|
|
1753
|
+
case skir::reflection::PrimitiveType::kBytes: {
|
|
1754
|
+
out.out += "\"bytes\"";
|
|
1755
|
+
break;
|
|
1756
|
+
}
|
|
1757
|
+
}
|
|
1758
|
+
}
|
|
1759
|
+
|
|
1760
|
+
void ReflectionPrimitiveTypeAdapter::Parse(
|
|
1761
|
+
JsonTokenizer& tokenizer, skir::reflection::PrimitiveType& out) {
|
|
1762
|
+
static const auto* kMap =
|
|
1763
|
+
new ::absl::flat_hash_map<std::string, skir::reflection::PrimitiveType>({
|
|
1764
|
+
{"bool", skir::reflection::PrimitiveType::kBool},
|
|
1765
|
+
{"int32", skir::reflection::PrimitiveType::kInt32},
|
|
1766
|
+
{"int64", skir::reflection::PrimitiveType::kInt64},
|
|
1767
|
+
{"uint64", skir::reflection::PrimitiveType::kUint64},
|
|
1768
|
+
{"float32", skir::reflection::PrimitiveType::kFloat32},
|
|
1769
|
+
{"float64", skir::reflection::PrimitiveType::kFloat64},
|
|
1770
|
+
{"timestamp", skir::reflection::PrimitiveType::kTimestamp},
|
|
1771
|
+
{"string", skir::reflection::PrimitiveType::kString},
|
|
1772
|
+
{"bytes", skir::reflection::PrimitiveType::kBytes},
|
|
1773
|
+
});
|
|
1774
|
+
if (tokenizer.state().token_type == JsonTokenType::kString) {
|
|
1775
|
+
const auto it = kMap->find(tokenizer.state().string_value);
|
|
1776
|
+
if (it != kMap->cend()) {
|
|
1777
|
+
out = it->second;
|
|
1778
|
+
tokenizer.Next();
|
|
1779
|
+
return;
|
|
1780
|
+
}
|
|
1781
|
+
}
|
|
1782
|
+
// Error.
|
|
1783
|
+
std::vector<std::string> options;
|
|
1784
|
+
options.reserve(kMap->size());
|
|
1785
|
+
for (const auto& [option, _] : *kMap) {
|
|
1786
|
+
options.push_back(absl::StrCat("\"", option, "\""));
|
|
1787
|
+
}
|
|
1788
|
+
absl::c_sort(options);
|
|
1789
|
+
tokenizer.mutable_state().PushUnexpectedTokenError(
|
|
1790
|
+
absl::StrCat("one of: [", absl::StrJoin(options, ", "), "]"));
|
|
1791
|
+
}
|
|
1792
|
+
|
|
1793
|
+
void ReflectionOptionalTypeAdapter::Append(
|
|
1794
|
+
const skir::reflection::OptionalType& input, ReadableJson& out) {
|
|
1795
|
+
TypeAdapter<skir::reflection::Type>::Append(*input.other, out);
|
|
1796
|
+
}
|
|
1797
|
+
|
|
1798
|
+
void ReflectionOptionalTypeAdapter::Parse(JsonTokenizer& tokenizer,
|
|
1799
|
+
skir::reflection::OptionalType& out) {
|
|
1800
|
+
TypeAdapter<skir::reflection::Type>::Parse(tokenizer, *out.other);
|
|
1801
|
+
}
|
|
1802
|
+
|
|
1803
|
+
void ReflectionRecordTypeAdapter::Append(
|
|
1804
|
+
const skir::reflection::RecordType& input, ReadableJson& out) {
|
|
1805
|
+
TypeAdapter<std::string>::Append(input.record_id, out);
|
|
1806
|
+
}
|
|
1807
|
+
|
|
1808
|
+
void ReflectionRecordTypeAdapter::Parse(JsonTokenizer& tokenizer,
|
|
1809
|
+
skir::reflection::RecordType& out) {
|
|
1810
|
+
TypeAdapter<std::string>::Parse(tokenizer, out.record_id);
|
|
1811
|
+
}
|
|
1812
|
+
|
|
1813
|
+
void ReflectionArrayTypeAdapter::Append(
|
|
1814
|
+
const skir::reflection::ArrayType& input, ReadableJson& out) {
|
|
1815
|
+
JsonObjectWriter(&out)
|
|
1816
|
+
.Write("item", input.item)
|
|
1817
|
+
.Write("key_extractor", input.key_extractor);
|
|
1818
|
+
}
|
|
1819
|
+
|
|
1820
|
+
void ReflectionArrayTypeAdapter::Parse(JsonTokenizer& tokenizer,
|
|
1821
|
+
skir::reflection::ArrayType& out) {
|
|
1822
|
+
if (tokenizer.state().token_type == JsonTokenType::kLeftCurlyBracket) {
|
|
1823
|
+
static const auto* kParser =
|
|
1824
|
+
(new StructJsonObjectParser<skir::reflection::ArrayType>())
|
|
1825
|
+
->AddField("item", &skir::reflection::ArrayType::item)
|
|
1826
|
+
->AddField("key_extractor",
|
|
1827
|
+
&skir::reflection::ArrayType::key_extractor);
|
|
1828
|
+
kParser->Parse(tokenizer, out);
|
|
1829
|
+
return;
|
|
1830
|
+
}
|
|
1831
|
+
tokenizer.mutable_state().PushUnexpectedTokenError("'{'");
|
|
1832
|
+
}
|
|
1833
|
+
|
|
1834
|
+
void ReflectionFieldAdapter::Append(const skir::reflection::Field& input,
|
|
1835
|
+
ReadableJson& out) {
|
|
1836
|
+
AppendFieldOrVariant(input, out);
|
|
1837
|
+
}
|
|
1838
|
+
|
|
1839
|
+
void ReflectionFieldAdapter::Parse(JsonTokenizer& tokenizer,
|
|
1840
|
+
skir::reflection::Field& out) {
|
|
1841
|
+
ParseFieldOrVariant(tokenizer, out);
|
|
1842
|
+
}
|
|
1843
|
+
|
|
1844
|
+
void ReflectionVariantAdapter::Append(const skir::reflection::Variant& input,
|
|
1845
|
+
ReadableJson& out) {
|
|
1846
|
+
AppendFieldOrVariant(input, out);
|
|
1847
|
+
}
|
|
1848
|
+
|
|
1849
|
+
void ReflectionVariantAdapter::Parse(JsonTokenizer& tokenizer,
|
|
1850
|
+
skir::reflection::Variant& out) {
|
|
1851
|
+
ParseFieldOrVariant(tokenizer, out);
|
|
1852
|
+
}
|
|
1853
|
+
|
|
1854
|
+
void ReflectionRecordAdapter::Append(const skir::reflection::Record& input,
|
|
1855
|
+
ReadableJson& out) {
|
|
1856
|
+
struct visitor {
|
|
1857
|
+
ReadableJson& out;
|
|
1858
|
+
|
|
1859
|
+
void operator()(const skir::reflection::Struct& record) const {
|
|
1860
|
+
static const std::string* kKindStr = new std::string("struct");
|
|
1861
|
+
JsonObjectWriter(&out)
|
|
1862
|
+
.Write("kind", *kKindStr)
|
|
1863
|
+
.Write("id", record.id)
|
|
1864
|
+
.Write("doc", record.doc)
|
|
1865
|
+
.Write("fields", record.fields)
|
|
1866
|
+
.Write("removed_numbers", record.removed_numbers);
|
|
1867
|
+
}
|
|
1868
|
+
|
|
1869
|
+
void operator()(const skir::reflection::Enum& record) const {
|
|
1870
|
+
static const std::string* kKindStr = new std::string("enum");
|
|
1871
|
+
JsonObjectWriter(&out)
|
|
1872
|
+
.Write("kind", *kKindStr)
|
|
1873
|
+
.Write("id", record.id)
|
|
1874
|
+
.Write("doc", record.doc)
|
|
1875
|
+
.Write("variants", record.variants)
|
|
1876
|
+
.Write("removed_numbers", record.removed_numbers);
|
|
1877
|
+
}
|
|
1878
|
+
};
|
|
1879
|
+
std::visit(visitor{out}, input);
|
|
1880
|
+
}
|
|
1881
|
+
|
|
1882
|
+
void ReflectionRecordAdapter::Parse(JsonTokenizer& tokenizer,
|
|
1883
|
+
skir::reflection::Record& out) {
|
|
1884
|
+
if (tokenizer.state().token_type == JsonTokenType::kLeftCurlyBracket) {
|
|
1885
|
+
static const auto* kParser =
|
|
1886
|
+
(new StructJsonObjectParser<::skir_internal::ReflectionStructOrEnum>())
|
|
1887
|
+
->AddField("kind", &::skir_internal::ReflectionStructOrEnum::kind)
|
|
1888
|
+
->AddField("id", &::skir_internal::ReflectionStructOrEnum::id)
|
|
1889
|
+
->AddField("doc", &::skir_internal::ReflectionStructOrEnum::doc)
|
|
1890
|
+
->AddField("fields",
|
|
1891
|
+
&::skir_internal::ReflectionStructOrEnum::fields)
|
|
1892
|
+
->AddField("variants",
|
|
1893
|
+
&::skir_internal::ReflectionStructOrEnum::variants)
|
|
1894
|
+
->AddField(
|
|
1895
|
+
"removed_numbers",
|
|
1896
|
+
&::skir_internal::ReflectionStructOrEnum::removed_numbers);
|
|
1897
|
+
::skir_internal::ReflectionStructOrEnum struct_or_enum;
|
|
1898
|
+
kParser->Parse(tokenizer, struct_or_enum);
|
|
1899
|
+
if (struct_or_enum.kind == "struct") {
|
|
1900
|
+
skir::reflection::Struct record;
|
|
1901
|
+
record.id = std::move(struct_or_enum.id);
|
|
1902
|
+
record.doc = std::move(struct_or_enum.doc);
|
|
1903
|
+
record.fields = std::move(struct_or_enum.fields);
|
|
1904
|
+
record.removed_numbers = std::move(struct_or_enum.removed_numbers);
|
|
1905
|
+
out = std::move(record);
|
|
1906
|
+
} else {
|
|
1907
|
+
skir::reflection::Enum record;
|
|
1908
|
+
record.id = std::move(struct_or_enum.id);
|
|
1909
|
+
record.doc = std::move(struct_or_enum.doc);
|
|
1910
|
+
record.variants = std::move(struct_or_enum.variants);
|
|
1911
|
+
record.removed_numbers = std::move(struct_or_enum.removed_numbers);
|
|
1912
|
+
out = std::move(record);
|
|
1913
|
+
}
|
|
1914
|
+
return;
|
|
1915
|
+
}
|
|
1916
|
+
tokenizer.mutable_state().PushUnexpectedTokenError("'{'");
|
|
1917
|
+
}
|
|
1918
|
+
|
|
1919
|
+
void ReflectionTypeDescriptorAdapter::Append(
|
|
1920
|
+
const skir::reflection::TypeDescriptor& input, ReadableJson& out) {
|
|
1921
|
+
JsonObjectWriter(&out)
|
|
1922
|
+
.Write("type", input.type)
|
|
1923
|
+
.WriteEvenIfDefault("records", input.records);
|
|
1924
|
+
}
|
|
1925
|
+
|
|
1926
|
+
void ReflectionTypeDescriptorAdapter::Parse(
|
|
1927
|
+
JsonTokenizer& tokenizer, skir::reflection::TypeDescriptor& out) {
|
|
1928
|
+
if (tokenizer.state().token_type == JsonTokenType::kLeftCurlyBracket) {
|
|
1929
|
+
static const auto* kParser =
|
|
1930
|
+
(new StructJsonObjectParser<skir::reflection::TypeDescriptor>())
|
|
1931
|
+
->AddField("type", &skir::reflection::TypeDescriptor::type)
|
|
1932
|
+
->AddField("records", &skir::reflection::TypeDescriptor::records);
|
|
1933
|
+
kParser->Parse(tokenizer, out);
|
|
1934
|
+
return;
|
|
1935
|
+
}
|
|
1936
|
+
tokenizer.mutable_state().PushUnexpectedTokenError("'{'");
|
|
1937
|
+
}
|
|
1938
|
+
|
|
1939
|
+
// =============================================================================
|
|
1940
|
+
// END serialization of type descriptors
|
|
1941
|
+
// =============================================================================
|
|
1942
|
+
|
|
1943
|
+
void StructJsonObjectParserImpl::Parse(JsonTokenizer& tokenizer,
|
|
1944
|
+
void* out) const {
|
|
1945
|
+
JsonObjectReader object_reader(&tokenizer);
|
|
1946
|
+
while (object_reader.NextEntry()) {
|
|
1947
|
+
const auto it = fields_.find(object_reader.name());
|
|
1948
|
+
if (it == fields_.end()) {
|
|
1949
|
+
SkipValue(tokenizer);
|
|
1950
|
+
continue;
|
|
1951
|
+
}
|
|
1952
|
+
const Field* field = it->second.get();
|
|
1953
|
+
field->Parse(tokenizer, out);
|
|
1954
|
+
}
|
|
1955
|
+
}
|
|
1956
|
+
|
|
1957
|
+
void EnumJsonObjectParserImpl::Parse(JsonTokenizer& tokenizer,
|
|
1958
|
+
void* out) const {
|
|
1959
|
+
JsonObjectReader object_reader(&tokenizer);
|
|
1960
|
+
bool kind_seen = false;
|
|
1961
|
+
bool value_seen = false;
|
|
1962
|
+
const Variant* variant = nullptr;
|
|
1963
|
+
// In the unlikely event "value" is seen before "kind", we need to rewind the
|
|
1964
|
+
// tokenizer to parse the value.
|
|
1965
|
+
std::unique_ptr<JsonTokenizer::State> value_state;
|
|
1966
|
+
while (object_reader.NextEntry()) {
|
|
1967
|
+
if (!kind_seen && object_reader.name() == "kind") {
|
|
1968
|
+
kind_seen = true;
|
|
1969
|
+
std::string kind;
|
|
1970
|
+
::skir_internal::Parse(tokenizer, kind);
|
|
1971
|
+
const auto it = variants_.find(kind);
|
|
1972
|
+
if (it == variants_.end()) {
|
|
1973
|
+
continue;
|
|
1974
|
+
}
|
|
1975
|
+
variant = it->second.get();
|
|
1976
|
+
if (value_state != nullptr) {
|
|
1977
|
+
// In this unlikely case, we need to rewind the tokenizer to parse the
|
|
1978
|
+
// value.
|
|
1979
|
+
if (!tokenizer.state().status.ok()) return;
|
|
1980
|
+
JsonTokenizer::State tokenizer_state =
|
|
1981
|
+
std::move(tokenizer.mutable_state());
|
|
1982
|
+
tokenizer.mutable_state() = *std::move(value_state);
|
|
1983
|
+
variant->Parse(tokenizer, out);
|
|
1984
|
+
const absl::Status status = std::move(tokenizer.mutable_state().status);
|
|
1985
|
+
tokenizer.mutable_state() = std::move(tokenizer_state);
|
|
1986
|
+
if (!status.ok()) {
|
|
1987
|
+
tokenizer.mutable_state().status = status;
|
|
1988
|
+
}
|
|
1989
|
+
}
|
|
1990
|
+
} else if (!value_seen && object_reader.name() == "value") {
|
|
1991
|
+
value_seen = true;
|
|
1992
|
+
if (variant != nullptr) {
|
|
1993
|
+
variant->Parse(tokenizer, out);
|
|
1994
|
+
} else {
|
|
1995
|
+
if (!kind_seen) {
|
|
1996
|
+
value_state =
|
|
1997
|
+
std::make_unique<JsonTokenizer::State>(tokenizer.state());
|
|
1998
|
+
}
|
|
1999
|
+
SkipValue(tokenizer);
|
|
2000
|
+
}
|
|
2001
|
+
} else {
|
|
2002
|
+
SkipValue(tokenizer);
|
|
2003
|
+
}
|
|
2004
|
+
}
|
|
2005
|
+
}
|
|
2006
|
+
|
|
2007
|
+
EnumJsonArrayParser::EnumJsonArrayParser(JsonTokenizer* tokenizer)
|
|
2008
|
+
: tokenizer_(*ABSL_DIE_IF_NULL(tokenizer)) {}
|
|
2009
|
+
|
|
2010
|
+
int EnumJsonArrayParser::ReadNumber() {
|
|
2011
|
+
int result = 0;
|
|
2012
|
+
switch (tokenizer_.Next()) {
|
|
2013
|
+
case JsonTokenType::kZero:
|
|
2014
|
+
break;
|
|
2015
|
+
case JsonTokenType::kUnsignedInteger:
|
|
2016
|
+
result = tokenizer_.state().uint_value;
|
|
2017
|
+
break;
|
|
2018
|
+
case JsonTokenType::kSignedInteger:
|
|
2019
|
+
result = tokenizer_.state().int_value;
|
|
2020
|
+
break;
|
|
2021
|
+
default:
|
|
2022
|
+
tokenizer_.mutable_state().PushUnexpectedTokenError("integer");
|
|
2023
|
+
return 0;
|
|
2024
|
+
}
|
|
2025
|
+
if (tokenizer_.Next() != JsonTokenType::kComma) {
|
|
2026
|
+
tokenizer_.mutable_state().PushUnexpectedTokenError("','");
|
|
2027
|
+
} else {
|
|
2028
|
+
tokenizer_.Next();
|
|
2029
|
+
}
|
|
2030
|
+
return result;
|
|
2031
|
+
}
|
|
2032
|
+
|
|
2033
|
+
void EnumJsonArrayParser::Finish() {
|
|
2034
|
+
if (tokenizer_.state().token_type == JsonTokenType::kRightSquareBracket) {
|
|
2035
|
+
tokenizer_.Next();
|
|
2036
|
+
} else {
|
|
2037
|
+
tokenizer_.mutable_state().PushUnexpectedTokenError("']'");
|
|
2038
|
+
}
|
|
2039
|
+
}
|
|
2040
|
+
|
|
2041
|
+
std::pair<bool, int32_t> ParseEnumPrefix(ByteSource& source) {
|
|
2042
|
+
const uint8_t wire = source.ReadWire();
|
|
2043
|
+
if (wire <= 238) {
|
|
2044
|
+
::int32_t number = 0;
|
|
2045
|
+
ParseNumberWithWire(wire, source, number);
|
|
2046
|
+
return {false, number};
|
|
2047
|
+
}
|
|
2048
|
+
switch (static_cast<uint8_t>(wire - 248)) {
|
|
2049
|
+
case 0: {
|
|
2050
|
+
// 248
|
|
2051
|
+
::int32_t number = 0;
|
|
2052
|
+
Int32Adapter::Parse(source, number);
|
|
2053
|
+
return {true, number};
|
|
2054
|
+
}
|
|
2055
|
+
case 2: {
|
|
2056
|
+
// 250
|
|
2057
|
+
uint32_t length = 0;
|
|
2058
|
+
ParseArrayPrefix(source, length);
|
|
2059
|
+
if (length != 2) break;
|
|
2060
|
+
::int32_t number = 0;
|
|
2061
|
+
Int32Adapter::Parse(source, number);
|
|
2062
|
+
return {true, number};
|
|
2063
|
+
}
|
|
2064
|
+
case 3:
|
|
2065
|
+
case 4:
|
|
2066
|
+
case 5:
|
|
2067
|
+
case 6:
|
|
2068
|
+
// 251-254
|
|
2069
|
+
return {true, wire - 250};
|
|
2070
|
+
}
|
|
2071
|
+
source.RaiseError();
|
|
2072
|
+
return {false, 0};
|
|
2073
|
+
}
|
|
2074
|
+
|
|
2075
|
+
void UnrecognizedValues::ParseFrom(JsonTokenizer& tokenizer) {
|
|
2076
|
+
// Each element in this stack is the index of an element in array_lengths_.
|
|
2077
|
+
std::vector<size_t> index_of_array_stack;
|
|
2078
|
+
while (true) {
|
|
2079
|
+
if (!index_of_array_stack.empty()) {
|
|
2080
|
+
uint32_t& array_length = array_lengths_[index_of_array_stack.back()];
|
|
2081
|
+
++array_length;
|
|
2082
|
+
}
|
|
2083
|
+
switch (tokenizer.state().token_type) {
|
|
2084
|
+
case JsonTokenType::kTrue: {
|
|
2085
|
+
bytes_.Push(1);
|
|
2086
|
+
tokenizer.Next();
|
|
2087
|
+
break;
|
|
2088
|
+
}
|
|
2089
|
+
case JsonTokenType::kZero:
|
|
2090
|
+
case JsonTokenType::kFalse: {
|
|
2091
|
+
bytes_.Push(0);
|
|
2092
|
+
tokenizer.Next();
|
|
2093
|
+
break;
|
|
2094
|
+
}
|
|
2095
|
+
case JsonTokenType::kNull: {
|
|
2096
|
+
bytes_.Push(255);
|
|
2097
|
+
tokenizer.Next();
|
|
2098
|
+
break;
|
|
2099
|
+
}
|
|
2100
|
+
case JsonTokenType::kUnsignedInteger: {
|
|
2101
|
+
Uint64Adapter::Append(tokenizer.state().uint_value, bytes_);
|
|
2102
|
+
tokenizer.Next();
|
|
2103
|
+
break;
|
|
2104
|
+
}
|
|
2105
|
+
case JsonTokenType::kSignedInteger: {
|
|
2106
|
+
Int64Adapter::Append(tokenizer.state().int_value, bytes_);
|
|
2107
|
+
tokenizer.Next();
|
|
2108
|
+
break;
|
|
2109
|
+
}
|
|
2110
|
+
case JsonTokenType::kFloat: {
|
|
2111
|
+
Float64Adapter::Append(tokenizer.state().float_value, bytes_);
|
|
2112
|
+
tokenizer.Next();
|
|
2113
|
+
break;
|
|
2114
|
+
}
|
|
2115
|
+
case JsonTokenType::kString: {
|
|
2116
|
+
StringAdapter::Append(tokenizer.state().string_value, bytes_);
|
|
2117
|
+
tokenizer.Next();
|
|
2118
|
+
break;
|
|
2119
|
+
}
|
|
2120
|
+
case JsonTokenType::kLeftSquareBracket: {
|
|
2121
|
+
if (tokenizer.Next() == JsonTokenType::kRightSquareBracket) {
|
|
2122
|
+
bytes_.Push(246);
|
|
2123
|
+
tokenizer.Next();
|
|
2124
|
+
break;
|
|
2125
|
+
}
|
|
2126
|
+
bytes_.Push(250);
|
|
2127
|
+
const size_t index = array_lengths_.size();
|
|
2128
|
+
array_lengths_.push_back(0);
|
|
2129
|
+
index_of_array_stack.push_back(index);
|
|
2130
|
+
continue;
|
|
2131
|
+
}
|
|
2132
|
+
case JsonTokenType::kLeftCurlyBracket: {
|
|
2133
|
+
// Not supported.
|
|
2134
|
+
bytes_.Push(0);
|
|
2135
|
+
SkipValue(tokenizer);
|
|
2136
|
+
continue;
|
|
2137
|
+
}
|
|
2138
|
+
default: {
|
|
2139
|
+
tokenizer.mutable_state().PushUnexpectedTokenError("value");
|
|
2140
|
+
return;
|
|
2141
|
+
}
|
|
2142
|
+
}
|
|
2143
|
+
while (!index_of_array_stack.empty() &&
|
|
2144
|
+
tokenizer.state().token_type == JsonTokenType::kRightSquareBracket) {
|
|
2145
|
+
tokenizer.Next();
|
|
2146
|
+
index_of_array_stack.pop_back();
|
|
2147
|
+
}
|
|
2148
|
+
if (index_of_array_stack.empty()) return;
|
|
2149
|
+
if (tokenizer.state().token_type == JsonTokenType::kComma) {
|
|
2150
|
+
tokenizer.Next();
|
|
2151
|
+
} else {
|
|
2152
|
+
tokenizer.mutable_state().PushUnexpectedTokenError("','");
|
|
2153
|
+
return;
|
|
2154
|
+
}
|
|
2155
|
+
}
|
|
2156
|
+
}
|
|
2157
|
+
|
|
2158
|
+
void UnrecognizedValues::ParseFrom(ByteSource& source) {
|
|
2159
|
+
for (size_t num_values_left = 1; num_values_left > 0; --num_values_left) {
|
|
2160
|
+
const uint8_t wire = source.ReadWire();
|
|
2161
|
+
switch (static_cast<uint8_t>(wire - 232)) {
|
|
2162
|
+
case 3: {
|
|
2163
|
+
// 235
|
|
2164
|
+
if (source.num_bytes_left() < 1) return source.RaiseError();
|
|
2165
|
+
++source.pos;
|
|
2166
|
+
bytes_.PushRange(source.pos - 2, source.pos);
|
|
2167
|
+
break;
|
|
2168
|
+
}
|
|
2169
|
+
case 0:
|
|
2170
|
+
case 4: {
|
|
2171
|
+
// 232, 236
|
|
2172
|
+
if (source.num_bytes_left() < 2) return source.RaiseError();
|
|
2173
|
+
source.pos += 2;
|
|
2174
|
+
bytes_.PushRange(source.pos - 3, source.pos);
|
|
2175
|
+
break;
|
|
2176
|
+
}
|
|
2177
|
+
case 1:
|
|
2178
|
+
case 5:
|
|
2179
|
+
case 8: {
|
|
2180
|
+
// 233, 237, 240
|
|
2181
|
+
if (source.num_bytes_left() < 4) return source.RaiseError();
|
|
2182
|
+
source.pos += 4;
|
|
2183
|
+
bytes_.PushRange(source.pos - 5, source.pos);
|
|
2184
|
+
break;
|
|
2185
|
+
}
|
|
2186
|
+
case 2:
|
|
2187
|
+
case 6:
|
|
2188
|
+
case 7:
|
|
2189
|
+
case 9: {
|
|
2190
|
+
// 234, 238, 239, 241
|
|
2191
|
+
if (source.num_bytes_left() < 8) return source.RaiseError();
|
|
2192
|
+
source.pos += 8;
|
|
2193
|
+
bytes_.PushRange(source.pos - 9, source.pos);
|
|
2194
|
+
break;
|
|
2195
|
+
}
|
|
2196
|
+
case 11:
|
|
2197
|
+
case 13: {
|
|
2198
|
+
// 243, 245
|
|
2199
|
+
const uint8_t* start = source.pos - 1;
|
|
2200
|
+
uint32_t length = 0;
|
|
2201
|
+
ParseNumber(source, length);
|
|
2202
|
+
if (source.num_bytes_left() < length) return source.RaiseError();
|
|
2203
|
+
bytes_.PushRange(start, source.pos += length);
|
|
2204
|
+
break;
|
|
2205
|
+
}
|
|
2206
|
+
case 15:
|
|
2207
|
+
case 16:
|
|
2208
|
+
case 17: {
|
|
2209
|
+
// 247-249
|
|
2210
|
+
num_values_left += wire - 246;
|
|
2211
|
+
bytes_.Push(wire);
|
|
2212
|
+
break;
|
|
2213
|
+
}
|
|
2214
|
+
case 18: {
|
|
2215
|
+
// 250
|
|
2216
|
+
uint32_t array_len = 0;
|
|
2217
|
+
ParseNumber(source, array_len);
|
|
2218
|
+
num_values_left += array_len;
|
|
2219
|
+
array_lengths_.push_back(array_len);
|
|
2220
|
+
bytes_.Push(wire);
|
|
2221
|
+
break;
|
|
2222
|
+
}
|
|
2223
|
+
case 19:
|
|
2224
|
+
case 20:
|
|
2225
|
+
case 21:
|
|
2226
|
+
case 22: {
|
|
2227
|
+
// 251-254
|
|
2228
|
+
++num_values_left;
|
|
2229
|
+
bytes_.Push(wire);
|
|
2230
|
+
break;
|
|
2231
|
+
}
|
|
2232
|
+
default: {
|
|
2233
|
+
if (wire == 0) {
|
|
2234
|
+
source.CheckEnd();
|
|
2235
|
+
if (source.error) return;
|
|
2236
|
+
}
|
|
2237
|
+
bytes_.Push(wire);
|
|
2238
|
+
}
|
|
2239
|
+
}
|
|
2240
|
+
}
|
|
2241
|
+
}
|
|
2242
|
+
|
|
2243
|
+
void UnrecognizedValues::AppendTo(DenseJson& out) const {
|
|
2244
|
+
size_t index_of_array = 0;
|
|
2245
|
+
ByteSource source(bytes_.data(), bytes_.length());
|
|
2246
|
+
std::vector<uint32_t> num_left_stack;
|
|
2247
|
+
for (;;) {
|
|
2248
|
+
if (!num_left_stack.empty()) {
|
|
2249
|
+
--num_left_stack.back();
|
|
2250
|
+
}
|
|
2251
|
+
if (source.pos == source.end) break;
|
|
2252
|
+
const uint8_t byte = *source.pos;
|
|
2253
|
+
if (byte <= 234) {
|
|
2254
|
+
uint64_t number = 0;
|
|
2255
|
+
Uint64Adapter::Parse(source, number);
|
|
2256
|
+
Uint64Adapter::Append(number, out);
|
|
2257
|
+
} else {
|
|
2258
|
+
switch (static_cast<uint8_t>(byte - 235)) {
|
|
2259
|
+
case 0:
|
|
2260
|
+
case 1:
|
|
2261
|
+
case 2:
|
|
2262
|
+
case 3:
|
|
2263
|
+
case 4: {
|
|
2264
|
+
// 235-239
|
|
2265
|
+
int64_t number = 0;
|
|
2266
|
+
Int64Adapter::Parse(source, number);
|
|
2267
|
+
Int64Adapter::Append(number, out);
|
|
2268
|
+
break;
|
|
2269
|
+
}
|
|
2270
|
+
case 5:
|
|
2271
|
+
case 6: {
|
|
2272
|
+
// 240-241
|
|
2273
|
+
double number = 0.0;
|
|
2274
|
+
Float64Adapter::Parse(source, number);
|
|
2275
|
+
Float64Adapter::Append(number, out);
|
|
2276
|
+
break;
|
|
2277
|
+
}
|
|
2278
|
+
case 7:
|
|
2279
|
+
case 9: {
|
|
2280
|
+
// 242, 244
|
|
2281
|
+
++source.pos;
|
|
2282
|
+
out.out += {'"', '"'};
|
|
2283
|
+
break;
|
|
2284
|
+
}
|
|
2285
|
+
case 8: {
|
|
2286
|
+
// 243
|
|
2287
|
+
++source.pos;
|
|
2288
|
+
uint32_t length = 0;
|
|
2289
|
+
ParseNumber(source, length);
|
|
2290
|
+
out.out += '"';
|
|
2291
|
+
const char* begin = cast(source.pos);
|
|
2292
|
+
EscapeJsonString<NullTerminated::kFalse>(
|
|
2293
|
+
begin, cast(source.pos += length), out.out);
|
|
2294
|
+
out.out += '"';
|
|
2295
|
+
break;
|
|
2296
|
+
}
|
|
2297
|
+
case 10: {
|
|
2298
|
+
// 245
|
|
2299
|
+
++source.pos;
|
|
2300
|
+
uint32_t length = 0;
|
|
2301
|
+
ParseNumber(source, length);
|
|
2302
|
+
out.out += '"';
|
|
2303
|
+
out.out +=
|
|
2304
|
+
absl::Base64Escape(absl::string_view(cast(source.pos), length));
|
|
2305
|
+
out.out += '"';
|
|
2306
|
+
source.pos += length;
|
|
2307
|
+
break;
|
|
2308
|
+
}
|
|
2309
|
+
case 11:
|
|
2310
|
+
case 12:
|
|
2311
|
+
case 13:
|
|
2312
|
+
case 14: {
|
|
2313
|
+
// 246-249
|
|
2314
|
+
++source.pos;
|
|
2315
|
+
const uint32_t length = byte - 246;
|
|
2316
|
+
num_left_stack.push_back(length);
|
|
2317
|
+
out.out += '[';
|
|
2318
|
+
break;
|
|
2319
|
+
}
|
|
2320
|
+
case 15: {
|
|
2321
|
+
// 250
|
|
2322
|
+
++source.pos;
|
|
2323
|
+
const uint32_t length = array_lengths_[index_of_array++];
|
|
2324
|
+
num_left_stack.push_back(length);
|
|
2325
|
+
out.out += '[';
|
|
2326
|
+
break;
|
|
2327
|
+
}
|
|
2328
|
+
case 16:
|
|
2329
|
+
case 17:
|
|
2330
|
+
case 18:
|
|
2331
|
+
case 19: {
|
|
2332
|
+
// 251-254
|
|
2333
|
+
++source.pos;
|
|
2334
|
+
const int number = byte - 250;
|
|
2335
|
+
num_left_stack.push_back(1);
|
|
2336
|
+
absl::StrAppend(&out.out, "[", number);
|
|
2337
|
+
break;
|
|
2338
|
+
}
|
|
2339
|
+
case 20: {
|
|
2340
|
+
// 255
|
|
2341
|
+
++source.pos;
|
|
2342
|
+
out.out += "null";
|
|
2343
|
+
break;
|
|
2344
|
+
}
|
|
2345
|
+
}
|
|
2346
|
+
}
|
|
2347
|
+
while (!num_left_stack.empty() && num_left_stack.back() == 0) {
|
|
2348
|
+
num_left_stack.pop_back();
|
|
2349
|
+
out.out += ']';
|
|
2350
|
+
}
|
|
2351
|
+
if (out.out.back() != '[' && source.pos < source.end) {
|
|
2352
|
+
out.out += ',';
|
|
2353
|
+
}
|
|
2354
|
+
}
|
|
2355
|
+
}
|
|
2356
|
+
|
|
2357
|
+
void UnrecognizedValues::AppendTo(ByteSink& out) const {
|
|
2358
|
+
{
|
|
2359
|
+
size_t total_bytes = bytes_.length();
|
|
2360
|
+
for (const uint32_t array_length : array_lengths_) {
|
|
2361
|
+
total_bytes += array_length < 4 ? 0
|
|
2362
|
+
: array_length < 232 ? 1
|
|
2363
|
+
: array_length < 65536 ? 3
|
|
2364
|
+
: 5;
|
|
2365
|
+
}
|
|
2366
|
+
out.Prepare(total_bytes);
|
|
2367
|
+
}
|
|
2368
|
+
size_t index_of_array = 0;
|
|
2369
|
+
ByteSource source(bytes_.data(), bytes_.length());
|
|
2370
|
+
while (true) {
|
|
2371
|
+
if (source.pos == source.end) break;
|
|
2372
|
+
const uint8_t byte = *source.pos;
|
|
2373
|
+
if (byte < 232) {
|
|
2374
|
+
++source.pos;
|
|
2375
|
+
out.PushUnsafe(byte);
|
|
2376
|
+
} else {
|
|
2377
|
+
switch (static_cast<uint8_t>(byte - 232)) {
|
|
2378
|
+
case 0:
|
|
2379
|
+
case 4: {
|
|
2380
|
+
// 232, 236
|
|
2381
|
+
const uint8_t* start = source.pos;
|
|
2382
|
+
out.PushRangeUnsafe(start, source.pos += 3);
|
|
2383
|
+
break;
|
|
2384
|
+
}
|
|
2385
|
+
case 1:
|
|
2386
|
+
case 5:
|
|
2387
|
+
case 8: {
|
|
2388
|
+
// 233, 237, 240
|
|
2389
|
+
const uint8_t* start = source.pos;
|
|
2390
|
+
out.PushRangeUnsafe(start, source.pos += 5);
|
|
2391
|
+
break;
|
|
2392
|
+
}
|
|
2393
|
+
case 2:
|
|
2394
|
+
case 6:
|
|
2395
|
+
case 7:
|
|
2396
|
+
case 9: {
|
|
2397
|
+
// 234, 238, 239, 241
|
|
2398
|
+
const uint8_t* start = source.pos;
|
|
2399
|
+
out.PushRangeUnsafe(start, source.pos += 9);
|
|
2400
|
+
break;
|
|
2401
|
+
}
|
|
2402
|
+
case 3: {
|
|
2403
|
+
// 235
|
|
2404
|
+
const uint8_t* start = source.pos;
|
|
2405
|
+
out.PushRangeUnsafe(start, source.pos += 2);
|
|
2406
|
+
break;
|
|
2407
|
+
}
|
|
2408
|
+
case 10:
|
|
2409
|
+
case 12:
|
|
2410
|
+
case 14:
|
|
2411
|
+
case 15:
|
|
2412
|
+
case 16:
|
|
2413
|
+
case 17:
|
|
2414
|
+
case 19:
|
|
2415
|
+
case 20:
|
|
2416
|
+
case 21:
|
|
2417
|
+
case 22:
|
|
2418
|
+
case 23: {
|
|
2419
|
+
// 242, 244, 246, 247, 248, 249, 251, 252, 253, 254, 255
|
|
2420
|
+
++source.pos;
|
|
2421
|
+
out.PushUnsafe(byte);
|
|
2422
|
+
break;
|
|
2423
|
+
}
|
|
2424
|
+
case 11:
|
|
2425
|
+
case 13: {
|
|
2426
|
+
// 243, 245
|
|
2427
|
+
const uint8_t* start = source.pos++;
|
|
2428
|
+
uint32_t length = 0;
|
|
2429
|
+
ParseNumber(source, length);
|
|
2430
|
+
out.PushRangeUnsafe(start, source.pos += length);
|
|
2431
|
+
break;
|
|
2432
|
+
}
|
|
2433
|
+
case 18: {
|
|
2434
|
+
++source.pos;
|
|
2435
|
+
const uint32_t length = array_lengths_[index_of_array++];
|
|
2436
|
+
AppendArrayPrefix(length, out);
|
|
2437
|
+
break;
|
|
2438
|
+
}
|
|
2439
|
+
}
|
|
2440
|
+
}
|
|
2441
|
+
}
|
|
2442
|
+
}
|
|
2443
|
+
|
|
2444
|
+
void AppendUnrecognizedVariant(const UnrecognizedVariant* input,
|
|
2445
|
+
DenseJson& out) {
|
|
2446
|
+
if (input == nullptr || input->format != UnrecognizedFormat::kDenseJson) {
|
|
2447
|
+
out.out += '0';
|
|
2448
|
+
} else if (input->value == nullptr) {
|
|
2449
|
+
absl::StrAppend(&out.out, input->number);
|
|
2450
|
+
} else {
|
|
2451
|
+
absl::StrAppend(&out.out, "[", input->number, ",");
|
|
2452
|
+
input->value->AppendTo(out);
|
|
2453
|
+
out.out += ']';
|
|
2454
|
+
}
|
|
2455
|
+
}
|
|
2456
|
+
|
|
2457
|
+
void AppendUnrecognizedVariant(const UnrecognizedVariant* input,
|
|
2458
|
+
ByteSink& out) {
|
|
2459
|
+
if (input == nullptr || input->format != UnrecognizedFormat::kBytes) {
|
|
2460
|
+
out.Push(0);
|
|
2461
|
+
} else {
|
|
2462
|
+
const int32_t number = input->number;
|
|
2463
|
+
if (input->value == nullptr) {
|
|
2464
|
+
Int32Adapter::Append(number, out);
|
|
2465
|
+
} else {
|
|
2466
|
+
if (1 <= number && number <= 4) {
|
|
2467
|
+
out.Push(number + 250);
|
|
2468
|
+
} else {
|
|
2469
|
+
out.Push(248);
|
|
2470
|
+
Int32Adapter::Append(number, out);
|
|
2471
|
+
}
|
|
2472
|
+
input->value->AppendTo(out);
|
|
2473
|
+
}
|
|
2474
|
+
}
|
|
2475
|
+
}
|
|
2476
|
+
|
|
2477
|
+
void ParseUnrecognizedFields(JsonArrayReader& array_reader, size_t num_slots,
|
|
2478
|
+
size_t num_slots_incl_removed,
|
|
2479
|
+
std::shared_ptr<UnrecognizedFieldsData>& out) {
|
|
2480
|
+
JsonTokenizer& tokenizer = array_reader.tokenizer();
|
|
2481
|
+
if (tokenizer.keep_unrecognized_values()) {
|
|
2482
|
+
const size_t num_trailing_removed = num_slots_incl_removed - num_slots;
|
|
2483
|
+
for (size_t i = 0; i < num_trailing_removed; ++i) {
|
|
2484
|
+
SkipValue(tokenizer);
|
|
2485
|
+
if (!array_reader.NextElement()) return;
|
|
2486
|
+
}
|
|
2487
|
+
|
|
2488
|
+
out = std::make_shared<UnrecognizedFieldsData>();
|
|
2489
|
+
out->format = UnrecognizedFormat::kDenseJson;
|
|
2490
|
+
out->array_len = num_slots_incl_removed;
|
|
2491
|
+
do {
|
|
2492
|
+
out->values.ParseFrom(tokenizer);
|
|
2493
|
+
++(out->array_len);
|
|
2494
|
+
} while (array_reader.NextElement());
|
|
2495
|
+
} else {
|
|
2496
|
+
do {
|
|
2497
|
+
SkipValue(tokenizer);
|
|
2498
|
+
} while (array_reader.NextElement());
|
|
2499
|
+
}
|
|
2500
|
+
}
|
|
2501
|
+
|
|
2502
|
+
void ParseUnrecognizedFields(ByteSource& source, size_t array_len,
|
|
2503
|
+
size_t num_slots, size_t num_slots_incl_removed,
|
|
2504
|
+
std::shared_ptr<UnrecognizedFieldsData>& out) {
|
|
2505
|
+
if (array_len > num_slots_incl_removed && source.keep_unrecognized_values) {
|
|
2506
|
+
const size_t num_trailing_removed = num_slots_incl_removed - num_slots;
|
|
2507
|
+
SkipValues(source, num_trailing_removed);
|
|
2508
|
+
|
|
2509
|
+
out = std::make_shared<UnrecognizedFieldsData>();
|
|
2510
|
+
out->format = UnrecognizedFormat::kBytes;
|
|
2511
|
+
out->array_len = array_len;
|
|
2512
|
+
for (size_t i = num_slots_incl_removed; i < array_len; ++i) {
|
|
2513
|
+
if (source.error) return;
|
|
2514
|
+
out->values.ParseFrom(source);
|
|
2515
|
+
}
|
|
2516
|
+
} else {
|
|
2517
|
+
SkipValues(source, array_len - num_slots);
|
|
2518
|
+
}
|
|
2519
|
+
}
|
|
2520
|
+
|
|
2521
|
+
absl::Status RequestBody::Parse(absl::string_view request_body) {
|
|
2522
|
+
if (const char first_char = (request_body.empty() ? '\0' : request_body[0]);
|
|
2523
|
+
first_char == '{' || first_char == ' ' || first_char == '\t' ||
|
|
2524
|
+
first_char == '\r' || first_char == '\n') {
|
|
2525
|
+
// A JSON object
|
|
2526
|
+
JsonTokenizer tokenizer(request_body.begin(), request_body.end(),
|
|
2527
|
+
skir::UnrecognizedValuesPolicy::kDrop);
|
|
2528
|
+
if (tokenizer.Next() != JsonTokenType::kLeftCurlyBracket) {
|
|
2529
|
+
return absl::InvalidArgumentError("expected: JSON object");
|
|
2530
|
+
}
|
|
2531
|
+
JsonObjectReader object_reader(&tokenizer);
|
|
2532
|
+
while (object_reader.NextEntry()) {
|
|
2533
|
+
if (object_reader.name() == "method") {
|
|
2534
|
+
const JsonTokenType json_token_type = tokenizer.state().token_type;
|
|
2535
|
+
if (json_token_type == JsonTokenType::kString) {
|
|
2536
|
+
method_name = tokenizer.state().string_value;
|
|
2537
|
+
} else if (json_token_type == JsonTokenType::kUnsignedInteger ||
|
|
2538
|
+
json_token_type == JsonTokenType::kSignedInteger) {
|
|
2539
|
+
method_number =
|
|
2540
|
+
tokenizer.state().token_type == JsonTokenType::kUnsignedInteger
|
|
2541
|
+
? tokenizer.state().uint_value
|
|
2542
|
+
: tokenizer.state().int_value;
|
|
2543
|
+
} else {
|
|
2544
|
+
return absl::InvalidArgumentError(
|
|
2545
|
+
"'method' field must be a string or an integer");
|
|
2546
|
+
}
|
|
2547
|
+
tokenizer.Next();
|
|
2548
|
+
} else if (object_reader.name() == "request") {
|
|
2549
|
+
const char* absl_nullable request_data_begin =
|
|
2550
|
+
tokenizer.state().token_begin;
|
|
2551
|
+
SkipValue(tokenizer);
|
|
2552
|
+
const char* absl_nullable request_data_end =
|
|
2553
|
+
tokenizer.state().token_begin;
|
|
2554
|
+
request_data =
|
|
2555
|
+
request_data_begin != nullptr && request_data_end != nullptr
|
|
2556
|
+
? absl::string_view(request_data_begin,
|
|
2557
|
+
request_data_end - request_data_begin)
|
|
2558
|
+
: absl::string_view();
|
|
2559
|
+
} else {
|
|
2560
|
+
SkipValue(tokenizer);
|
|
2561
|
+
}
|
|
2562
|
+
}
|
|
2563
|
+
return tokenizer.state().status;
|
|
2564
|
+
} else {
|
|
2565
|
+
const std::vector<absl::string_view> parts =
|
|
2566
|
+
absl::StrSplit(request_body, absl::MaxSplits(':', 3));
|
|
2567
|
+
if (parts.size() != 4) {
|
|
2568
|
+
return absl::InvalidArgumentError("invalid request format");
|
|
2569
|
+
}
|
|
2570
|
+
method_name = parts[0];
|
|
2571
|
+
if (!absl::SimpleAtoi(parts[1], &method_number.emplace())) {
|
|
2572
|
+
return absl::InvalidArgumentError("can't parse method number");
|
|
2573
|
+
}
|
|
2574
|
+
readable = parts[2] == "readable";
|
|
2575
|
+
request_data = parts[3];
|
|
2576
|
+
return absl::OkStatus();
|
|
2577
|
+
}
|
|
2578
|
+
}
|
|
2579
|
+
|
|
2580
|
+
void MethodDescriptorAdapter::Append(const MethodDescriptor& input,
|
|
2581
|
+
ReadableJson& out) {
|
|
2582
|
+
JsonObjectWriter(&out)
|
|
2583
|
+
.Write("method", std::string(input.name))
|
|
2584
|
+
.WriteEvenIfDefault("number", input.number)
|
|
2585
|
+
.Write("request", input.request_descriptor_json)
|
|
2586
|
+
.Write("response", input.response_descriptor_json)
|
|
2587
|
+
.Write("doc", input.doc);
|
|
2588
|
+
}
|
|
2589
|
+
|
|
2590
|
+
void MethodListAdapter::Append(const MethodList& input, ReadableJson& out) {
|
|
2591
|
+
JsonObjectWriter(&out).WriteEvenIfDefault("methods", input.methods);
|
|
2592
|
+
}
|
|
2593
|
+
|
|
2594
|
+
} // namespace skir_internal
|
|
2595
|
+
|
|
2596
|
+
namespace skir {
|
|
2597
|
+
namespace reflection {
|
|
2598
|
+
|
|
2599
|
+
std::string TypeDescriptor::AsJson() const {
|
|
2600
|
+
skir_internal::ReadableJson json;
|
|
2601
|
+
skir_internal::Append(*this, json);
|
|
2602
|
+
return std::move(json).out;
|
|
2603
|
+
}
|
|
2604
|
+
|
|
2605
|
+
absl::StatusOr<TypeDescriptor> TypeDescriptor::FromJson(
|
|
2606
|
+
absl::string_view json) {
|
|
2607
|
+
skir_internal::JsonTokenizer tokenizer(json.begin(), json.end(),
|
|
2608
|
+
UnrecognizedValuesPolicy::kDrop);
|
|
2609
|
+
tokenizer.Next();
|
|
2610
|
+
TypeDescriptor result;
|
|
2611
|
+
skir_internal::Parse(tokenizer, result);
|
|
2612
|
+
if (tokenizer.state().token_type != skir_internal::JsonTokenType::kStrEnd) {
|
|
2613
|
+
tokenizer.mutable_state().PushUnexpectedTokenError("end");
|
|
2614
|
+
}
|
|
2615
|
+
const absl::Status status = tokenizer.state().status;
|
|
2616
|
+
if (!status.ok()) return status;
|
|
2617
|
+
return result;
|
|
2618
|
+
}
|
|
2619
|
+
|
|
2620
|
+
} // namespace reflection
|
|
2621
|
+
|
|
2622
|
+
namespace service {
|
|
2623
|
+
|
|
2624
|
+
void HttpHeaders::Insert(absl::string_view name, absl::string_view value) {
|
|
2625
|
+
map_[absl::AsciiStrToLower(name)].emplace_back(value);
|
|
2626
|
+
}
|
|
2627
|
+
|
|
2628
|
+
const std::vector<std::string>& HttpHeaders::Get(absl::string_view name) const {
|
|
2629
|
+
const auto it = map_.find(absl::AsciiStrToLower(name));
|
|
2630
|
+
if (it == map_.cend()) {
|
|
2631
|
+
static const auto* const kResult = new std::vector<std::string>();
|
|
2632
|
+
return *kResult;
|
|
2633
|
+
} else {
|
|
2634
|
+
return it->second;
|
|
2635
|
+
}
|
|
2636
|
+
}
|
|
2637
|
+
|
|
2638
|
+
absl::string_view HttpHeaders::GetLast(absl::string_view name) const {
|
|
2639
|
+
const std::vector<std::string>& values = Get(name);
|
|
2640
|
+
if (values.empty()) {
|
|
2641
|
+
return "";
|
|
2642
|
+
} else {
|
|
2643
|
+
return values.back();
|
|
2644
|
+
}
|
|
2645
|
+
}
|
|
2646
|
+
|
|
2647
|
+
absl::StatusOr<std::string> DecodeUrlQueryString(
|
|
2648
|
+
absl::string_view encoded_query_string) {
|
|
2649
|
+
std::string result;
|
|
2650
|
+
result.reserve(encoded_query_string.length());
|
|
2651
|
+
|
|
2652
|
+
for (size_t i = 0; i < encoded_query_string.length(); i++) {
|
|
2653
|
+
const char c = encoded_query_string[i];
|
|
2654
|
+
switch (c) {
|
|
2655
|
+
case '%': {
|
|
2656
|
+
if (i + 2 >= encoded_query_string.length()) {
|
|
2657
|
+
goto invalid_escape_sequence;
|
|
2658
|
+
}
|
|
2659
|
+
const int hi =
|
|
2660
|
+
skir_internal::HexDigitToInt(encoded_query_string[i + 1]);
|
|
2661
|
+
const int lo =
|
|
2662
|
+
skir_internal::HexDigitToInt(encoded_query_string[i + 2]);
|
|
2663
|
+
if (hi < 0 || lo < 0) {
|
|
2664
|
+
goto invalid_escape_sequence;
|
|
2665
|
+
}
|
|
2666
|
+
const uint8_t c = hi << 4 | lo;
|
|
2667
|
+
result += static_cast<char>(c);
|
|
2668
|
+
i += 2;
|
|
2669
|
+
break;
|
|
2670
|
+
}
|
|
2671
|
+
case '+':
|
|
2672
|
+
result += ' ';
|
|
2673
|
+
break;
|
|
2674
|
+
default:
|
|
2675
|
+
result += c;
|
|
2676
|
+
break;
|
|
2677
|
+
}
|
|
2678
|
+
}
|
|
2679
|
+
|
|
2680
|
+
return result;
|
|
2681
|
+
|
|
2682
|
+
invalid_escape_sequence:
|
|
2683
|
+
return absl::InvalidArgumentError("Invalid escape sequence");
|
|
2684
|
+
}
|
|
2685
|
+
|
|
2686
|
+
} // namespace service
|
|
2687
|
+
} // namespace skir
|