json-as 0.9.29 → 1.0.0-alpha.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/.github/workflows/nodejs.yml +0 -3
- package/.prettierrc.json +3 -2
- package/CHANGELOG +13 -0
- package/LICENSE +1 -1
- package/README.md +22 -7
- package/as-test.config.json +1 -1
- package/asconfig.json +2 -2
- package/assembly/__benches__/misc.bench.ts +17 -32
- package/assembly/__tests__/bool.spec.ts +1 -1
- package/assembly/__tests__/simd/string.spec.ts +32 -0
- package/assembly/custom/memory.ts +25 -0
- package/assembly/custom/util.ts +14 -92
- package/assembly/deserialize/simd/string.ts +103 -0
- package/assembly/deserialize/simple/arbitrary.ts +17 -0
- package/assembly/deserialize/simple/array/arbitrary.ts +113 -0
- package/assembly/deserialize/simple/array/array.ts +18 -0
- package/assembly/deserialize/simple/array/bool.ts +17 -0
- package/assembly/deserialize/simple/array/float.ts +28 -0
- package/assembly/deserialize/simple/array/integer.ts +27 -0
- package/assembly/deserialize/simple/array/map.ts +18 -0
- package/assembly/deserialize/simple/array/object.ts +18 -0
- package/assembly/deserialize/simple/array/string.ts +22 -0
- package/assembly/deserialize/simple/array.ts +48 -0
- package/assembly/deserialize/simple/bool.ts +9 -0
- package/assembly/deserialize/simple/date.ts +11 -0
- package/assembly/deserialize/simple/float.ts +10 -0
- package/assembly/deserialize/simple/integer.ts +5 -0
- package/assembly/deserialize/simple/map.ts +154 -0
- package/assembly/deserialize/simple/object.ts +159 -0
- package/assembly/deserialize/simple/string.ts +48 -0
- package/assembly/globals/tables.ts +417 -0
- package/assembly/index.d.ts +9 -13
- package/assembly/index.ts +266 -146
- package/assembly/serialize/simd/string.ts +176 -0
- package/assembly/serialize/simple/arbitrary.ts +36 -0
- package/assembly/serialize/simple/array.ts +32 -0
- package/assembly/serialize/simple/bool.ts +19 -0
- package/assembly/serialize/simple/date.ts +13 -0
- package/assembly/serialize/simple/float.ts +7 -0
- package/assembly/serialize/simple/integer.ts +7 -0
- package/assembly/serialize/simple/map.ts +43 -0
- package/assembly/serialize/simple/object.ts +7 -0
- package/assembly/serialize/simple/string.ts +48 -0
- package/assembly/test.ts +41 -27
- package/assembly/tsconfig.json +2 -91
- package/assembly/types.ts +0 -0
- package/assembly/util/atoi.ts +35 -0
- package/assembly/util/bytes.ts +12 -0
- package/assembly/util/concat.ts +9 -0
- package/assembly/util/getArrayDepth.ts +17 -0
- package/assembly/util/index.ts +5 -0
- package/assembly/util/isSpace.ts +4 -0
- package/assembly/util/nextPowerOf2.ts +4 -0
- package/assembly/util/ptrToStr.ts +7 -0
- package/assembly/util/snp.ts +69 -0
- package/bench.js +5 -5
- package/modules/bs/index.ts +167 -0
- package/modules/tsconfig.json +8 -0
- package/package.json +42 -48
- package/transform/lib/builder.js +1353 -0
- package/transform/lib/builder.js.map +1 -0
- package/transform/lib/index.js +497 -332
- package/transform/lib/index.js.map +1 -1
- package/transform/lib/index.old.js +404 -0
- package/transform/lib/index.old.js.map +1 -0
- package/transform/lib/linker.js +18 -0
- package/transform/lib/linker.js.map +1 -0
- package/transform/lib/types.js +25 -0
- package/transform/lib/types.js.map +1 -0
- package/transform/lib/util.js +47 -0
- package/transform/lib/util.js.map +1 -0
- package/transform/lib/visitor.js +529 -446
- package/transform/lib/visitor.js.map +1 -0
- package/transform/package.json +1 -34
- package/transform/src/builder.ts +1371 -0
- package/transform/src/index.ts +564 -341
- package/transform/src/linker.ts +21 -0
- package/transform/src/types.ts +27 -0
- package/transform/src/util.ts +56 -0
- package/transform/src/visitor.ts +531 -0
- package/transform/tsconfig.json +3 -1
- package/assembly/__benches__/as-tral.d.ts +0 -1
- package/assembly/__tests__/date.spec.ts +0 -12
- package/assembly/custom/bs.ts +0 -202
- package/assembly/deserialize/array/array.ts +0 -31
- package/assembly/deserialize/array/bool.ts +0 -19
- package/assembly/deserialize/array/float.ts +0 -24
- package/assembly/deserialize/array/integer.ts +0 -24
- package/assembly/deserialize/array/map.ts +0 -27
- package/assembly/deserialize/array/object.ts +0 -27
- package/assembly/deserialize/array/string.ts +0 -29
- package/assembly/deserialize/array.ts +0 -46
- package/assembly/deserialize/bool.ts +0 -34
- package/assembly/deserialize/date.ts +0 -19
- package/assembly/deserialize/float.ts +0 -21
- package/assembly/deserialize/integer.ts +0 -16
- package/assembly/deserialize/map.ts +0 -139
- package/assembly/deserialize/object.ts +0 -211
- package/assembly/deserialize/string.ts +0 -149
- package/assembly/serialize/array.ts +0 -44
- package/assembly/serialize/bool.ts +0 -10
- package/assembly/serialize/date.ts +0 -4
- package/assembly/serialize/float.ts +0 -4
- package/assembly/serialize/integer.ts +0 -5
- package/assembly/serialize/map.ts +0 -24
- package/assembly/serialize/object.ts +0 -13
- package/assembly/serialize/string.ts +0 -284
package/assembly/index.ts
CHANGED
|
@@ -1,23 +1,31 @@
|
|
|
1
1
|
/// <reference path="./index.d.ts" />
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
|
|
17
|
-
import { deserializeInteger, deserializeInteger_Safe } from "./deserialize/integer";
|
|
18
|
-
import { deserializeString, deserializeString_Safe } from "./deserialize/string";
|
|
2
|
+
import { bs } from "../modules/bs";
|
|
3
|
+
|
|
4
|
+
import { serializeString } from "./serialize/simple/string";
|
|
5
|
+
import { serializeArray } from "./serialize/simple/array";
|
|
6
|
+
import { serializeMap } from "./serialize/simple/map";
|
|
7
|
+
import { deserializeBoolean } from "./deserialize/simple/bool";
|
|
8
|
+
import { deserializeArray } from "./deserialize/simple/array";
|
|
9
|
+
import { deserializeFloat } from "./deserialize/simple/float";
|
|
10
|
+
import { deserializeObject } from "./deserialize/simple/object";
|
|
11
|
+
import { deserializeMap } from "./deserialize/simple/map";
|
|
12
|
+
import { deserializeDate } from "./deserialize/simple/date";
|
|
13
|
+
import { deserializeInteger } from "./deserialize/simple/integer";
|
|
14
|
+
import { deserializeString } from "./deserialize/simple/string";
|
|
15
|
+
import { serializeArbitrary } from "./serialize/simple/arbitrary";
|
|
16
|
+
|
|
19
17
|
import { Sink } from "./custom/sink";
|
|
20
|
-
import {
|
|
18
|
+
import { NULL_WORD, QUOTE } from "./custom/chars";
|
|
19
|
+
import { dtoa_buffered, itoa_buffered } from "util/number";
|
|
20
|
+
import { serializeBool } from "./serialize/simple/bool";
|
|
21
|
+
import { serializeInteger } from "./serialize/simple/integer";
|
|
22
|
+
import { serializeFloat } from "./serialize/simple/float";
|
|
23
|
+
import { serializeObject } from "./serialize/simple/object";
|
|
24
|
+
import { ptrToStr } from "./util/ptrToStr";
|
|
25
|
+
import { bytes } from "./util";
|
|
26
|
+
import { serializeString_SIMD } from "./serialize/simd/string";
|
|
27
|
+
|
|
28
|
+
export type Raw = string;
|
|
21
29
|
|
|
22
30
|
/**
|
|
23
31
|
* Offset of the 'storage' property in the JSON.Value class.
|
|
@@ -29,6 +37,158 @@ import { getArrayDepth } from "./custom/util";
|
|
|
29
37
|
* JSON Encoder/Decoder for AssemblyScript
|
|
30
38
|
*/
|
|
31
39
|
export namespace JSON {
|
|
40
|
+
/**
|
|
41
|
+
* Serializes valid JSON data
|
|
42
|
+
* ```js
|
|
43
|
+
* JSON.stringify<T>(data)
|
|
44
|
+
* ```
|
|
45
|
+
* @param data T
|
|
46
|
+
* @returns string
|
|
47
|
+
*/
|
|
48
|
+
export function stringify<T>(data: T, out: string | null = null): string {
|
|
49
|
+
if (isBoolean<T>()) {
|
|
50
|
+
if (out) {
|
|
51
|
+
if (<bool>data == true) {
|
|
52
|
+
out = changetype<string>(__renew(changetype<usize>(out), 8));
|
|
53
|
+
store<u64>(changetype<usize>(out), 28429475166421108);
|
|
54
|
+
} else {
|
|
55
|
+
out = changetype<string>(__renew(changetype<usize>(out), 10));
|
|
56
|
+
store<u64>(changetype<usize>(out), 32370086184550502);
|
|
57
|
+
store<u16>(changetype<usize>(out), 101, 8);
|
|
58
|
+
}
|
|
59
|
+
return out;
|
|
60
|
+
}
|
|
61
|
+
return data ? "true" : "false";
|
|
62
|
+
} else if (isInteger<T>() && nameof<T>() == "usize" && data == 0) {
|
|
63
|
+
if (out) {
|
|
64
|
+
out = changetype<string>(__renew(changetype<usize>(out), 8));
|
|
65
|
+
store<u64>(changetype<usize>(out), 30399761348886638);
|
|
66
|
+
return out;
|
|
67
|
+
}
|
|
68
|
+
return NULL_WORD;
|
|
69
|
+
} else if (isInteger<T>(data)) {
|
|
70
|
+
if (out) {
|
|
71
|
+
out = changetype<string>(__renew(changetype<usize>(out), sizeof<T>() << 3));
|
|
72
|
+
|
|
73
|
+
// @ts-ignore
|
|
74
|
+
const bytes = itoa_buffered(changetype<usize>(out), data) << 1;
|
|
75
|
+
return (out = changetype<string>(__renew(changetype<usize>(out), bytes)));
|
|
76
|
+
}
|
|
77
|
+
return data.toString();
|
|
78
|
+
} else if (isFloat<T>(data)) {
|
|
79
|
+
if (out) {
|
|
80
|
+
out = changetype<string>(__renew(changetype<usize>(out), 64));
|
|
81
|
+
|
|
82
|
+
// @ts-ignore
|
|
83
|
+
const bytes = dtoa_buffered(changetype<usize>(out), data) << 1;
|
|
84
|
+
return (out = changetype<string>(__renew(changetype<usize>(out), bytes)));
|
|
85
|
+
}
|
|
86
|
+
return data.toString();
|
|
87
|
+
// @ts-ignore: Function is generated by transform
|
|
88
|
+
} else if (isNullable<T>() && changetype<usize>(data) == <usize>0) {
|
|
89
|
+
if (out) {
|
|
90
|
+
out = changetype<string>(__renew(changetype<usize>(out), 8));
|
|
91
|
+
store<u64>(changetype<usize>(out), 30399761348886638);
|
|
92
|
+
return out;
|
|
93
|
+
}
|
|
94
|
+
return NULL_WORD;
|
|
95
|
+
// @ts-ignore
|
|
96
|
+
} else if (isString<nonnull<T>>()) {
|
|
97
|
+
if (out) {
|
|
98
|
+
out = changetype<string>(__renew(changetype<usize>(out), bytes(data) + 4));
|
|
99
|
+
// const oldSize = bs.byteLength;
|
|
100
|
+
const oldBuf = bs.buffer;
|
|
101
|
+
const newSize = bytes(data) + 4;
|
|
102
|
+
const newBuf = __new(newSize, idof<string>());
|
|
103
|
+
bs.setBuffer(newBuf);
|
|
104
|
+
serializeString(changetype<string>(data));
|
|
105
|
+
bs.setBuffer(oldBuf);
|
|
106
|
+
return changetype<string>(newBuf);
|
|
107
|
+
}
|
|
108
|
+
serializeString(changetype<string>(data));
|
|
109
|
+
return bs.out<string>();
|
|
110
|
+
// @ts-ignore: Supplied by transform
|
|
111
|
+
} else if (isDefined(data.__SERIALIZE) && isDefined(data.__ALLOCATE)) {
|
|
112
|
+
// @ts-ignore
|
|
113
|
+
data.__ALLOCATE();
|
|
114
|
+
// @ts-ignore
|
|
115
|
+
data.__SERIALIZE(changetype<usize>(data));
|
|
116
|
+
return bs.out<string>();
|
|
117
|
+
// @ts-ignore: Supplied by transform
|
|
118
|
+
} else if (data instanceof Date) {
|
|
119
|
+
out = out ? changetype<string>(__renew(changetype<usize>(out), 52)) : changetype<string>(__new(52, idof<string>()));
|
|
120
|
+
|
|
121
|
+
store<u16>(changetype<usize>(out), QUOTE);
|
|
122
|
+
memory.copy(changetype<usize>(out) + 2, changetype<usize>(data.toISOString()), 48);
|
|
123
|
+
store<u16>(changetype<usize>(out), 50);
|
|
124
|
+
return out;
|
|
125
|
+
} else if (data instanceof Array) {
|
|
126
|
+
// @ts-ignore
|
|
127
|
+
serializeArray(changetype<nonnull<T>>(data));
|
|
128
|
+
return bs.out<string>();
|
|
129
|
+
} else if (data instanceof Map) {
|
|
130
|
+
// @ts-ignore
|
|
131
|
+
serializeMap(changetype<nonnull<T>>(data));
|
|
132
|
+
return bs.out<string>();
|
|
133
|
+
} else if (data instanceof JSON.Value) {
|
|
134
|
+
serializeArbitrary(data);
|
|
135
|
+
return bs.out<string>();
|
|
136
|
+
} else if (data instanceof JSON.Box) {
|
|
137
|
+
return JSON.stringify(data.value);
|
|
138
|
+
} else {
|
|
139
|
+
ERROR(`Could not serialize data of type ${nameof<T>()}. Make sure to add the correct decorators to classes.`);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Parses valid JSON strings into their original format
|
|
145
|
+
* ```js
|
|
146
|
+
* JSON.parse<T>(data)
|
|
147
|
+
* ```
|
|
148
|
+
* @param data string
|
|
149
|
+
* @returns T
|
|
150
|
+
*/
|
|
151
|
+
export function parse<T>(data: string): T {
|
|
152
|
+
const dataSize = bytes(data);
|
|
153
|
+
const dataPtr = changetype<usize>(data);
|
|
154
|
+
if (isBoolean<T>()) {
|
|
155
|
+
return deserializeBoolean(dataPtr, dataPtr + dataSize) as T;
|
|
156
|
+
} else if (isInteger<T>()) {
|
|
157
|
+
return deserializeInteger<T>(dataPtr, dataPtr + dataSize);
|
|
158
|
+
} else if (isFloat<T>()) {
|
|
159
|
+
return deserializeFloat<T>(dataPtr, dataPtr + dataSize);
|
|
160
|
+
} else if (isNullable<T>() && data.length == 4 && data == "null") {
|
|
161
|
+
// @ts-ignore
|
|
162
|
+
return null;
|
|
163
|
+
} else if (isString<T>()) {
|
|
164
|
+
// @ts-ignore
|
|
165
|
+
return deserializeString(dataPtr, dataPtr + dataSize);
|
|
166
|
+
} else if (isArray<T>()) {
|
|
167
|
+
// @ts-ignore
|
|
168
|
+
return deserializeArray<nonnull<T>>(dataPtr, dataPtr + dataSize, changetype<usize>(instantiate<T>()));
|
|
169
|
+
}
|
|
170
|
+
let type: nonnull<T> = changetype<nonnull<T>>(0);
|
|
171
|
+
// @ts-ignore: Defined by transform
|
|
172
|
+
if (isDefined(type.__DESERIALIZE) && isDefined(type.__INITIALIZE)) {
|
|
173
|
+
const out = __new(offsetof<nonnull<T>>(), idof<nonnull<T>>());
|
|
174
|
+
// @ts-ignore
|
|
175
|
+
changetype<nonnull<T>>(out).__INITIALIZE();
|
|
176
|
+
// @ts-ignore
|
|
177
|
+
return deserializeObject<nonnull<T>>(dataPtr, dataPtr + dataSize, out);
|
|
178
|
+
} else if (type instanceof Map) {
|
|
179
|
+
// @ts-ignore
|
|
180
|
+
return deserializeMap<nonnull<T>>(dataPtr, dataPtr + dataSize);
|
|
181
|
+
} else if (type instanceof Date) {
|
|
182
|
+
// @ts-ignore
|
|
183
|
+
return deserializeDate(dataPtr, dataPtr + dataSize);
|
|
184
|
+
} else if (type instanceof JSON.Box) {
|
|
185
|
+
// @ts-ignore
|
|
186
|
+
return new JSON.Box(JSON.parse<indexof<T>>(data));
|
|
187
|
+
} else {
|
|
188
|
+
ERROR(`Could not deserialize data ${data} to type ${nameof<T>()}. Make sure to add the correct decorators to classes.`);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
32
192
|
/**
|
|
33
193
|
* Enum representing the different types supported by JSON.
|
|
34
194
|
*/
|
|
@@ -42,11 +202,15 @@ export namespace JSON {
|
|
|
42
202
|
F64 = 6,
|
|
43
203
|
Bool = 7,
|
|
44
204
|
String = 8,
|
|
45
|
-
|
|
46
|
-
Array =
|
|
205
|
+
Object = 9,
|
|
206
|
+
Array = 10,
|
|
207
|
+
Struct = 11,
|
|
47
208
|
}
|
|
209
|
+
|
|
48
210
|
export type Raw = string;
|
|
211
|
+
|
|
49
212
|
export class Value {
|
|
213
|
+
static METHODS: Map<u32, u32> = new Map<u32, u32>();
|
|
50
214
|
public type: i32;
|
|
51
215
|
|
|
52
216
|
// @ts-ignore
|
|
@@ -103,11 +267,19 @@ export namespace JSON {
|
|
|
103
267
|
if (idof<T>() !== idof<Map<string, JSON.Value>>()) {
|
|
104
268
|
abort("Maps must be of type Map<string, JSON.Value>!");
|
|
105
269
|
}
|
|
106
|
-
this.type = JSON.Types.
|
|
270
|
+
this.type = JSON.Types.Struct;
|
|
271
|
+
store<T>(changetype<usize>(this), value, STORAGE);
|
|
272
|
+
// @ts-ignore
|
|
273
|
+
} else if (isDefined(value.__SERIALIZE)) {
|
|
274
|
+
this.type = idof<T>() + JSON.Types.Struct;
|
|
275
|
+
// @ts-ignore
|
|
276
|
+
if (!JSON.Value.METHODS.has(idof<T>())) JSON.Value.METHODS.set(idof<T>(), value.__SERIALIZE.index);
|
|
277
|
+
// @ts-ignore
|
|
107
278
|
store<T>(changetype<usize>(this), value, STORAGE);
|
|
108
|
-
|
|
279
|
+
// @ts-ignore
|
|
280
|
+
} else if (isArray<T>() && idof<valueof<T>>() == idof<JSON.Value>()) {
|
|
109
281
|
// @ts-ignore: T satisfies constraints of any[]
|
|
110
|
-
this.type = JSON.Types.Array
|
|
282
|
+
this.type = JSON.Types.Array;
|
|
111
283
|
store<T>(changetype<usize>(this), value, STORAGE);
|
|
112
284
|
}
|
|
113
285
|
}
|
|
@@ -122,7 +294,6 @@ export namespace JSON {
|
|
|
122
294
|
|
|
123
295
|
/**
|
|
124
296
|
* Converts the JSON.Value to a string representation.
|
|
125
|
-
* @param useString - If true, treats Buffer as a string.
|
|
126
297
|
* @returns The string representation of the JSON.Value.
|
|
127
298
|
*/
|
|
128
299
|
toString(): string {
|
|
@@ -139,7 +310,7 @@ export namespace JSON {
|
|
|
139
310
|
return '"' + this.get<string>() + '"';
|
|
140
311
|
case JSON.Types.Bool:
|
|
141
312
|
return this.get<boolean>() ? "true" : "false";
|
|
142
|
-
|
|
313
|
+
case JSON.Types.Array: {
|
|
143
314
|
const arr = this.get<JSON.Value[]>();
|
|
144
315
|
if (!arr.length) return "[]";
|
|
145
316
|
const out = Sink.fromStringLiteral("[");
|
|
@@ -156,158 +327,107 @@ export namespace JSON {
|
|
|
156
327
|
out.write("]");
|
|
157
328
|
return out.toString();
|
|
158
329
|
}
|
|
330
|
+
default: {
|
|
331
|
+
const fn = JSON.Value.METHODS.get(this.type - JSON.Types.Struct);
|
|
332
|
+
const value = this.get<usize>();
|
|
333
|
+
return call_indirect<string>(fn, 0, value);
|
|
334
|
+
}
|
|
159
335
|
}
|
|
160
336
|
}
|
|
161
337
|
}
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* Box for primitive types
|
|
341
|
+
*/
|
|
162
342
|
export class Box<T> {
|
|
163
343
|
constructor(public value: T) {}
|
|
164
|
-
|
|
165
|
-
|
|
344
|
+
/**
|
|
345
|
+
* Creates a reference to a primitive type
|
|
346
|
+
* This means that it can create a nullable primitive
|
|
347
|
+
* ```js
|
|
348
|
+
* JSON.stringify<Box<i32> | null>(null);
|
|
349
|
+
* // null
|
|
350
|
+
* ```
|
|
351
|
+
* @param from T
|
|
352
|
+
* @returns Box<T>
|
|
353
|
+
*/
|
|
166
354
|
@inline static from<T>(value: T): Box<T> {
|
|
167
355
|
return new Box(value);
|
|
168
356
|
}
|
|
169
357
|
}
|
|
170
358
|
|
|
171
|
-
|
|
172
|
-
* Stringifies valid JSON data.
|
|
173
|
-
* ```js
|
|
174
|
-
* JSON.stringify<T>(data)
|
|
175
|
-
* ```
|
|
176
|
-
* @param data T
|
|
177
|
-
* @returns string
|
|
178
|
-
*/
|
|
179
|
-
export function stringify<T>(data: T /*, options: SerializeOptions = DEFAULT_SERIALIZE_OPTIONS*/): string {
|
|
359
|
+
export function __serialize<T>(src: T): void {
|
|
180
360
|
if (isBoolean<T>()) {
|
|
181
|
-
|
|
182
|
-
} else if (isInteger<T>() && nameof<T>() == "usize" &&
|
|
183
|
-
|
|
361
|
+
serializeBool(src as bool);
|
|
362
|
+
} else if (isInteger<T>() && nameof<T>() == "usize" && src == 0) {
|
|
363
|
+
bs.ensureSize(8);
|
|
364
|
+
store<u64>(bs.offset, 30399761348886638);
|
|
365
|
+
bs.offset += 8;
|
|
184
366
|
} else if (isInteger<T>()) {
|
|
185
367
|
// @ts-ignore
|
|
186
|
-
|
|
187
|
-
} else if (isFloat<T>(
|
|
368
|
+
serializeInteger<T>(src);
|
|
369
|
+
} else if (isFloat<T>(src)) {
|
|
188
370
|
// @ts-ignore
|
|
189
|
-
|
|
371
|
+
serializeFloat<T>(src);
|
|
190
372
|
// @ts-ignore: Function is generated by transform
|
|
191
|
-
} else if (isNullable<T>() && changetype<usize>(
|
|
192
|
-
|
|
193
|
-
|
|
373
|
+
} else if (isNullable<T>() && changetype<usize>(src) == <usize>0) {
|
|
374
|
+
bs.ensureSize(8);
|
|
375
|
+
store<u64>(bs.offset, 30399761348886638);
|
|
376
|
+
bs.offset += 8;
|
|
194
377
|
} else if (isString<nonnull<T>>()) {
|
|
195
|
-
|
|
378
|
+
if (ASC_FEATURE_SIMD) {
|
|
379
|
+
serializeString_SIMD(src as string);
|
|
380
|
+
} else {
|
|
381
|
+
serializeString(src as string);
|
|
382
|
+
}
|
|
196
383
|
// @ts-ignore: Supplied by transform
|
|
197
|
-
} else if (isDefined(
|
|
198
|
-
/*if (options.pretty) {
|
|
199
|
-
// @ts-ignore
|
|
200
|
-
return serializeObject_Pretty(changetype<nonnull<T>>(data));
|
|
201
|
-
}*/
|
|
384
|
+
} else if (isDefined(src.__SERIALIZE)) {
|
|
202
385
|
// @ts-ignore
|
|
203
|
-
|
|
204
|
-
} else if (
|
|
386
|
+
serializeObject(changetype<nonnull<T>>(src));
|
|
387
|
+
} else if (src instanceof Date) {
|
|
205
388
|
// @ts-ignore
|
|
206
|
-
|
|
207
|
-
} else if (
|
|
389
|
+
serializeDate(changetype<nonnull<T>>(src));
|
|
390
|
+
} else if (src instanceof Array) {
|
|
208
391
|
// @ts-ignore
|
|
209
|
-
|
|
210
|
-
} else if (
|
|
392
|
+
serializeArray(changetype<nonnull<T>>(src));
|
|
393
|
+
} else if (src instanceof Map) {
|
|
211
394
|
// @ts-ignore
|
|
212
|
-
|
|
395
|
+
serializeMap(changetype<nonnull<T>>(src));
|
|
396
|
+
} else if (src instanceof JSON.Value) {
|
|
397
|
+
serializeArbitrary(src);
|
|
398
|
+
} else if (src instanceof JSON.Box) {
|
|
399
|
+
__serialize(src.value);
|
|
213
400
|
} else {
|
|
214
|
-
|
|
401
|
+
ERROR(`Could not serialize provided data. Make sure to add the correct decorators to classes.`);
|
|
215
402
|
}
|
|
216
403
|
}
|
|
217
|
-
|
|
218
|
-
* Parses valid JSON strings into their original format.
|
|
219
|
-
* ```js
|
|
220
|
-
* JSON.parse<T>(data)
|
|
221
|
-
* ```
|
|
222
|
-
* @param data string
|
|
223
|
-
* @returns T
|
|
224
|
-
*/
|
|
225
|
-
export function parse<T>(data: string): T {
|
|
404
|
+
export function __deserialize<T>(srcStart: usize, srcEnd: usize, dst: usize = 0): T {
|
|
226
405
|
if (isBoolean<T>()) {
|
|
227
|
-
|
|
406
|
+
// @ts-ignore: type
|
|
407
|
+
return deserializeBoolean(srcStart, srcEnd);
|
|
228
408
|
} else if (isInteger<T>()) {
|
|
229
|
-
return deserializeInteger<T>(
|
|
409
|
+
return deserializeInteger<T>(srcStart, srcEnd);
|
|
230
410
|
} else if (isFloat<T>()) {
|
|
231
|
-
return deserializeFloat<T>(
|
|
232
|
-
} else if (isNullable<T>() && data.length === 4 && data == "null") {
|
|
233
|
-
// @ts-ignore
|
|
234
|
-
return null;
|
|
411
|
+
return deserializeFloat<T>(srcStart, srcEnd);
|
|
235
412
|
} else if (isString<T>()) {
|
|
236
|
-
// @ts-ignore
|
|
237
|
-
return deserializeString(
|
|
413
|
+
// @ts-ignore: type
|
|
414
|
+
return deserializeString(srcStart, srcEnd, dst);
|
|
238
415
|
} else if (isArray<T>()) {
|
|
239
416
|
// @ts-ignore
|
|
240
|
-
return deserializeArray<
|
|
241
|
-
}
|
|
242
|
-
let type: nonnull<T> = changetype<nonnull<T>>(0);
|
|
243
|
-
// @ts-ignore: Defined by transform
|
|
244
|
-
if (isDefined(type.__DESERIALIZE)) {
|
|
245
|
-
// @ts-ignore
|
|
246
|
-
return deserializeObject<nonnull<T>>(data.trimStart());
|
|
247
|
-
} else if (type instanceof Map) {
|
|
248
|
-
// @ts-ignore
|
|
249
|
-
return deserializeMap<nonnull<T>>(data.trimStart());
|
|
250
|
-
} else if (type instanceof Date) {
|
|
251
|
-
// @ts-ignore
|
|
252
|
-
return deserializeDate(data);
|
|
253
|
-
} else {
|
|
254
|
-
throw new Error(`Could not deserialize data ${data} to type ${nameof<T>()}. Make sure to add the correct decorators to classes.`);
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
/**
|
|
258
|
-
* Parses valid JSON strings into their original format (safely).
|
|
259
|
-
* ```js
|
|
260
|
-
* JSON.parseSafe<T>(data)
|
|
261
|
-
* ```
|
|
262
|
-
* @param data string
|
|
263
|
-
* @returns T
|
|
264
|
-
*/
|
|
265
|
-
|
|
266
|
-
// @ts-ignore: Decorator
|
|
267
|
-
@inline export function parseSafe<T>(data: string): T {
|
|
268
|
-
if (isBoolean<T>()) {
|
|
269
|
-
return deserializeBoolean_Safe(data) as T;
|
|
270
|
-
} else if (isInteger<T>()) {
|
|
271
|
-
return deserializeInteger_Safe<T>(data);
|
|
272
|
-
} else if (isFloat<T>()) {
|
|
273
|
-
return deserializeFloat<T>(data);
|
|
274
|
-
} else if (isNullable<T>() && data.length === 4 && data == "null") {
|
|
275
|
-
// @ts-ignore
|
|
276
|
-
return null;
|
|
277
|
-
} else if (isString<T>()) {
|
|
278
|
-
// @ts-ignore
|
|
279
|
-
return deserializeString_Safe(data);
|
|
280
|
-
} else if (isArray<T>()) {
|
|
281
|
-
// @ts-ignore
|
|
282
|
-
return deserializeArray_Safe<nonnull<T>>(data);
|
|
283
|
-
}
|
|
284
|
-
let type: nonnull<T> = changetype<nonnull<T>>(0);
|
|
285
|
-
// @ts-ignore: Defined by transform
|
|
286
|
-
if (isDefined(type.__DESERIALIZE)) {
|
|
287
|
-
// @ts-ignore
|
|
288
|
-
return deserializeObject_Safe<nonnull<T>>(data.trimStart());
|
|
289
|
-
} else if (type instanceof Map) {
|
|
290
|
-
// @ts-ignore
|
|
291
|
-
return deserializeMap_Safe<nonnull<T>>(data.trimStart());
|
|
292
|
-
} else if (type instanceof Date) {
|
|
293
|
-
// @ts-ignore
|
|
294
|
-
return deserializeDate_Safe(data);
|
|
417
|
+
return deserializeArray<T>(srcStart, srcEnd, dst);
|
|
295
418
|
} else {
|
|
296
|
-
|
|
419
|
+
let type: nonnull<T> = changetype<nonnull<T>>(0);
|
|
420
|
+
// @ts-ignore: declared by transform
|
|
421
|
+
if (isDefined(type.__DESERIALIZE)) {
|
|
422
|
+
return deserializeObject<T>(srcStart, srcEnd, dst);
|
|
423
|
+
} else if (type instanceof Map) {
|
|
424
|
+
// @ts-ignore: type
|
|
425
|
+
return deserializeMap<T>(srcStart, srcEnd, dst);
|
|
426
|
+
} else if (type instanceof Date) {
|
|
427
|
+
// @ts-ignore: type
|
|
428
|
+
return deserializeDate(srcStart, srcEnd);
|
|
429
|
+
}
|
|
297
430
|
}
|
|
431
|
+
throw new Error(`Could not deserialize data '${ptrToStr(srcStart, srcEnd).slice(0, 100)}' to type. Make sure to add the correct decorators to classes.`);
|
|
298
432
|
}
|
|
299
433
|
}
|
|
300
|
-
|
|
301
|
-
// This allows JSON.stringify and JSON.parse to be available globally through an alias
|
|
302
|
-
// @ts-ignore: Decorator
|
|
303
|
-
@global @inline function __SERIALIZE<T>(data: T): string {
|
|
304
|
-
return JSON.stringify(data);
|
|
305
|
-
}
|
|
306
|
-
// @ts-ignore: Decorator
|
|
307
|
-
@global @inline function __DESERIALIZE<T>(data: string): T {
|
|
308
|
-
return JSON.parse<T>(data);
|
|
309
|
-
}
|
|
310
|
-
// @ts-ignore: Decorator
|
|
311
|
-
@global @inline function __DESERIALIZE_SAFE<T>(data: string): T {
|
|
312
|
-
return JSON.parseSafe<T>(data);
|
|
313
|
-
}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { bs } from "../../../modules/bs";
|
|
2
|
+
import { BACK_SLASH } from "../../custom/chars";
|
|
3
|
+
import { SERIALIZE_ESCAPE_TABLE } from "../../globals/tables";
|
|
4
|
+
import { OBJECT, TOTAL_OVERHEAD } from "rt/common";
|
|
5
|
+
|
|
6
|
+
const SPLAT_34 = i16x8.splat(34); /* " */
|
|
7
|
+
const SPLAT_92 = i16x8.splat(92); /* \ */
|
|
8
|
+
|
|
9
|
+
const SPLAT_32 = i16x8.splat(32); /* [ESC] */
|
|
10
|
+
const SPLAT_0 = i16x8.splat(0); /* 0 */
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Serializes strings into their JSON counterparts using SIMD operations
|
|
14
|
+
* @param srcStart pointer to begin serializing at
|
|
15
|
+
* @param srcEnd pointer to end serialization at
|
|
16
|
+
*/
|
|
17
|
+
export function serializeString_SIMD(src: string): void {
|
|
18
|
+
const srcSize = changetype<OBJECT>(changetype<usize>(src) - TOTAL_OVERHEAD).rtSize;
|
|
19
|
+
let srcStart = changetype<usize>(src);
|
|
20
|
+
const srcEnd = srcStart + srcSize;
|
|
21
|
+
bs.ensureSize(srcSize + 4);
|
|
22
|
+
const srcEnd16 = srcEnd - 15;
|
|
23
|
+
|
|
24
|
+
store<u8>(changetype<usize>(bs.offset), 34); /* " */
|
|
25
|
+
bs.offset += 2;
|
|
26
|
+
|
|
27
|
+
while (srcStart < srcEnd16) {
|
|
28
|
+
const block = v128.load(srcStart);
|
|
29
|
+
v128.store(bs.offset, block);
|
|
30
|
+
|
|
31
|
+
const backslash_indices = i16x8.eq(block, SPLAT_92);
|
|
32
|
+
const quote_indices = i16x8.eq(block, SPLAT_34);
|
|
33
|
+
const escape_indices = i16x8.lt_u(block, SPLAT_32);
|
|
34
|
+
const sieve = v128.or(v128.or(backslash_indices, quote_indices), escape_indices);
|
|
35
|
+
|
|
36
|
+
let mask = i16x8.bitmask(sieve);
|
|
37
|
+
|
|
38
|
+
while (mask != 0) {
|
|
39
|
+
const lane_index = ctz(mask) << 1;
|
|
40
|
+
const dst_offset = bs.offset + lane_index;
|
|
41
|
+
const src_offset = srcStart + lane_index;
|
|
42
|
+
const code = load<u16>(src_offset) << 2;
|
|
43
|
+
const escaped = load<u32>(SERIALIZE_ESCAPE_TABLE + code);
|
|
44
|
+
|
|
45
|
+
mask &= mask - 1;
|
|
46
|
+
|
|
47
|
+
if ((escaped & 0xffff) != BACK_SLASH) {
|
|
48
|
+
bs.ensureSize(10);
|
|
49
|
+
store<u64>(dst_offset, 13511005048209500);
|
|
50
|
+
store<u32>(dst_offset, escaped, 8);
|
|
51
|
+
v128.store(dst_offset, v128.load(src_offset, 2), 12);
|
|
52
|
+
bs.offset += 10;
|
|
53
|
+
} else {
|
|
54
|
+
bs.ensureSize(2);
|
|
55
|
+
store<u32>(dst_offset, escaped);
|
|
56
|
+
v128.store(dst_offset, v128.load(src_offset, 2), 4);
|
|
57
|
+
bs.offset += 2;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
srcStart += 16;
|
|
62
|
+
bs.offset += 16;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
let rem = srcEnd - srcStart;
|
|
66
|
+
|
|
67
|
+
if (rem & 8) {
|
|
68
|
+
const block = v128.load64_zero(srcStart);
|
|
69
|
+
v128.store64_lane(bs.offset, block, 0);
|
|
70
|
+
|
|
71
|
+
const backslash_indices = i16x8.eq(block, SPLAT_92);
|
|
72
|
+
const quote_indices = i16x8.eq(block, SPLAT_34);
|
|
73
|
+
const escape_indices = i16x8.lt_u(block, SPLAT_32);
|
|
74
|
+
const zero_indices = i16x8.eq(block, SPLAT_0);
|
|
75
|
+
const sieve = v128.and(v128.or(v128.or(backslash_indices, quote_indices), escape_indices), v128.not(zero_indices));
|
|
76
|
+
|
|
77
|
+
let mask = i16x8.bitmask(sieve);
|
|
78
|
+
while (mask != 0) {
|
|
79
|
+
let lane_index = ctz(mask) << 1;
|
|
80
|
+
const dst_offset = bs.offset + lane_index;
|
|
81
|
+
const src_offset = srcStart + lane_index;
|
|
82
|
+
const code = load<u16>(src_offset) << 2;
|
|
83
|
+
const escaped = load<u32>(SERIALIZE_ESCAPE_TABLE + code);
|
|
84
|
+
mask &= mask - 1;
|
|
85
|
+
|
|
86
|
+
if ((escaped & 0xffff) != BACK_SLASH) {
|
|
87
|
+
bs.ensureSize(10);
|
|
88
|
+
store<u64>(dst_offset, 13511005048209500);
|
|
89
|
+
store<u32>(dst_offset, escaped, 8);
|
|
90
|
+
while (lane_index < 6) {
|
|
91
|
+
store<u8>(bs.offset + lane_index, load<u8>(srcStart + lane_index, 2), 12);
|
|
92
|
+
lane_index += 2;
|
|
93
|
+
}
|
|
94
|
+
bs.offset += 10;
|
|
95
|
+
} else {
|
|
96
|
+
bs.ensureSize(2);
|
|
97
|
+
store<u32>(dst_offset, escaped);
|
|
98
|
+
|
|
99
|
+
while (lane_index < 6) {
|
|
100
|
+
store<u8>(bs.offset + lane_index, load<u8>(srcStart + lane_index, 2), 4);
|
|
101
|
+
lane_index += 2;
|
|
102
|
+
}
|
|
103
|
+
bs.offset += 2;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
bs.offset += 8;
|
|
108
|
+
srcStart += 8;
|
|
109
|
+
}
|
|
110
|
+
if (rem & 4) {
|
|
111
|
+
const block = load<u32>(srcStart);
|
|
112
|
+
const codeA = block & 0xffff;
|
|
113
|
+
const codeB = (block >> 16) & 0xffff;
|
|
114
|
+
|
|
115
|
+
if (codeA == 92 || codeA == 34 || codeA < 32) {
|
|
116
|
+
const escaped = load<u32>(SERIALIZE_ESCAPE_TABLE + (codeA << 2));
|
|
117
|
+
|
|
118
|
+
if ((escaped & 0xffff) != BACK_SLASH) {
|
|
119
|
+
bs.ensureSize(10);
|
|
120
|
+
store<u64>(bs.offset, 13511005048209500);
|
|
121
|
+
store<u32>(bs.offset, escaped, 8);
|
|
122
|
+
bs.offset += 12;
|
|
123
|
+
} else {
|
|
124
|
+
bs.ensureSize(2);
|
|
125
|
+
store<u32>(bs.offset, escaped);
|
|
126
|
+
bs.offset += 4;
|
|
127
|
+
}
|
|
128
|
+
} else {
|
|
129
|
+
store<u16>(bs.offset, codeA);
|
|
130
|
+
bs.offset += 2;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (codeB == 92 || codeB == 34 || codeB < 32) {
|
|
134
|
+
const escaped = load<u32>(SERIALIZE_ESCAPE_TABLE + (codeB << 2));
|
|
135
|
+
|
|
136
|
+
if ((escaped & 0xffff) != BACK_SLASH) {
|
|
137
|
+
bs.ensureSize(10);
|
|
138
|
+
store<u64>(bs.offset, 13511005048209500);
|
|
139
|
+
store<u32>(bs.offset, escaped, 8);
|
|
140
|
+
bs.offset += 12;
|
|
141
|
+
} else {
|
|
142
|
+
bs.ensureSize(2);
|
|
143
|
+
store<u32>(bs.offset, escaped);
|
|
144
|
+
bs.offset += 4;
|
|
145
|
+
}
|
|
146
|
+
} else {
|
|
147
|
+
store<u16>(bs.offset, codeB);
|
|
148
|
+
bs.offset += 2;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
srcStart += 4;
|
|
152
|
+
}
|
|
153
|
+
if (rem & 2) {
|
|
154
|
+
const code = load<u16>(srcStart);
|
|
155
|
+
if (code == 92 || code == 34 || code < 32) {
|
|
156
|
+
const escaped = load<u32>(SERIALIZE_ESCAPE_TABLE + (code << 2));
|
|
157
|
+
|
|
158
|
+
if ((escaped & 0xffff) != BACK_SLASH) {
|
|
159
|
+
bs.ensureSize(10);
|
|
160
|
+
store<u64>(bs.offset, 13511005048209500);
|
|
161
|
+
store<u32>(bs.offset, escaped, 8);
|
|
162
|
+
bs.offset += 12;
|
|
163
|
+
} else {
|
|
164
|
+
bs.ensureSize(2);
|
|
165
|
+
store<u32>(bs.offset, escaped);
|
|
166
|
+
bs.offset += 4;
|
|
167
|
+
}
|
|
168
|
+
} else {
|
|
169
|
+
store<u16>(bs.offset, code);
|
|
170
|
+
bs.offset += 2;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
store<u8>(bs.offset, 34); /* " */
|
|
175
|
+
bs.offset += 2;
|
|
176
|
+
}
|