json-as 0.8.6 → 0.8.8
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/CHANGELOG +2 -1
- package/assembly/__benches__/as-json.ts +1 -1
- package/assembly/deserialize/array/array.ts +31 -0
- package/assembly/deserialize/array/bool.ts +19 -0
- package/assembly/deserialize/array/float.ts +24 -0
- package/assembly/deserialize/array/integer.ts +24 -0
- package/assembly/deserialize/array/map.ts +27 -0
- package/assembly/deserialize/array/object.ts +27 -0
- package/assembly/deserialize/array/string.ts +29 -0
- package/assembly/deserialize/array.ts +37 -0
- package/assembly/deserialize/bool.ts +18 -0
- package/assembly/deserialize/box.ts +14 -0
- package/assembly/deserialize/date.ts +11 -0
- package/assembly/deserialize/float.ts +9 -0
- package/assembly/deserialize/integer.ts +7 -0
- package/assembly/deserialize/map.ts +182 -0
- package/assembly/deserialize/object.ts +139 -0
- package/assembly/deserialize/string.ts +88 -0
- package/assembly/serialize/array.ts +51 -0
- package/assembly/serialize/bool.ts +4 -0
- package/assembly/serialize/box.ts +10 -0
- package/assembly/serialize/date.ts +4 -0
- package/assembly/serialize/float.ts +4 -0
- package/assembly/serialize/integer.ts +5 -0
- package/assembly/serialize/map.ts +24 -0
- package/assembly/serialize/object.ts +7 -0
- package/assembly/serialize/string.ts +64 -0
- package/assembly/src/json.ts +55 -872
- package/assembly/src/sink.ts +286 -0
- package/assembly/src/util.ts +6 -0
- package/assembly/test.ts +8 -1
- package/package.json +1 -1
- package/transform/lib/index.js +3 -3
- package/transform/package.json +1 -1
- package/transform/src/index.ts +3 -3
package/assembly/src/json.ts
CHANGED
|
@@ -1,48 +1,23 @@
|
|
|
1
|
-
import { StringSink } from "as-string-sink/assembly";
|
|
2
|
-
import { isSpace } from "util/string";
|
|
3
|
-
import {
|
|
4
|
-
aCode,
|
|
5
|
-
bCode,
|
|
6
|
-
eCode,
|
|
7
|
-
fCode,
|
|
8
|
-
lCode,
|
|
9
|
-
nCode,
|
|
10
|
-
rCode,
|
|
11
|
-
sCode,
|
|
12
|
-
tCode,
|
|
13
|
-
uCode,
|
|
14
|
-
|
|
15
|
-
backSlashCode,
|
|
16
|
-
colonCode,
|
|
17
|
-
commaCode,
|
|
18
|
-
forwardSlashCode,
|
|
19
|
-
leftBraceCode,
|
|
20
|
-
leftBracketCode,
|
|
21
|
-
quoteCode,
|
|
22
|
-
rightBraceCode,
|
|
23
|
-
rightBracketCode,
|
|
24
|
-
|
|
25
|
-
backspaceCode,
|
|
26
|
-
carriageReturnCode,
|
|
27
|
-
tabCode,
|
|
28
|
-
formFeedCode,
|
|
29
|
-
newLineCode,
|
|
30
|
-
|
|
31
|
-
commaWord,
|
|
32
|
-
quoteWord,
|
|
33
|
-
|
|
34
|
-
leftBraceWord,
|
|
35
|
-
leftBracketWord,
|
|
36
|
-
rightBracketWord,
|
|
37
|
-
emptyArrayWord,
|
|
38
|
-
|
|
39
|
-
trueWord,
|
|
40
|
-
falseWord,
|
|
41
|
-
nullWord,
|
|
42
|
-
} from "./chars";
|
|
43
|
-
import { snip_fast, unsafeCharCodeAt, containsCodePoint } from "./util";
|
|
44
|
-
import { Virtual } from "as-virtual/assembly";
|
|
45
1
|
import { Box } from "as-container/assembly";
|
|
2
|
+
import { serializeString } from "../serialize/string";
|
|
3
|
+
import { serializeBool } from "../serialize/bool";
|
|
4
|
+
import { serializeBox } from "../serialize/box";
|
|
5
|
+
import { serializeInteger } from "../serialize/integer";
|
|
6
|
+
import { serializeFloat } from "../serialize/float";
|
|
7
|
+
import { serializeObject } from "../serialize/object";
|
|
8
|
+
import { serializeDate } from "../serialize/date";
|
|
9
|
+
import { serializeArray } from "../serialize/array";
|
|
10
|
+
import { serializeMap } from "../serialize/map";
|
|
11
|
+
import { deserializeBoolean } from "../deserialize/bool";
|
|
12
|
+
import { deserializeArray } from "../deserialize/array";
|
|
13
|
+
import { deserializeFloat } from "../deserialize/float";
|
|
14
|
+
import { deserializeBox } from "../deserialize/box";
|
|
15
|
+
import { deserializeObject } from "../deserialize/object";
|
|
16
|
+
import { deserializeMap } from "../deserialize/map";
|
|
17
|
+
import { deserializeDate } from "../deserialize/date";
|
|
18
|
+
import { nullWord } from "./chars";
|
|
19
|
+
import { deserializeInteger } from "../deserialize/integer";
|
|
20
|
+
import { deserializeString } from "../deserialize/string";
|
|
46
21
|
|
|
47
22
|
/**
|
|
48
23
|
* JSON Encoder/Decoder for AssemblyScript
|
|
@@ -51,101 +26,44 @@ export namespace JSON {
|
|
|
51
26
|
/**
|
|
52
27
|
* Stringifies valid JSON data.
|
|
53
28
|
* ```js
|
|
54
|
-
*
|
|
29
|
+
* JSON.stringify<T>(data)
|
|
55
30
|
* ```
|
|
56
31
|
* @param data T
|
|
57
32
|
* @returns string
|
|
58
33
|
*/
|
|
59
34
|
// @ts-ignore: Decorator
|
|
60
35
|
@inline export function stringify<T>(data: T): string {
|
|
61
|
-
|
|
62
|
-
|
|
36
|
+
if (isNullable<T>() && changetype<usize>(data) == <usize>0) {
|
|
37
|
+
return nullWord;
|
|
38
|
+
// @ts-ignore
|
|
39
|
+
} else if (isString<T>()) {
|
|
63
40
|
return serializeString(data as string);
|
|
64
41
|
} else if (isBoolean<T>()) {
|
|
65
|
-
return data
|
|
42
|
+
return serializeBool(data as bool);
|
|
66
43
|
} else if (data instanceof Box) {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
}
|
|
70
|
-
return JSON.stringify(data.unwrap());
|
|
71
|
-
} else if (isNullable<T>() && changetype<usize>(data) == <usize>0) {
|
|
72
|
-
return nullWord;
|
|
44
|
+
return serializeBox(data);
|
|
45
|
+
} else if (isInteger<T>()) {
|
|
73
46
|
// @ts-ignore
|
|
74
|
-
|
|
47
|
+
return serializeInteger<T>(data);
|
|
48
|
+
} else if (isFloat<T>(data)) {
|
|
75
49
|
// @ts-ignore
|
|
76
|
-
return data
|
|
77
|
-
// @ts-ignore:
|
|
78
|
-
} else if (isDefined(data.
|
|
79
|
-
// @ts-ignore: Hidden function
|
|
80
|
-
return data.__JSON_Serialize();
|
|
81
|
-
} else if (data instanceof Date) {
|
|
82
|
-
return `"${data.toISOString()}"`;
|
|
83
|
-
} else if (isArrayLike<T>()) {
|
|
50
|
+
return serializeFloat<T>(data);
|
|
51
|
+
// @ts-ignore: Function is generated by transform
|
|
52
|
+
} else if (isDefined(data.__SERIALIZE())) {
|
|
84
53
|
// @ts-ignore
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
// @ts-ignore
|
|
91
|
-
for (let i = 0; i < data.length - 1; i++) {
|
|
92
|
-
// @ts-ignore
|
|
93
|
-
result += serializeString(unchecked(data[i]));
|
|
94
|
-
result += commaWord;
|
|
95
|
-
}
|
|
96
|
-
// @ts-ignore
|
|
97
|
-
result += serializeString(unchecked(data[data.length - 1]));
|
|
98
|
-
result += rightBracketWord;
|
|
99
|
-
return result;
|
|
100
|
-
// @ts-ignore
|
|
101
|
-
} else if (isBoolean<valueof<T>>()) {
|
|
102
|
-
// @ts-ignore
|
|
103
|
-
return leftBracketWord + data.join(commaWord) + rightBracketWord;
|
|
104
|
-
// @ts-ignore
|
|
105
|
-
} else if (isFloat<valueof<T>>() || isInteger<valueof<T>>()) {
|
|
106
|
-
// @ts-ignore
|
|
107
|
-
return leftBracketWord + data.join(commaWord) + rightBracketWord;
|
|
108
|
-
} else {
|
|
109
|
-
let result = new StringSink(leftBracketWord);
|
|
110
|
-
// @ts-ignore
|
|
111
|
-
for (let i = 0; i < data.length - 1; i++) {
|
|
112
|
-
// @ts-ignore
|
|
113
|
-
result.write(__JSON_Stringify(unchecked(data[i])));
|
|
114
|
-
result.writeCodePoint(commaCode);
|
|
115
|
-
}
|
|
116
|
-
// @ts-ignore
|
|
117
|
-
result.write(__JSON_Stringify(unchecked(data[data.length - 1])));
|
|
118
|
-
result.writeCodePoint(rightBracketCode);
|
|
119
|
-
return result.toString();
|
|
120
|
-
}
|
|
54
|
+
return serializeObject(data);
|
|
55
|
+
} else if (data instanceof Date) {
|
|
56
|
+
return serializeDate(data);
|
|
57
|
+
} else if (data instanceof Array) {
|
|
58
|
+
return serializeArray(data);
|
|
121
59
|
} else if (data instanceof Map) {
|
|
122
|
-
|
|
123
|
-
let keys = data.keys();
|
|
124
|
-
let values = data.values();
|
|
125
|
-
const end = data.size - 1;
|
|
126
|
-
for (let i = 0; i < end; i++) {
|
|
127
|
-
result.write(serializeString(unchecked(keys[i]).toString()));
|
|
128
|
-
result.writeCodePoint(colonCode);
|
|
129
|
-
result.write(__JSON_Stringify(unchecked(values[i])));
|
|
130
|
-
result.writeCodePoint(commaCode);
|
|
131
|
-
}
|
|
132
|
-
result.write(serializeString(unchecked(keys[end]).toString()));
|
|
133
|
-
result.writeCodePoint(colonCode);
|
|
134
|
-
result.write(__JSON_Stringify(unchecked(values[end])));
|
|
135
|
-
|
|
136
|
-
result.writeCodePoint(rightBraceCode);
|
|
137
|
-
return result.toString();
|
|
60
|
+
return serializeMap(data);
|
|
138
61
|
} else {
|
|
139
62
|
throw new Error(
|
|
140
63
|
`Could not serialize data of type ${nameof<T>()}. Make sure to add the correct decorators to classes.`
|
|
141
64
|
);
|
|
142
65
|
}
|
|
143
66
|
}
|
|
144
|
-
// @ts-ignore: Decorator
|
|
145
|
-
@unsafe
|
|
146
|
-
@inline export function stringifyTo<T>(data: T, out: string): void {
|
|
147
|
-
throw new Error("Method is deprecated");
|
|
148
|
-
}
|
|
149
67
|
/**
|
|
150
68
|
* Parses valid JSON strings into their original format.
|
|
151
69
|
* ```js
|
|
@@ -159,35 +77,31 @@ export namespace JSON {
|
|
|
159
77
|
@inline export function parse<T>(data: string, initializeDefaultValues: boolean = false): T {
|
|
160
78
|
if (isString<T>()) {
|
|
161
79
|
// @ts-ignore
|
|
162
|
-
return
|
|
80
|
+
return deserializeString(data);
|
|
163
81
|
} else if (isBoolean<T>()) {
|
|
82
|
+
return deserializeBoolean(data) as T;
|
|
83
|
+
} else if (isInteger<T>()) {
|
|
84
|
+
return deserializeInteger<T>(data);
|
|
85
|
+
} else if (isFloat<T>()) {
|
|
86
|
+
return deserializeFloat<T>(data);
|
|
87
|
+
} else if (isArray<T>()) {
|
|
164
88
|
// @ts-ignore
|
|
165
|
-
return
|
|
166
|
-
} else if (isFloat<T>() || isInteger<T>()) {
|
|
167
|
-
return parseNumber<T>(data);
|
|
168
|
-
} else if (isArrayLike<T>()) {
|
|
169
|
-
// @ts-ignore
|
|
170
|
-
return parseArray<T>(data.trimStart());
|
|
171
|
-
// @ts-ignore
|
|
89
|
+
return deserializeArray<T>(data);
|
|
172
90
|
}
|
|
173
91
|
let type: nonnull<T> = changetype<nonnull<T>>(0);
|
|
174
92
|
if (type instanceof Box) {
|
|
175
|
-
|
|
176
|
-
const val = instance._val;
|
|
177
|
-
instance._val = parseDirectInference(val, data);
|
|
178
|
-
// @ts-ignore
|
|
179
|
-
return changetype<T>(instance);
|
|
93
|
+
return deserializeBox<T>(data);
|
|
180
94
|
} else if (isNullable<T>() && data == nullWord) {
|
|
181
95
|
// @ts-ignore
|
|
182
96
|
return null;
|
|
183
97
|
// @ts-ignore
|
|
184
98
|
} else if (isDefined(type.__JSON_Set_Key)) {
|
|
185
|
-
return
|
|
186
|
-
} else if (
|
|
187
|
-
return
|
|
188
|
-
} else if (
|
|
99
|
+
return deserializeObject<T>(data.trimStart(), initializeDefaultValues);
|
|
100
|
+
} else if (type instanceof Map) {
|
|
101
|
+
return deserializeMap<T>(data.trimStart());
|
|
102
|
+
} else if (type instanceof Date) {
|
|
189
103
|
// @ts-ignore
|
|
190
|
-
return
|
|
104
|
+
return deserializeDate(data);
|
|
191
105
|
} else {
|
|
192
106
|
throw new Error(
|
|
193
107
|
`Could not deserialize data ${data} to type ${nameof<T>()}. Make sure to add the correct decorators to classes.`
|
|
@@ -198,744 +112,13 @@ export namespace JSON {
|
|
|
198
112
|
|
|
199
113
|
// @ts-ignore: Decorator
|
|
200
114
|
@global @inline function __parseObjectValue<T>(data: string, initializeDefaultValues: boolean): T {
|
|
201
|
-
if (isString<T>()) {
|
|
202
|
-
// @ts-ignore
|
|
203
|
-
return data;
|
|
204
|
-
} else if (isBoolean<T>()) {
|
|
205
|
-
// @ts-ignore
|
|
206
|
-
return parseBoolean<T>(data);
|
|
207
|
-
} else if (isFloat<T>() || isInteger<T>()) {
|
|
208
|
-
return parseNumber<T>(data);
|
|
209
|
-
} else if (isArrayLike<T>()) {
|
|
210
|
-
// @ts-ignore
|
|
211
|
-
return parseArray<T>(data);
|
|
212
|
-
// @ts-ignore
|
|
213
|
-
}
|
|
214
|
-
let type: nonnull<T> = changetype<nonnull<T>>(0);
|
|
215
|
-
if (type instanceof Box) {
|
|
216
|
-
const instance = changetype<nonnull<T>>(__new(offsetof<nonnull<T>>(), idof<nonnull<T>>()))// as Box<usize>;
|
|
217
|
-
const val = instance._val;
|
|
218
|
-
instance._val = parseDirectInference(val, data);
|
|
219
|
-
// @ts-ignore
|
|
220
|
-
return changetype<T>(instance);
|
|
221
|
-
} else if (isNullable<T>() && data == nullWord) {
|
|
222
|
-
// @ts-ignore
|
|
223
|
-
return null;
|
|
224
|
-
// @ts-ignore
|
|
225
|
-
} else if (isDefined(type.__JSON_Set_Key)) {
|
|
226
|
-
return parseObject<T>(data.trimStart(), initializeDefaultValues);
|
|
227
|
-
} else if (isMap<T>()) {
|
|
228
|
-
return parseMap<T>(data.trimStart(), initializeDefaultValues);
|
|
229
|
-
} else if (idof<nonnull<T>>() == idof<Date>()) {
|
|
230
|
-
// @ts-ignore
|
|
231
|
-
return parseDate(data);
|
|
232
|
-
} else {
|
|
233
|
-
throw new Error(
|
|
234
|
-
`Could not deserialize data ${data} to type ${nameof<T>()}. Make sure to add the correct decorators to classes.`
|
|
235
|
-
);
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
// @ts-ignore: Decorator
|
|
240
|
-
@inline function serializeString(data: string): string {
|
|
241
|
-
if (data.length === 0) {
|
|
242
|
-
return quoteWord + quoteWord;
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
let result = new StringSink(quoteWord);
|
|
246
|
-
|
|
247
|
-
let last: i32 = 0;
|
|
248
|
-
for (let i = 0; i < data.length; i++) {
|
|
249
|
-
const char = unsafeCharCodeAt(<string>data, i);
|
|
250
|
-
if (char === quoteCode || char === backSlashCode) {
|
|
251
|
-
result.write(<string>data, last, i);
|
|
252
|
-
result.writeCodePoint(backSlashCode);
|
|
253
|
-
last = i;
|
|
254
|
-
} else if (char < 16) {
|
|
255
|
-
result.write(<string>data, last, i);
|
|
256
|
-
last = i + 1;
|
|
257
|
-
switch (char) {
|
|
258
|
-
case backspaceCode: {
|
|
259
|
-
result.write("\\b");
|
|
260
|
-
break;
|
|
261
|
-
}
|
|
262
|
-
case tabCode: {
|
|
263
|
-
result.write("\\t");
|
|
264
|
-
break;
|
|
265
|
-
}
|
|
266
|
-
case newLineCode: {
|
|
267
|
-
result.write("\\n");
|
|
268
|
-
break;
|
|
269
|
-
}
|
|
270
|
-
case formFeedCode: {
|
|
271
|
-
result.write("\\f");
|
|
272
|
-
break;
|
|
273
|
-
}
|
|
274
|
-
case carriageReturnCode: {
|
|
275
|
-
result.write("\\r");
|
|
276
|
-
break;
|
|
277
|
-
}
|
|
278
|
-
default: {
|
|
279
|
-
// all chars 0-31 must be encoded as a four digit unicode escape sequence
|
|
280
|
-
// \u0000 to \u000f handled here
|
|
281
|
-
result.write("\\u000");
|
|
282
|
-
result.write(char.toString(16));
|
|
283
|
-
break;
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
} else if (char < 32) {
|
|
287
|
-
result.write(<string>data, last, i);
|
|
288
|
-
last = i + 1;
|
|
289
|
-
// all chars 0-31 must be encoded as a four digit unicode escape sequence
|
|
290
|
-
// \u0010 to \u001f handled here
|
|
291
|
-
result.write("\\u00");
|
|
292
|
-
result.write(char.toString(16));
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
result.write(<string>data, last);
|
|
296
|
-
result.writeCodePoint(quoteCode);
|
|
297
|
-
return result.toString();
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
// @ts-ignore: Decorator
|
|
301
|
-
@inline function parseString(data: string, start: i32 = 0, end: i32 = 0): string {
|
|
302
|
-
end = end || data.length - 1;
|
|
303
|
-
let result = StringSink.withCapacity(end - start - 1);
|
|
304
|
-
let last = start + 1;
|
|
305
|
-
for (let i = last; i < end; i++) {
|
|
306
|
-
if (unsafeCharCodeAt(data, i) !== backSlashCode) {
|
|
307
|
-
continue;
|
|
308
|
-
}
|
|
309
|
-
const char = unsafeCharCodeAt(data, ++i);
|
|
310
|
-
result.write(data, last, i - 1);
|
|
311
|
-
switch (char) {
|
|
312
|
-
case quoteCode: {
|
|
313
|
-
result.writeCodePoint(quoteCode);
|
|
314
|
-
last = i + 1;
|
|
315
|
-
break;
|
|
316
|
-
}
|
|
317
|
-
case backSlashCode: {
|
|
318
|
-
result.writeCodePoint(backSlashCode);
|
|
319
|
-
last = i + 1;
|
|
320
|
-
break;
|
|
321
|
-
}
|
|
322
|
-
case forwardSlashCode: {
|
|
323
|
-
result.writeCodePoint(forwardSlashCode);
|
|
324
|
-
last = i + 1;
|
|
325
|
-
break;
|
|
326
|
-
}
|
|
327
|
-
case bCode: {
|
|
328
|
-
result.writeCodePoint(backspaceCode);
|
|
329
|
-
last = i + 1;
|
|
330
|
-
break;
|
|
331
|
-
}
|
|
332
|
-
case fCode: {
|
|
333
|
-
result.writeCodePoint(formFeedCode);
|
|
334
|
-
last = i + 1;
|
|
335
|
-
break;
|
|
336
|
-
}
|
|
337
|
-
case nCode: {
|
|
338
|
-
result.writeCodePoint(newLineCode);
|
|
339
|
-
last = i + 1;
|
|
340
|
-
break;
|
|
341
|
-
}
|
|
342
|
-
case rCode: {
|
|
343
|
-
result.writeCodePoint(carriageReturnCode);
|
|
344
|
-
last = i + 1;
|
|
345
|
-
break;
|
|
346
|
-
}
|
|
347
|
-
case tCode: {
|
|
348
|
-
result.writeCodePoint(tabCode);
|
|
349
|
-
last = i + 1;
|
|
350
|
-
break;
|
|
351
|
-
}
|
|
352
|
-
case uCode: {
|
|
353
|
-
const code = u16.parse(data.slice(i + 1, i + 5), 16);
|
|
354
|
-
result.writeCodePoint(code);
|
|
355
|
-
i += 4;
|
|
356
|
-
last = i + 1;
|
|
357
|
-
break;
|
|
358
|
-
}
|
|
359
|
-
default: {
|
|
360
|
-
throw new Error(`JSON: Cannot parse "${data}" as string. Invalid escape sequence: \\${data.charAt(i)}`);
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
if (end > last) {
|
|
365
|
-
result.write(data, last, end);
|
|
366
|
-
}
|
|
367
|
-
return result.toString()
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
// @ts-ignore: Decorator
|
|
371
|
-
@inline function parseBoolean<T extends boolean>(data: string): T {
|
|
372
|
-
if (data.length > 3 && data.startsWith(trueWord)) return <T>true;
|
|
373
|
-
else if (data.length > 4 && data.startsWith(falseWord)) return <T>false;
|
|
374
|
-
else throw new Error(`JSON: Cannot parse "${data}" as boolean`);
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
// @ts-ignore: Decorator
|
|
378
|
-
@inline function parseNumber<T>(data: string): T {
|
|
379
|
-
if (isInteger<T>()) {
|
|
380
|
-
// @ts-ignore
|
|
381
|
-
return snip_fast<T>(data);
|
|
382
|
-
}
|
|
383
|
-
// @ts-ignore
|
|
384
|
-
const type: T = 0;
|
|
385
115
|
// @ts-ignore
|
|
386
|
-
if (
|
|
387
|
-
|
|
388
|
-
else if (type instanceof f32) return f32.parse(data);
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
// @ts-ignore: Decorator
|
|
392
|
-
@inline function parseNumberDirectInference<T>(type: T, data: string): T {
|
|
393
|
-
if (isInteger(type)) {
|
|
394
|
-
// @ts-ignore
|
|
395
|
-
return snip_fast<T>(data);
|
|
396
|
-
}
|
|
397
|
-
// @ts-ignore
|
|
398
|
-
if (type instanceof f64) return f64.parse(data);
|
|
399
|
-
// @ts-ignore
|
|
400
|
-
else if (type instanceof f32) return f32.parse(data);
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
// @ts-ignore: Decorator
|
|
404
|
-
@inline function parseObject<T>(data: string, initializeDefaultValues: boolean): T {
|
|
405
|
-
const schema: nonnull<T> = changetype<nonnull<T>>(
|
|
406
|
-
__new(offsetof<nonnull<T>>(), idof<nonnull<T>>())
|
|
407
|
-
);
|
|
408
|
-
|
|
409
|
-
// @ts-ignore
|
|
410
|
-
if (initializeDefaultValues) schema.__JSON_Initialize();
|
|
411
|
-
|
|
412
|
-
const key = Virtual.createEmpty<string>();
|
|
413
|
-
let isKey = false;
|
|
414
|
-
let depth = 0;
|
|
415
|
-
let outerLoopIndex = 1;
|
|
416
|
-
for (; outerLoopIndex < data.length - 1; outerLoopIndex++) {
|
|
417
|
-
const char = unsafeCharCodeAt(data, outerLoopIndex);
|
|
418
|
-
if (char === leftBracketCode) {
|
|
419
|
-
for (
|
|
420
|
-
let arrayValueIndex = outerLoopIndex;
|
|
421
|
-
arrayValueIndex < data.length - 1;
|
|
422
|
-
arrayValueIndex++
|
|
423
|
-
) {
|
|
424
|
-
const char = unsafeCharCodeAt(data, arrayValueIndex);
|
|
425
|
-
if (char === leftBracketCode) {
|
|
426
|
-
depth++;
|
|
427
|
-
} else if (char === rightBracketCode) {
|
|
428
|
-
depth--;
|
|
429
|
-
if (depth === 0) {
|
|
430
|
-
++arrayValueIndex;
|
|
431
|
-
// @ts-ignore
|
|
432
|
-
schema.__JSON_Set_Key(key, data, outerLoopIndex, arrayValueIndex, initializeDefaultValues);
|
|
433
|
-
outerLoopIndex = arrayValueIndex;
|
|
434
|
-
isKey = false;
|
|
435
|
-
break;
|
|
436
|
-
}
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
} else if (char === leftBraceCode) {
|
|
440
|
-
for (
|
|
441
|
-
let objectValueIndex = outerLoopIndex;
|
|
442
|
-
objectValueIndex < data.length - 1;
|
|
443
|
-
objectValueIndex++
|
|
444
|
-
) {
|
|
445
|
-
const char = unsafeCharCodeAt(data, objectValueIndex);
|
|
446
|
-
if (char === leftBraceCode) {
|
|
447
|
-
depth++;
|
|
448
|
-
} else if (char === rightBraceCode) {
|
|
449
|
-
depth--;
|
|
450
|
-
if (depth === 0) {
|
|
451
|
-
++objectValueIndex;
|
|
452
|
-
// @ts-ignore
|
|
453
|
-
schema.__JSON_Set_Key(key, data, outerLoopIndex, objectValueIndex, initializeDefaultValues);
|
|
454
|
-
outerLoopIndex = objectValueIndex;
|
|
455
|
-
isKey = false;
|
|
456
|
-
break;
|
|
457
|
-
}
|
|
458
|
-
}
|
|
459
|
-
}
|
|
460
|
-
} else if (char === quoteCode) {
|
|
461
|
-
let escaping = false;
|
|
462
|
-
for (
|
|
463
|
-
let stringValueIndex = ++outerLoopIndex;
|
|
464
|
-
stringValueIndex < data.length - 1;
|
|
465
|
-
stringValueIndex++
|
|
466
|
-
) {
|
|
467
|
-
const char = unsafeCharCodeAt(data, stringValueIndex);
|
|
468
|
-
if (char === backSlashCode && !escaping) {
|
|
469
|
-
escaping = true;
|
|
470
|
-
} else {
|
|
471
|
-
if (char === quoteCode && !escaping) {
|
|
472
|
-
if (isKey === false) {
|
|
473
|
-
// perf: we can avoid creating a new string here if the key doesn't contain any escape sequences
|
|
474
|
-
if (containsCodePoint(data, backSlashCode, outerLoopIndex, stringValueIndex)) {
|
|
475
|
-
key.reinst(parseString(data, outerLoopIndex - 1, stringValueIndex));
|
|
476
|
-
} else {
|
|
477
|
-
key.reinst(data, outerLoopIndex, stringValueIndex);
|
|
478
|
-
}
|
|
479
|
-
isKey = true;
|
|
480
|
-
} else {
|
|
481
|
-
const value = parseString(data, outerLoopIndex - 1, stringValueIndex);
|
|
482
|
-
// @ts-ignore
|
|
483
|
-
schema.__JSON_Set_Key(key, value, 0, value.length, initializeDefaultValues);
|
|
484
|
-
isKey = false;
|
|
485
|
-
}
|
|
486
|
-
outerLoopIndex = ++stringValueIndex;
|
|
487
|
-
break;
|
|
488
|
-
}
|
|
489
|
-
escaping = false;
|
|
490
|
-
}
|
|
491
|
-
}
|
|
492
|
-
} else if (
|
|
493
|
-
char == nCode &&
|
|
494
|
-
unsafeCharCodeAt(data, ++outerLoopIndex) === uCode &&
|
|
495
|
-
unsafeCharCodeAt(data, ++outerLoopIndex) === lCode &&
|
|
496
|
-
unsafeCharCodeAt(data, ++outerLoopIndex) === lCode
|
|
497
|
-
) {
|
|
498
|
-
// @ts-ignore
|
|
499
|
-
schema.__JSON_Set_Key(key, nullWord, 0, 4, initializeDefaultValues);
|
|
500
|
-
isKey = false;
|
|
501
|
-
} else if (
|
|
502
|
-
char === tCode &&
|
|
503
|
-
unsafeCharCodeAt(data, ++outerLoopIndex) === rCode &&
|
|
504
|
-
unsafeCharCodeAt(data, ++outerLoopIndex) === uCode &&
|
|
505
|
-
unsafeCharCodeAt(data, ++outerLoopIndex) === eCode
|
|
506
|
-
) {
|
|
507
|
-
// @ts-ignore
|
|
508
|
-
schema.__JSON_Set_Key(key, trueWord, 0, 4, initializeDefaultValues);
|
|
509
|
-
isKey = false;
|
|
510
|
-
} else if (
|
|
511
|
-
char === fCode &&
|
|
512
|
-
unsafeCharCodeAt(data, ++outerLoopIndex) === aCode &&
|
|
513
|
-
unsafeCharCodeAt(data, ++outerLoopIndex) === lCode &&
|
|
514
|
-
unsafeCharCodeAt(data, ++outerLoopIndex) === sCode &&
|
|
515
|
-
unsafeCharCodeAt(data, ++outerLoopIndex) === eCode
|
|
516
|
-
) {
|
|
517
|
-
// @ts-ignore
|
|
518
|
-
schema.__JSON_Set_Key(key, falseWord, 0, 5, initializeDefaultValues);
|
|
519
|
-
isKey = false;
|
|
520
|
-
} else if ((char >= 48 && char <= 57) || char === 45) {
|
|
521
|
-
let numberValueIndex = ++outerLoopIndex;
|
|
522
|
-
for (; numberValueIndex < data.length; numberValueIndex++) {
|
|
523
|
-
const char = unsafeCharCodeAt(data, numberValueIndex);
|
|
524
|
-
if (char === commaCode || char === rightBraceCode || isSpace(char)) {
|
|
525
|
-
// @ts-ignore
|
|
526
|
-
schema.__JSON_Set_Key(key, data, outerLoopIndex - 1, numberValueIndex, initializeDefaultValues);
|
|
527
|
-
outerLoopIndex = numberValueIndex;
|
|
528
|
-
isKey = false;
|
|
529
|
-
break;
|
|
530
|
-
}
|
|
531
|
-
}
|
|
532
|
-
}
|
|
533
|
-
}
|
|
534
|
-
return schema;
|
|
535
|
-
}
|
|
536
|
-
|
|
537
|
-
// @ts-ignore: Decorator
|
|
538
|
-
@inline function parseMap<T extends Map>(data: string, initializeDefaultValues: boolean): T {
|
|
539
|
-
|
|
540
|
-
const map: nonnull<T> = changetype<nonnull<T>>(
|
|
541
|
-
__new(offsetof<nonnull<T>>(), idof<nonnull<T>>())
|
|
542
|
-
);
|
|
543
|
-
|
|
544
|
-
if (!isDefined(map.set)) {
|
|
545
|
-
throw new Error("Tried to parse a map, but the types did not match!")
|
|
546
|
-
}
|
|
547
|
-
|
|
548
|
-
const key = Virtual.createEmpty<string>();
|
|
549
|
-
let isKey = false;
|
|
550
|
-
let depth = 0;
|
|
551
|
-
let outerLoopIndex = 1;
|
|
552
|
-
for (; outerLoopIndex < data.length - 1; outerLoopIndex++) {
|
|
553
|
-
const char = unsafeCharCodeAt(data, outerLoopIndex);
|
|
554
|
-
if (char === leftBracketCode) {
|
|
555
|
-
for (
|
|
556
|
-
let arrayValueIndex = outerLoopIndex;
|
|
557
|
-
arrayValueIndex < data.length - 1;
|
|
558
|
-
arrayValueIndex++
|
|
559
|
-
) {
|
|
560
|
-
const char = unsafeCharCodeAt(data, arrayValueIndex);
|
|
561
|
-
if (char === leftBracketCode) {
|
|
562
|
-
depth++;
|
|
563
|
-
} else if (char === rightBracketCode) {
|
|
564
|
-
depth--;
|
|
565
|
-
if (depth === 0) {
|
|
566
|
-
++arrayValueIndex;
|
|
567
|
-
map.set(parseMapKey<indexof<T>>(key), JSON.parse<valueof<T>>(data.slice(outerLoopIndex, arrayValueIndex), initializeDefaultValues));
|
|
568
|
-
outerLoopIndex = arrayValueIndex;
|
|
569
|
-
isKey = false;
|
|
570
|
-
break;
|
|
571
|
-
}
|
|
572
|
-
}
|
|
573
|
-
}
|
|
574
|
-
} else if (char === leftBraceCode) {
|
|
575
|
-
for (
|
|
576
|
-
let objectValueIndex = outerLoopIndex;
|
|
577
|
-
objectValueIndex < data.length - 1;
|
|
578
|
-
objectValueIndex++
|
|
579
|
-
) {
|
|
580
|
-
const char = unsafeCharCodeAt(data, objectValueIndex);
|
|
581
|
-
if (char === leftBraceCode) {
|
|
582
|
-
depth++;
|
|
583
|
-
} else if (char === rightBraceCode) {
|
|
584
|
-
depth--;
|
|
585
|
-
if (depth === 0) {
|
|
586
|
-
++objectValueIndex;
|
|
587
|
-
map.set(parseMapKey<indexof<T>>(key), JSON.parse<valueof<T>>(data.slice(outerLoopIndex, objectValueIndex), initializeDefaultValues));
|
|
588
|
-
outerLoopIndex = objectValueIndex;
|
|
589
|
-
isKey = false;
|
|
590
|
-
break;
|
|
591
|
-
}
|
|
592
|
-
}
|
|
593
|
-
}
|
|
594
|
-
} else if (char === quoteCode) {
|
|
595
|
-
let escaping = false;
|
|
596
|
-
for (
|
|
597
|
-
let stringValueIndex = ++outerLoopIndex;
|
|
598
|
-
stringValueIndex < data.length - 1;
|
|
599
|
-
stringValueIndex++
|
|
600
|
-
) {
|
|
601
|
-
const char = unsafeCharCodeAt(data, stringValueIndex);
|
|
602
|
-
if (char === backSlashCode && !escaping) {
|
|
603
|
-
escaping = true;
|
|
604
|
-
} else {
|
|
605
|
-
if (
|
|
606
|
-
char === quoteCode && !escaping
|
|
607
|
-
) {
|
|
608
|
-
if (isKey === false) {
|
|
609
|
-
// perf: we can avoid creating a new string here if the key doesn't contain any escape sequences
|
|
610
|
-
if (containsCodePoint(data, backSlashCode, outerLoopIndex, stringValueIndex)) {
|
|
611
|
-
key.reinst(parseString(data, outerLoopIndex - 1, stringValueIndex));
|
|
612
|
-
} else {
|
|
613
|
-
key.reinst(data, outerLoopIndex, stringValueIndex);
|
|
614
|
-
}
|
|
615
|
-
isKey = true;
|
|
616
|
-
} else {
|
|
617
|
-
if (isString<valueof<T>>()) {
|
|
618
|
-
const value = parseString(data, outerLoopIndex - 1, stringValueIndex);
|
|
619
|
-
map.set(parseMapKey<indexof<T>>(key), value);
|
|
620
|
-
}
|
|
621
|
-
isKey = false;
|
|
622
|
-
}
|
|
623
|
-
outerLoopIndex = ++stringValueIndex;
|
|
624
|
-
break;
|
|
625
|
-
}
|
|
626
|
-
escaping = false;
|
|
627
|
-
}
|
|
628
|
-
}
|
|
629
|
-
} else if (
|
|
630
|
-
char == nCode &&
|
|
631
|
-
unsafeCharCodeAt(data, ++outerLoopIndex) === uCode &&
|
|
632
|
-
unsafeCharCodeAt(data, ++outerLoopIndex) === lCode &&
|
|
633
|
-
unsafeCharCodeAt(data, ++outerLoopIndex) === lCode) {
|
|
634
|
-
if (isNullable<valueof<T>>()) {
|
|
635
|
-
map.set(parseMapKey<indexof<T>>(key), null);
|
|
636
|
-
}
|
|
637
|
-
isKey = false;
|
|
638
|
-
} else if (
|
|
639
|
-
char === tCode &&
|
|
640
|
-
unsafeCharCodeAt(data, ++outerLoopIndex) === rCode &&
|
|
641
|
-
unsafeCharCodeAt(data, ++outerLoopIndex) === uCode &&
|
|
642
|
-
unsafeCharCodeAt(data, ++outerLoopIndex) === eCode
|
|
643
|
-
) {
|
|
644
|
-
if (isBoolean<valueof<T>>()) {
|
|
645
|
-
map.set(parseMapKey<indexof<T>>(key), true);
|
|
646
|
-
}
|
|
647
|
-
isKey = false;
|
|
648
|
-
} else if (
|
|
649
|
-
char === fCode &&
|
|
650
|
-
unsafeCharCodeAt(data, ++outerLoopIndex) === aCode &&
|
|
651
|
-
unsafeCharCodeAt(data, ++outerLoopIndex) === lCode &&
|
|
652
|
-
unsafeCharCodeAt(data, ++outerLoopIndex) === sCode &&
|
|
653
|
-
unsafeCharCodeAt(data, ++outerLoopIndex) === eCode
|
|
654
|
-
) {
|
|
655
|
-
if (isBoolean<valueof<T>>()) {
|
|
656
|
-
map.set(parseMapKey<indexof<T>>(key), false);
|
|
657
|
-
}
|
|
658
|
-
isKey = false;
|
|
659
|
-
} else if ((char >= 48 && char <= 57) || char === 45) {
|
|
660
|
-
let numberValueIndex = ++outerLoopIndex;
|
|
661
|
-
for (; numberValueIndex < data.length; numberValueIndex++) {
|
|
662
|
-
const char = unsafeCharCodeAt(data, numberValueIndex);
|
|
663
|
-
if (char === colonCode || char === commaCode || char === rightBraceCode || isSpace(char)) {
|
|
664
|
-
if (isFloat<valueof<T>>() || isInteger<valueof<T>>()) {
|
|
665
|
-
map.set(parseMapKey<indexof<T>>(key), parseNumber<valueof<T>>(data.slice(outerLoopIndex - 1, numberValueIndex)));
|
|
666
|
-
}
|
|
667
|
-
outerLoopIndex = numberValueIndex;
|
|
668
|
-
isKey = false;
|
|
669
|
-
break;
|
|
670
|
-
}
|
|
671
|
-
}
|
|
672
|
-
}
|
|
673
|
-
}
|
|
674
|
-
|
|
675
|
-
return map;
|
|
676
|
-
}
|
|
677
|
-
|
|
678
|
-
//@ts-ignore: Decorator
|
|
679
|
-
@inline function parseMapKey<T>(key: Virtual<string>): T {
|
|
680
|
-
const k = key.copyOut();
|
|
681
|
-
if (isString<T>()) {
|
|
682
|
-
return k as T;
|
|
683
|
-
} else if (isBoolean<T>()) {
|
|
684
|
-
// @ts-ignore
|
|
685
|
-
return parseBoolean<T>(k) as T;
|
|
686
|
-
} else if (isInteger<T>() || isFloat<T>()) {
|
|
687
|
-
return parseNumber<T>(k);
|
|
688
|
-
}
|
|
689
|
-
|
|
690
|
-
throw new Error(`JSON: Cannot parse JSON object to a Map with a key of type ${nameof<T>()}`);
|
|
691
|
-
}
|
|
692
|
-
|
|
693
|
-
// @ts-ignore: Decorator
|
|
694
|
-
@inline function parseArray<T extends unknown[]>(data: string): T {
|
|
695
|
-
if (isString<valueof<T>>()) {
|
|
696
|
-
return <T>parseStringArray(data);
|
|
697
|
-
} else if (isBoolean<valueof<T>>()) {
|
|
698
|
-
// @ts-ignore
|
|
699
|
-
return parseBooleanArray<T>(data);
|
|
700
|
-
} else if (isFloat<valueof<T>>() || isInteger<valueof<T>>()) {
|
|
701
|
-
// @ts-ignore
|
|
702
|
-
return parseNumberArray<T>(data);
|
|
703
|
-
} else if (isArrayLike<valueof<T>>()) {
|
|
704
|
-
// @ts-ignore
|
|
705
|
-
return parseArrayArray<T>(data);
|
|
706
|
-
} else if (isMap<valueof<T>>()) {
|
|
707
|
-
return parseObjectArray<T>(data);
|
|
708
|
-
} else if (isManaged<valueof<T>>() || isReference<valueof<T>>()) {
|
|
709
|
-
// We instantiate the required memory for the class and fill it. This is extremely unsafe and uses "a bit of magic".
|
|
710
|
-
const type = changetype<nonnull<valueof<T>>>(
|
|
711
|
-
__new(offsetof<nonnull<valueof<T>>>(), idof<nonnull<valueof<T>>>())
|
|
712
|
-
);
|
|
713
|
-
// @ts-ignore
|
|
714
|
-
if (isDefined(type.__JSON_Set_Key)) {
|
|
715
|
-
return parseObjectArray<T>(data);
|
|
716
|
-
}
|
|
717
|
-
}
|
|
718
|
-
|
|
719
|
-
throw new Error("Tried to parse array, but failed!")
|
|
720
|
-
}
|
|
721
|
-
|
|
722
|
-
// @ts-ignore: Decorator
|
|
723
|
-
@inline function parseStringArray(data: string): string[] {
|
|
724
|
-
const result: string[] = [];
|
|
725
|
-
let lastPos = 0;
|
|
726
|
-
let instr = false;
|
|
727
|
-
let escaping = false;
|
|
728
|
-
for (let i = 1; i < data.length - 1; i++) {
|
|
729
|
-
const char = unsafeCharCodeAt(data, i);
|
|
730
|
-
if (char === backSlashCode && !escaping) {
|
|
731
|
-
escaping = true;
|
|
732
|
-
} else {
|
|
733
|
-
if (char === quoteCode && !escaping) {
|
|
734
|
-
if (instr === false) {
|
|
735
|
-
instr = true;
|
|
736
|
-
lastPos = i;
|
|
737
|
-
} else {
|
|
738
|
-
instr = false;
|
|
739
|
-
result.push(parseString(data, lastPos, i));
|
|
740
|
-
}
|
|
741
|
-
}
|
|
742
|
-
escaping = false;
|
|
743
|
-
}
|
|
744
|
-
}
|
|
745
|
-
return result;
|
|
746
|
-
}
|
|
747
|
-
|
|
748
|
-
// @ts-ignore: Decorator
|
|
749
|
-
@inline function parseBooleanArray<T extends boolean[]>(data: string): T {
|
|
750
|
-
const result = instantiate<T>();
|
|
751
|
-
let lastPos = 1;
|
|
752
|
-
for (let i = 1; i < data.length - 1; i++) {
|
|
753
|
-
const char = unsafeCharCodeAt(data, i);
|
|
754
|
-
if (char === tCode || char === fCode) {
|
|
755
|
-
lastPos = i;
|
|
756
|
-
} else if (char === eCode) {
|
|
757
|
-
i++;
|
|
758
|
-
result.push(parseBoolean<valueof<T>>(data.slice(lastPos, i)));
|
|
759
|
-
}
|
|
760
|
-
}
|
|
761
|
-
return result;
|
|
762
|
-
}
|
|
763
|
-
|
|
764
|
-
// @ts-ignore: Decorator
|
|
765
|
-
@inline function parseNumberArray<T extends number[]>(data: string): T {
|
|
766
|
-
const result = instantiate<T>();
|
|
767
|
-
let lastPos = 0;
|
|
768
|
-
let i = 1;
|
|
769
|
-
let awaitingParse = false;
|
|
770
|
-
for (; i < data.length; i++) {
|
|
771
|
-
const char = unsafeCharCodeAt(data, i);
|
|
772
|
-
if (lastPos === 0 && ((char >= 48 && char <= 57) || char === 45)) {
|
|
773
|
-
awaitingParse = true;
|
|
774
|
-
lastPos = i;
|
|
775
|
-
} else if (awaitingParse && (isSpace(char) || char == commaCode || char == rightBracketCode) && lastPos > 0) {
|
|
776
|
-
awaitingParse = false;
|
|
777
|
-
result.push(parseNumber<valueof<T>>(data.slice(lastPos, i)));
|
|
778
|
-
lastPos = 0;
|
|
779
|
-
}
|
|
780
|
-
}
|
|
781
|
-
return result;
|
|
782
|
-
}
|
|
783
|
-
|
|
784
|
-
// @ts-ignore: Decorator
|
|
785
|
-
@inline function parseArrayArray<T extends unknown[][]>(data: string): T {
|
|
786
|
-
const result = instantiate<T>();
|
|
787
|
-
let lastPos = 0;
|
|
788
|
-
let depth = 0;
|
|
789
|
-
let i = 1;
|
|
790
|
-
// Find start of bracket
|
|
791
|
-
//for (; unsafeCharCodeAt(data, i) !== leftBracketCode; i++) {}
|
|
792
|
-
//i++;
|
|
793
|
-
for (; i < data.length - 1; i++) {
|
|
794
|
-
const char = unsafeCharCodeAt(data, i);
|
|
795
|
-
if (char === leftBracketCode) {
|
|
796
|
-
if (depth === 0) {
|
|
797
|
-
lastPos = i;
|
|
798
|
-
}
|
|
799
|
-
// Shifting is 6% faster than incrementing
|
|
800
|
-
depth++;
|
|
801
|
-
} else if (char === rightBracketCode) {
|
|
802
|
-
depth--;
|
|
803
|
-
if (depth === 0) {
|
|
804
|
-
i++;
|
|
805
|
-
result.push(JSON.parse<valueof<T>>(data.slice(lastPos, i)));
|
|
806
|
-
}
|
|
807
|
-
}
|
|
808
|
-
}
|
|
809
|
-
return result;
|
|
810
|
-
}
|
|
811
|
-
|
|
812
|
-
// @ts-ignore: Decorator
|
|
813
|
-
@inline function parseObjectArray<T extends unknown[]>(data: string): T {
|
|
814
|
-
const result = instantiate<T>();
|
|
815
|
-
let lastPos: u32 = 1;
|
|
816
|
-
let depth: u32 = 0;
|
|
817
|
-
for (let pos: u32 = 0; pos < <u32>data.length; pos++) {
|
|
818
|
-
const char = unsafeCharCodeAt(data, pos);
|
|
819
|
-
if (char === leftBraceCode) {
|
|
820
|
-
if (depth === 0) {
|
|
821
|
-
lastPos = pos;
|
|
822
|
-
}
|
|
823
|
-
depth++;
|
|
824
|
-
} else if (char === rightBraceCode) {
|
|
825
|
-
depth--;
|
|
826
|
-
if (depth === 0) {
|
|
827
|
-
pos++;
|
|
828
|
-
result.push(JSON.parse<valueof<T>>(data.slice(lastPos, pos)));
|
|
829
|
-
//lastPos = pos + 2;
|
|
830
|
-
}
|
|
831
|
-
}
|
|
832
|
-
}
|
|
833
|
-
return result;
|
|
834
|
-
}
|
|
835
|
-
|
|
836
|
-
function parseDate(dateTimeString: string): Date {
|
|
837
|
-
// Use AssemblyScript's date parser
|
|
838
|
-
const d = Date.fromString(dateTimeString);
|
|
839
|
-
|
|
840
|
-
// Return a new object instead of the one that the parser returned.
|
|
841
|
-
// This may seem redundant, but addreses the issue when Date
|
|
842
|
-
// is globally aliased to wasi_Date (or some other superclass).
|
|
843
|
-
return new Date(d.getTime());
|
|
844
|
-
}
|
|
845
|
-
|
|
846
|
-
// @ts-ignore: Decorator
|
|
847
|
-
@inline function isMap<T>(): bool {
|
|
848
|
-
let type = changetype<T>(0);
|
|
849
|
-
return type instanceof Map;
|
|
116
|
+
if (isString<T>()) return data;
|
|
117
|
+
return JSON.parse<T>(data, initializeDefaultValues);
|
|
850
118
|
}
|
|
851
119
|
|
|
852
120
|
// Dirty fix
|
|
853
121
|
// @ts-ignore: Decorator
|
|
854
122
|
@global @inline function __JSON_Stringify<T>(data: T): string {
|
|
855
|
-
|
|
856
|
-
if (isString<T>() && data != null) {
|
|
857
|
-
return serializeString(data as string);
|
|
858
|
-
} else if (isBoolean<T>()) {
|
|
859
|
-
return data ? "true" : "false";
|
|
860
|
-
} else if (isNullable<T>() && changetype<usize>(data) == <usize>0) {
|
|
861
|
-
return nullWord;
|
|
862
|
-
// @ts-ignore
|
|
863
|
-
} else if ((isInteger<T>() || isFloat<T>()) && isFinite(data)) {
|
|
864
|
-
// @ts-ignore
|
|
865
|
-
return data.toString();
|
|
866
|
-
// @ts-ignore: Hidden function
|
|
867
|
-
} else if (isDefined(data.__JSON_Serialize)) {
|
|
868
|
-
// @ts-ignore: Hidden function
|
|
869
|
-
return data.__JSON_Serialize();
|
|
870
|
-
} else if (data instanceof Date) {
|
|
871
|
-
return `"${data.toISOString()}"`;
|
|
872
|
-
} else if (data instanceof Box) {
|
|
873
|
-
if (isNullable<T>() && changetype<usize>(data) == <usize>0) {
|
|
874
|
-
return nullWord;
|
|
875
|
-
}
|
|
876
|
-
return JSON.stringify(data.unwrap());
|
|
877
|
-
} else if (isArrayLike<T>()) {
|
|
878
|
-
// @ts-ignore
|
|
879
|
-
if (data.length == 0) {
|
|
880
|
-
return emptyArrayWord;
|
|
881
|
-
// @ts-ignore
|
|
882
|
-
} else if (isString<valueof<T>>()) {
|
|
883
|
-
let result = leftBracketWord;
|
|
884
|
-
// @ts-ignore
|
|
885
|
-
for (let i = 0; i < data.length - 1; i++) {
|
|
886
|
-
// @ts-ignore
|
|
887
|
-
result += serializeString(unchecked(data[i]));
|
|
888
|
-
result += commaWord;
|
|
889
|
-
}
|
|
890
|
-
// @ts-ignore
|
|
891
|
-
result += serializeString(unchecked(data[data.length - 1]));
|
|
892
|
-
result += rightBracketWord;
|
|
893
|
-
return result;
|
|
894
|
-
// @ts-ignore
|
|
895
|
-
} else if (isBoolean<valueof<T>>()) {
|
|
896
|
-
// @ts-ignore
|
|
897
|
-
return leftBracketWord + data.join(commaWord) + rightBracketWord;
|
|
898
|
-
// @ts-ignore
|
|
899
|
-
} else if (isFloat<valueof<T>>() || isInteger<valueof<T>>()) {
|
|
900
|
-
// @ts-ignore
|
|
901
|
-
return leftBracketWord + data.join(commaWord) + rightBracketWord;
|
|
902
|
-
} else {
|
|
903
|
-
let result = new StringSink(leftBracketWord);
|
|
904
|
-
// @ts-ignore
|
|
905
|
-
for (let i = 0; i < data.length - 1; i++) {
|
|
906
|
-
// @ts-ignore
|
|
907
|
-
result.write(__JSON_Stringify(unchecked(data[i])));
|
|
908
|
-
result.writeCodePoint(commaCode);
|
|
909
|
-
}
|
|
910
|
-
// @ts-ignore
|
|
911
|
-
result.write(__JSON_Stringify(unchecked(data[data.length - 1])));
|
|
912
|
-
result.writeCodePoint(rightBracketCode);
|
|
913
|
-
return result.toString();
|
|
914
|
-
}
|
|
915
|
-
} else if (data instanceof Map) {
|
|
916
|
-
let result = new StringSink(leftBraceWord);
|
|
917
|
-
let keys = data.keys();
|
|
918
|
-
let values = data.values();
|
|
919
|
-
const end = data.size - 1;
|
|
920
|
-
for (let i = 0; i < end; i++) {
|
|
921
|
-
result.write(serializeString(unchecked(keys[i]).toString()));
|
|
922
|
-
result.writeCodePoint(colonCode);
|
|
923
|
-
result.write(__JSON_Stringify(unchecked(values[i])));
|
|
924
|
-
result.writeCodePoint(commaCode);
|
|
925
|
-
}
|
|
926
|
-
result.write(serializeString(unchecked(keys[end]).toString()));
|
|
927
|
-
result.writeCodePoint(colonCode);
|
|
928
|
-
result.write(__JSON_Stringify(unchecked(values[end])));
|
|
929
|
-
|
|
930
|
-
result.writeCodePoint(rightBraceCode);
|
|
931
|
-
return result.toString();
|
|
932
|
-
} else {
|
|
933
|
-
throw new Error(
|
|
934
|
-
`Could not serialize data of type ${nameof<T>()}. Make sure to add the correct decorators to classes.`
|
|
935
|
-
);
|
|
936
|
-
}
|
|
937
|
-
}
|
|
938
|
-
|
|
939
|
-
@inline function parseDirectInference<T>(type: T, data: string, initializeDefaultValues: boolean = false): T {
|
|
940
|
-
return JSON.parse<T>(data, initializeDefaultValues)
|
|
123
|
+
return JSON.stringify(data);
|
|
941
124
|
}
|