json-as 0.5.3 → 0.5.5

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 CHANGED
@@ -1,7 +1,10 @@
1
1
  # AS-JSON
2
+ ![AssemblyScript](https://img.shields.io/badge/AssemblyScript-blue)
3
+ ![WebAssembly](https://img.shields.io/badge/WebAssemby-purple)
2
4
 
3
- **JSON serializer/deserializer for AssemblyScript**
5
+ ## Features
4
6
 
7
+ Full
5
8
  ## Installation
6
9
 
7
10
  ```bash
@@ -11,6 +14,12 @@
11
14
  ~ npm install visitor-as
12
15
  ```
13
16
 
17
+ For arbitrary-length numbers, use
18
+
19
+ ```bash
20
+ ~ npm install as-bignum
21
+ ```
22
+
14
23
  Add the transform to your `asc` command
15
24
 
16
25
  ```bash
@@ -31,34 +40,50 @@ Or, add it to `asconfig.json`
31
40
 
32
41
  ```js
33
42
  import { JSON } from "json-as/assembly";
43
+ import { u128 } from "as-bignum/assembly";
34
44
 
45
+ // @ts-ignore
35
46
  @json
36
- class Vec2 {
37
- x: f32
38
- y: f32
47
+ class Stats {
48
+ wins: u128
49
+ loss: u128
50
+ }
51
+ // @ts-ignore
52
+ @json
53
+ class Vec3 {
54
+ x: f32;
55
+ y: f32;
56
+ z: f32;
39
57
  }
40
58
 
59
+ // @ts-ignore
41
60
  @json
42
61
  class Player {
43
- firstName: string
44
- lastName: string
45
- lastActive: i32[]
46
- age: i32
47
- pos: Vec2
48
- isVerified: boolean
62
+ firstName: string;
63
+ lastName: string;
64
+ lastActive: i32[];
65
+ age: i32;
66
+ pos: Vec3 | null;
67
+ isVerified: boolean;
68
+ stats: Stats
49
69
  }
50
70
 
51
- const data: Player = {
71
+ const player: Player = {
52
72
  firstName: "Emmet",
53
73
  lastName: "West",
54
74
  lastActive: [8, 27, 2022],
55
75
  age: 23,
56
76
  pos: {
57
- x: -3.4,
58
- y: 1.2
77
+ x: 3.4,
78
+ y: 1.2,
79
+ z: 8.3
59
80
  },
60
- isVerified: true
61
- }
81
+ isVerified: true,
82
+ stats: {
83
+ wins: u128.fromString("443"),
84
+ loss: u128.fromString("693")
85
+ }
86
+ };
62
87
 
63
88
  const stringified = JSON.stringify<Player>(data);
64
89
 
@@ -68,9 +93,9 @@ const parsed = JSON.parse<Player>(stringified);
68
93
 
69
94
  ## Performance
70
95
 
71
- **Serialize Object (Vec2):** ~7.29m ops/s
96
+ **Serialize Object (Vec2):** ~7.20m ops/s
72
97
 
73
- **Deserialize Object (Vec2):** ~1.36m ops/s
98
+ **Deserialize Object (Vec2):** ~2.2m ops/s
74
99
 
75
100
  **Serialize Array (int[4]):** ~1.4m ops/s
76
101
 
package/asconfig.json CHANGED
@@ -11,6 +11,8 @@
11
11
  },
12
12
  "options": {
13
13
  "transform": ["./transform"],
14
- "bindings": "esm"
15
- }
14
+ "bindings": "esm",
15
+ "extends": "./node_modules/@assemblyscript/wasi-shim/asconfig.json"
16
+ },
17
+ "extends": "./node_modules/@assemblyscript/wasi-shim/asconfig.json"
16
18
  }
@@ -1,4 +1,5 @@
1
1
  import { JSON } from "..";
2
+ import { u128, u128Safe, u256, u256Safe, i128, i128Safe, i256Safe } from "as-bignum/assembly";
2
3
  function canSerde<T>(data: T): void {
3
4
  const serialized = JSON.stringify<T>(data);
4
5
  const deserialized = JSON.stringify<T>(JSON.parse<T>(serialized));
@@ -39,6 +40,34 @@ describe("Ser/de Numbers", () => {
39
40
  canSerde<u64>(101);
40
41
  canSerde<i32>(-100);
41
42
  canSerde<i64>(-101);
43
+
44
+ canSerde<u128>(u128.from("0"))
45
+ canSerde<u128>(u128.from("100"))
46
+ canSerde<u128>(u128.from("101"))
47
+
48
+ canSerde<u128Safe>(u128Safe.from("0"))
49
+ canSerde<u128Safe>(u128Safe.from("100"))
50
+ canSerde<u128Safe>(u128Safe.from("101"))
51
+
52
+ canSerde<u256>(u256.fromU128(u128.from("0")))
53
+ canSerde<u256>(u256.fromU128(u128.from("100")))
54
+ canSerde<u256>(u256.fromU128(u128.from("101")))
55
+
56
+ canSerde<u256Safe>(u256Safe.fromU128(u128.from("0")))
57
+ canSerde<u256Safe>(u256Safe.fromU128(u128.from("100")))
58
+ canSerde<u256Safe>(u256Safe.fromU128(u128.from("101")))
59
+
60
+ canSerde<i128>(i128.from("0"))
61
+ canSerde<i128>(i128.from("100"))
62
+ canSerde<i128>(i128.from("101"))
63
+
64
+ canSerde<i128Safe>(i128Safe.from("0"))
65
+ canSerde<i128Safe>(i128Safe.from("100"))
66
+ canSerde<i128Safe>(i128Safe.from("101"))
67
+ canSerde<i128Safe>(i128Safe.from("-100"))
68
+ canSerde<i128Safe>(i128Safe.from("-101"))
69
+
70
+ canSerde<i256Safe>(new i256Safe(10, 11, 500, 501))
42
71
  });
43
72
 
44
73
  it("should ser/de floats", () => {
@@ -71,6 +100,21 @@ describe("Ser/de Numbers", () => {
71
100
  'string with colon : comma , brace [ ] bracket { } and quote " and other quote \\"'
72
101
  );
73
102
  });
103
+
104
+ it("should ser/de BigInt objects", () => {
105
+ canSerde<i32>(0);
106
+
107
+ canSerde<u32>(100);
108
+ canSerde<u64>(101);
109
+ canSerde<i32>(-100);
110
+ canSerde<i64>(-101);
111
+ canSerde<u128>(u128.from("0"))
112
+ canSerde<u128>(u128.from("100"))
113
+ canSerde<u128>(u128.from("101"))
114
+ canSerde<u128>(u128.from("-100"))
115
+ canSerde<u128>(u128.from("-101"))
116
+
117
+ })
74
118
  });
75
119
 
76
120
  describe("Ser/de Array", () => {
File without changes
package/assembly/index.ts CHANGED
@@ -1 +1 @@
1
- export { JSON } from "./json";
1
+ export { JSON } from "./src/json";
@@ -1,3 +1,4 @@
1
+ // Characters
1
2
  export const commaCode = ",".charCodeAt(0);
2
3
  export const quoteCode = '"'.charCodeAt(0);
3
4
  export const backSlashCode = "\\".charCodeAt(0);
@@ -16,3 +17,11 @@ export const aCode = "a".charCodeAt(0);
16
17
  export const lCode = "l".charCodeAt(0);
17
18
  export const sCode = "s".charCodeAt(0);
18
19
  export const nCode = "n".charCodeAt(0);
20
+ // Strings
21
+ export const trueWord = "true";
22
+ export const falseWord = "false";
23
+ export const nullWord = "null";
24
+ export const leftBracketWord = "[";
25
+ export const emptyArrayWord = "[]";
26
+ export const commaWord = ",";
27
+ export const rightBracketWord = "]";
@@ -0,0 +1,494 @@
1
+ import { u128, u128Safe, u256, u256Safe, i128, i128Safe, i256Safe } from "as-bignum/assembly";
2
+ import { StringSink } from "as-string-sink/assembly";
3
+ import { isSpace } from "util/string";
4
+ import {
5
+ backSlashCode,
6
+ commaCode,
7
+ commaWord,
8
+ eCode,
9
+ fCode,
10
+ leftBraceCode,
11
+ leftBracketCode,
12
+ leftBracketWord,
13
+ nCode,
14
+ nullWord,
15
+ quoteCode,
16
+ rCode,
17
+ rightBraceCode,
18
+ rightBracketCode,
19
+ rightBracketWord,
20
+ tCode,
21
+ trueWord,
22
+ uCode,
23
+ emptyArrayWord
24
+ } from "./chars";
25
+ import { isBigNum, unsafeCharCodeAt } from "./util";
26
+
27
+ /**
28
+ * JSON Encoder/Decoder for AssemblyScript
29
+ */
30
+ export namespace JSON {
31
+ /**
32
+ * Stringifies valid JSON data.
33
+ * ```js
34
+ * JSON.stringify<T>(data)
35
+ * ```
36
+ * @param data T
37
+ * @returns string
38
+ */
39
+ export function stringify<T>(data: T): string {
40
+ // String
41
+ if (isString<T>()) {
42
+ return '"' + (<string>data).replaceAll('"', '\\"') + '"';
43
+ }
44
+ // Boolean
45
+ else if (isBoolean<T>()) {
46
+ return data ? "true" : "false";
47
+ }
48
+ // Nullable
49
+ else if (isNullable<T>() && data == null) {
50
+ return "null";
51
+ }
52
+ // Integers/Floats
53
+ // @ts-ignore
54
+ else if ((isInteger<T>() || isFloat<T>()) && isFinite(data)) {
55
+ // @ts-ignore
56
+ return data.toString();
57
+ }
58
+ // Class-Based serialization
59
+ // @ts-ignore
60
+ else if (isDefined(data.__JSON_Serialize)) {
61
+ // @ts-ignore
62
+ //if (isNullable<T>()) return "null";
63
+ // @ts-ignore
64
+ return data.__JSON_Serialize();
65
+ }
66
+ // ArrayLike
67
+ else if (isArrayLike<T>()) {
68
+ let result = new StringSink(leftBracketWord);
69
+ // @ts-ignore
70
+ if (data.length == 0) return emptyArrayWord;
71
+ // @ts-ignore
72
+ for (let i = 0; i < data.length - 1; i++) {
73
+ // @ts-ignore
74
+ result.write(JSON.stringify(unchecked(data[i])));
75
+ result.write(commaWord);
76
+ }
77
+ // @ts-ignore
78
+ result.write(JSON.stringify(unchecked(data[data.length - 1])));
79
+ result.write(rightBracketWord);
80
+ return result.toString();
81
+ } else if ((isManaged<T>() || isReference<T>()) && isBigNum<T>()) {
82
+ // @ts-ignore
83
+ return data.toString();
84
+ } else {
85
+ throw new Error(`Could not serialize data of type ${nameof<T>()}. Invalid data provided.`);
86
+ }
87
+ }
88
+ /**
89
+ * Parses valid JSON strings into their original format.
90
+ * ```js
91
+ * JSON.parse<T>(data)
92
+ * ```
93
+ * @param data string
94
+ * @returns T
95
+ */
96
+ export function parse<T>(data: string): T {
97
+ let type!: T;
98
+ if (isString<T>()) {
99
+ // @ts-ignore
100
+ return parseString(data);
101
+ } else if (isBoolean<T>()) {
102
+ // @ts-ignore
103
+ return parseBoolean<T>(data);
104
+ } else if (isFloat<T>() || isInteger<T>()) {
105
+ return parseNumber<T>(data);
106
+ } else if (isArrayLike<T>()) {
107
+ // @ts-ignore
108
+ return parseArray<T>(data.trimStart());
109
+ // @ts-ignore
110
+ } else if (isNullable<T>() && data == "null") {
111
+ // @ts-ignore
112
+ return null;
113
+ // @ts-ignore
114
+ } else if (isDefined(type.__JSON_Set_Key)) {
115
+ return parseObject<T>(data.trimStart());
116
+ } else if ((isManaged<T>() || isReference<T>()) && isBigNum<T>()) {
117
+ // @ts-ignore
118
+ return parseBigNum<T>(data);
119
+ } else {
120
+ // @ts-ignore
121
+ throw new Error(`Could not deserialize data ${data} to type ${nameof<T>()}. Invalide data provided.`);
122
+ }
123
+ }
124
+ function parseObjectValue<T>(data: string): T {
125
+ let type!: T;
126
+ if (isString<T>()) {
127
+ // @ts-ignore
128
+ return data.replaceAll('\\"', '"');
129
+ } else if (isBoolean<T>()) {
130
+ // @ts-ignore
131
+ return parseBoolean<T>(data);
132
+ } else if (isFloat<T>() || isInteger<T>()) {
133
+ return parseNumber<T>(data);
134
+ } else if (isArrayLike<T>()) {
135
+ // @ts-ignore
136
+ return parseArray<T>(data);
137
+ // @ts-ignore
138
+ } else if (isNullable<T>() && data == "null") {
139
+ // @ts-ignore
140
+ return null;
141
+ // @ts-ignore
142
+ } else if (isDefined(type.__JSON_Set_Key)) {
143
+ // @ts-ignore
144
+ //if (isNullable<T>()) return null;
145
+ return parseObject<T>(data);
146
+ } else if ((isManaged<T>() || isReference<T>()) && isBigNum<T>()) {
147
+ // @ts-ignore
148
+ return parseBigNum<T>(data);
149
+ } else {
150
+ // @ts-ignore
151
+ //return null;
152
+ throw new Error(`Could not deserialize data ${data} to type ${nameof<T>()}. Invalide data provided.`)
153
+ }
154
+ }
155
+ /*export class Arr extends Array<Variant> {
156
+ public data: Variant[] = [];
157
+ push<T>(data: T): i32 {
158
+ return this.data.push(Variant.from<T>(data));
159
+ }
160
+ at<T>(index: i32): T {
161
+ return this.data.at(index).get<T>();
162
+ }
163
+ }*/
164
+ }
165
+
166
+ // @ts-ignore
167
+ @inline
168
+ // @ts-ignore
169
+ function parseBigNum<T>(data: string): T {
170
+ // @ts-ignore
171
+ if (idof<T>() == idof<u128>()) return u128.fromString(data);
172
+ // @ts-ignore
173
+ if (idof<T>() == idof<u128Safe>()) return u128Safe.fromString(data);
174
+ // @ts-ignore
175
+ if (idof<T>() == idof<u256>()) return u128Safe.fromString(data);
176
+ // @ts-ignore
177
+ if (idof<T>() == idof<u256Safe>()) return u256Safe.fromString(data);
178
+ // @ts-ignore
179
+ if (idof<T>() == idof<i128>()) return i128.fromString(data);
180
+ // @ts-ignore
181
+ if (idof<T>() == idof<i128Safe>()) return i128Safe.fromString(data);
182
+ // @ts-ignore
183
+ if (idof<T>() == idof<i256Safe>()) return i256Safe.fromString(data);
184
+ }
185
+
186
+ // @ts-ignore
187
+ @inline
188
+ function parseString(data: string): string {
189
+ return data.slice(1, data.length - 1).replaceAll('\\"', '"');
190
+ }
191
+
192
+ // @ts-ignore
193
+ @inline
194
+ function parseBoolean<T extends boolean>(data: string): T {
195
+ if (data.length > 3 && data.startsWith("true")) return <T>true;
196
+ else if (data.length > 4 && data.startsWith("false")) return <T>false;
197
+ else throw new Error(`JSON: Cannot parse "${data}" as boolean`);
198
+ }
199
+
200
+ // @ts-ignore
201
+ @inline
202
+ function parseNumber<T>(data: string): T {
203
+ let type: T;
204
+ // @ts-ignore
205
+ if (type instanceof f64) return F64.parseFloat(data);
206
+ // @ts-ignore
207
+ else if (type instanceof f32) return F32.parseFloat(data);
208
+ // @ts-ignore
209
+ else if (type instanceof u64) return U64.parseInt(data);
210
+ // @ts-ignore
211
+ else if (type instanceof u32) return U32.parseInt(data);
212
+ // @ts-ignore
213
+ else if (type instanceof u8) return U8.parseInt(data);
214
+ // @ts-ignore
215
+ else if (type instanceof u16) return U16.parseInt(data);
216
+ // @ts-ignore
217
+ else if (type instanceof i64) return I64.parseInt(data);
218
+ // @ts-ignore
219
+ else if (type instanceof i32) return I32.parseInt(data);
220
+ // @ts-ignore
221
+ else if (type instanceof i16) return I16.parseInt(data);
222
+ // @ts-ignore
223
+ else if (type instanceof i8) return I8.parseInt(data);
224
+ else
225
+ throw new Error(
226
+ `JSON: Cannot parse invalid data into a number. Either "${data}" is not a valid number, or <${nameof<T>()}> is an invald number type.`
227
+ );
228
+ }
229
+
230
+ // @ts-ignore
231
+ @inline
232
+ export function parseObject<T>(data: string): T {
233
+ let schema: nonnull<T> = changetype<nonnull<T>>(__new(offsetof<nonnull<T>>(), idof<nonnull<T>>()));
234
+ let key = "";
235
+ let isKey = false;
236
+ let depth = 1;
237
+ let char = 0;
238
+ let outerLoopIndex = 1;
239
+ for (; outerLoopIndex < data.length - 1; outerLoopIndex++) {
240
+ char = unsafeCharCodeAt(data, outerLoopIndex);
241
+ if (char === leftBracketCode) {
242
+ for (
243
+ let arrayValueIndex = outerLoopIndex;
244
+ arrayValueIndex < data.length - 1;
245
+ arrayValueIndex++
246
+ ) {
247
+ char = unsafeCharCodeAt(data, arrayValueIndex);
248
+ if (char === leftBracketCode) {
249
+ depth = depth << 1;
250
+ } else if (char === rightBracketCode) {
251
+ depth = depth >> 1;
252
+ if (depth === 1) {
253
+ ++arrayValueIndex;
254
+ schema.__JSON_Set_Key(key, data.slice(outerLoopIndex, arrayValueIndex));
255
+ outerLoopIndex = arrayValueIndex;
256
+ isKey = false;
257
+ break;
258
+ }
259
+ }
260
+ }
261
+ } else if (char === leftBraceCode) {
262
+ for (
263
+ let objectValueIndex = outerLoopIndex;
264
+ objectValueIndex < data.length - 1;
265
+ objectValueIndex++
266
+ ) {
267
+ char = unsafeCharCodeAt(data, objectValueIndex);
268
+ if (char === leftBraceCode) {
269
+ depth = depth << 1;
270
+ } else if (char === rightBraceCode) {
271
+ depth = depth >> 1;
272
+ if (depth === 1) {
273
+ ++objectValueIndex;
274
+ schema.__JSON_Set_Key(key, data.slice(outerLoopIndex, objectValueIndex));
275
+ outerLoopIndex = objectValueIndex;
276
+ isKey = false;
277
+ break;
278
+ }
279
+ }
280
+ }
281
+ } else if (char === quoteCode) {
282
+ for (
283
+ let stringValueIndex = ++outerLoopIndex;
284
+ stringValueIndex < data.length - 1;
285
+ stringValueIndex++
286
+ ) {
287
+ char = unsafeCharCodeAt(data, stringValueIndex);
288
+ if (
289
+ char === quoteCode &&
290
+ unsafeCharCodeAt(data, stringValueIndex - 1) !== backSlashCode
291
+ ) {
292
+ if (isKey === false) {
293
+ key = data.slice(outerLoopIndex, stringValueIndex);
294
+ isKey = true;
295
+ } else {
296
+ schema.__JSON_Set_Key(key, data.slice(outerLoopIndex, stringValueIndex));
297
+ isKey = false;
298
+ }
299
+ outerLoopIndex = ++stringValueIndex;
300
+ break;
301
+ }
302
+ }
303
+ } else if (char == nCode) {
304
+ schema.__JSON_Set_Key(key, nullWord);
305
+ isKey = false;
306
+ } else if (
307
+ char === tCode &&
308
+ unsafeCharCodeAt(data, ++outerLoopIndex) === rCode &&
309
+ unsafeCharCodeAt(data, ++outerLoopIndex) === uCode &&
310
+ unsafeCharCodeAt(data, ++outerLoopIndex) === eCode
311
+ ) {
312
+ schema.__JSON_Set_Key(key, trueWord);
313
+ isKey = false;
314
+ } else if (
315
+ char === fCode &&
316
+ unsafeCharCodeAt(data, ++outerLoopIndex) === "a".charCodeAt(0) &&
317
+ unsafeCharCodeAt(data, ++outerLoopIndex) === "l".charCodeAt(0) &&
318
+ unsafeCharCodeAt(data, ++outerLoopIndex) === "s".charCodeAt(0) &&
319
+ unsafeCharCodeAt(data, ++outerLoopIndex) === eCode
320
+ ) {
321
+ schema.__JSON_Set_Key(key, "false");
322
+ isKey = false;
323
+ } else if ((char >= 48 && char <= 57) || char === 45) {
324
+ let numberValueIndex = ++outerLoopIndex;
325
+ for (; numberValueIndex < data.length; numberValueIndex++) {
326
+ char = unsafeCharCodeAt(data, numberValueIndex);
327
+ if (char === commaCode || char === rightBraceCode || isSpace(char)) {
328
+ schema.__JSON_Set_Key(key, data.slice(outerLoopIndex - 1, numberValueIndex));
329
+ outerLoopIndex = numberValueIndex;
330
+ isKey = false;
331
+ break;
332
+ }
333
+ }
334
+ }
335
+ }
336
+ return schema;
337
+ }
338
+
339
+ // @ts-ignore
340
+ @inline
341
+ // @ts-ignore
342
+ export function parseArray<T extends unknown[]>(data: string): T {
343
+ let type!: valueof<T>;
344
+ if (type instanceof String) {
345
+ return <T>parseStringArray(data);
346
+ } else if (isBoolean<valueof<T>>()) {
347
+ // @ts-ignore
348
+ return parseBooleanArray<T>(data);
349
+ } else if (isFloat<valueof<T>>() || isInteger<valueof<T>>()) {
350
+ // @ts-ignore
351
+ return parseNumberArray<T>(data);
352
+ } else if (isArrayLike<valueof<T>>()) {
353
+ // @ts-ignore
354
+ return parseArrayArray<T>(data);
355
+ // @ts-ignore
356
+ } else if (isDefined(type.__JSON_Set_Key)) {
357
+ // @ts-ignore
358
+ return parseObjectArray<T>(data);
359
+ }
360
+ }
361
+
362
+ // @ts-ignore
363
+ @inline
364
+ export function parseStringArray(data: string): string[] {
365
+ const result: string[] = [];
366
+ let lastPos = 0;
367
+ let instr = false;
368
+ for (let i = 1; i < data.length - 1; i++) {
369
+ if (unsafeCharCodeAt(data, i) === quoteCode) {
370
+ if (instr === false) {
371
+ instr = true;
372
+ lastPos = i;
373
+ } else if (unsafeCharCodeAt(data, i - 1) !== backSlashCode) {
374
+ instr = false;
375
+ result.push(data.slice(lastPos + 1, i).replaceAll('\\"', '"'));
376
+ }
377
+ }
378
+ }
379
+ return result;
380
+ }
381
+
382
+ // @ts-ignore
383
+ @inline
384
+ export function parseBooleanArray<T extends boolean[]>(data: string): T {
385
+ const result = instantiate<T>();
386
+ let lastPos = 1;
387
+ let char = 0;
388
+ for (let i = 1; i < data.length - 1; i++) {
389
+ char = unsafeCharCodeAt(data, i);
390
+ /*// if char == "t" && i+3 == "e"
391
+ if (char === tCode && data.charCodeAt(i + 3) === eCode) {
392
+ //i += 3;
393
+ result.push(parseBoolean<valueof<T>>(data.slice(lastPos, i+2)));
394
+ //i++;
395
+ } else if (char === fCode && data.charCodeAt(i + 4) === eCode) {
396
+ //i += 4;
397
+ result.push(parseBoolean<valueof<T>>(data.slice(lastPos, i+3)));
398
+ //i++;
399
+ }*/
400
+ if (char === tCode || char === fCode) {
401
+ lastPos = i;
402
+ } else if (char === eCode) {
403
+ i++;
404
+ result.push(parseBoolean<valueof<T>>(data.slice(lastPos, i)));
405
+ }
406
+ }
407
+ return result;
408
+ }
409
+
410
+ // @ts-ignore
411
+ @inline
412
+ export function parseNumberArray<T extends number[]>(data: string): T {
413
+ const result = instantiate<T>();
414
+ let lastPos = 0;
415
+ let char = 0;
416
+ let i = 1;
417
+ for (; i < data.length - 1; i++) {
418
+ char = unsafeCharCodeAt(data, i);
419
+ if ((lastPos === 0 && char >= 48 && char <= 57) || char === 45) {
420
+ lastPos = i;
421
+ } else if ((isSpace(char) || char == commaCode) && lastPos > 0) {
422
+ result.push(parseNumber<valueof<T>>(data.slice(lastPos, i)));
423
+ lastPos = 0;
424
+ }
425
+ }
426
+ for (; i > lastPos - 1; i--) {
427
+ char = unsafeCharCodeAt(data, i);
428
+ if (char !== rightBracketCode) {
429
+ result.push(parseNumber<valueof<T>>(data.slice(lastPos, i + 1)));
430
+ break;
431
+ }
432
+ }
433
+ return result;
434
+ }
435
+
436
+ // @ts-ignore
437
+ @inline
438
+ export function parseArrayArray<T extends unknown[][]>(data: string): T {
439
+ const result = instantiate<T>();
440
+ let char = 0;
441
+ let lastPos = 0;
442
+ let depth = 1;
443
+ let i = 1;
444
+ // Find start of bracket
445
+ //for (; unsafeCharCodeAt(data, i) !== leftBracketCode; i++) {}
446
+ //i++;
447
+ for (; i < data.length - 1; i++) {
448
+ char = unsafeCharCodeAt(data, i);
449
+ if (char === leftBracketCode) {
450
+ if (depth === 1) {
451
+ lastPos = i;
452
+ }
453
+ // Shifting is 6% faster than incrementing
454
+ depth = depth << 1;
455
+ } else if (char === rightBracketCode) {
456
+ depth = depth >> 1;
457
+ if (depth === 1) {
458
+ i++;
459
+ result.push(JSON.parse<valueof<T>>(data.slice(lastPos, i)));
460
+ }
461
+ }
462
+ }
463
+ return result;
464
+ }
465
+
466
+ // @ts-ignore
467
+ @inline
468
+ export function parseObjectArray<T extends unknown[][]>(data: string): T {
469
+ const result = instantiate<T>();
470
+ let char = 0;
471
+ let lastPos = 1;
472
+ let depth = 1;
473
+ let i = 1;
474
+ // Find start of bracket
475
+ //for (; unsafeCharCodeAt(data, i) !== leftBracketCode; i++) { }
476
+ //i++;
477
+ for (; i < data.length - 1; i++) {
478
+ char = unsafeCharCodeAt(data, i);
479
+ if (char === leftBraceCode) {
480
+ if (depth === 1) {
481
+ lastPos = i;
482
+ }
483
+ // Shifting is 6% faster than incrementing
484
+ depth = depth << 1;
485
+ } else if (char === rightBraceCode) {
486
+ depth = depth >> 1;
487
+ if (depth === 1) {
488
+ i++;
489
+ result.push(JSON.parse<valueof<T>>(data.slice(lastPos, i)));
490
+ }
491
+ }
492
+ }
493
+ return result;
494
+ }
@@ -1,6 +1,21 @@
1
1
  import { StringSink } from "as-string-sink/assembly";
2
2
  import { isSpace } from "assemblyscript/std/assembly/util/string";
3
3
  import { backSlashCode, quoteCode } from "./chars";
4
+ import { u128, u128Safe, u256, u256Safe, i128, i128Safe, i256Safe } from "as-bignum/assembly";
5
+
6
+ // @ts-ignore
7
+ @inline
8
+ export function isBigNum<T>(): boolean {
9
+ if (idof<T>() == idof<u128>()) return true;
10
+ if (idof<T>() == idof<u128Safe>()) return true;
11
+ if (idof<T>() == idof<u256>()) return true;
12
+ if (idof<T>() == idof<u256Safe>()) return true;
13
+ if (idof<T>() == idof<i128>()) return true;
14
+ if (idof<T>() == idof<i128Safe>()) return true;
15
+ if (idof<T>() == idof<i256Safe>()) return true;
16
+ return false;
17
+ }
18
+
4
19
  // @ts-ignore
5
20
  @inline
6
21
  export function unsafeCharCodeAt(data: string, pos: i32): i32 {
package/assembly/test.ts CHANGED
@@ -1,8 +1,15 @@
1
1
  import "wasi";
2
+ import { u128 } from "as-bignum/assembly";
2
3
  import {
3
4
  JSON
4
5
  } from ".";
5
6
 
7
+ // @ts-ignore
8
+ @json
9
+ class Stats {
10
+ wins: u128
11
+ loss: u128
12
+ }
6
13
  // @ts-ignore
7
14
  @json
8
15
  class Vec3 {
@@ -20,6 +27,7 @@ class Player {
20
27
  age: i32;
21
28
  pos: Vec3 | null;
22
29
  isVerified: boolean;
30
+ stats: Stats
23
31
  }
24
32
 
25
33
  const player: Player = {
@@ -33,9 +41,13 @@ const player: Player = {
33
41
  z: 8.3
34
42
  },
35
43
  isVerified: true,
44
+ stats: {
45
+ wins: u128.fromString("443"),
46
+ loss: u128.fromString("693")
47
+ }
36
48
  };
37
49
 
38
50
  const serializedPlayer = JSON.stringify<Player>(player);
39
51
  console.log("Serialized Player: " + serializedPlayer);
40
52
  const deserializedPlayer = JSON.parse<Player>(serializedPlayer);
41
- console.log("Deserialized Player: " + JSON.stringify(deserializedPlayer));
53
+ console.log("Deserialized Player: " + JSON.stringify(deserializedPlayer));
package/index.ts CHANGED
@@ -1 +1 @@
1
- export { JSON } from "./assembly/json";
1
+ export { JSON } from "./assembly/src/json";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "json-as",
3
- "version": "0.5.3",
3
+ "version": "0.5.5",
4
4
  "description": "JSON encoder/decoder for AssemblyScript",
5
5
  "types": "assembly/index.ts",
6
6
  "author": "Jairus Tanaka",
@@ -29,7 +29,8 @@
29
29
  "typescript": "^4.7.2"
30
30
  },
31
31
  "dependencies": {
32
- "as-string-sink": "^0.5.0"
32
+ "as-string-sink": "^0.5.0",
33
+ "as-variant": "^0.4.0"
33
34
  },
34
35
  "repository": {
35
36
  "type": "git",
@@ -6,9 +6,10 @@ class AsJSONTransform extends ClassDecorator {
6
6
  super(...arguments);
7
7
  this.sources = [];
8
8
  this.encodeStmts = [];
9
- this.decodeStmts = [];
10
- this.checkDecodeStmts = [];
9
+ //public decodeStmts: string[] = [];
10
+ this.setDataStmts = [];
11
11
  }
12
+ //public checkDecodeStmts: string[] = [];
12
13
  visitMethodDeclaration() { }
13
14
  visitFieldDeclaration(node) {
14
15
  const lineText = toString(node);
@@ -22,9 +23,19 @@ class AsJSONTransform extends ClassDecorator {
22
23
  // @ts-ignore
23
24
  this.encodeStmts.push(`"${name}":\${JSON.stringify<${type}>(this.${name})},`);
24
25
  // @ts-ignore
25
- this.decodeStmts.push(`${name}: JSON.parseObjectValue<${type}>(values.get("${name}")),\n`);
26
+ //this.decodeStmts.push(
27
+ // `${name}: JSON.parseObjectValue<${type}>(values.get("${name}")),\n`
28
+ //);
26
29
  // @ts-ignore
27
- this.checkDecodeStmts.push(' if (!values.has("${name}")) throw new Error("Key "${name}" was not found. Cannot instantiate object.");\n');
30
+ this.setDataStmts.push(`if (key.length === ${name.length} && (memory.compare(changetype<usize>("${name}"), changetype<usize>(key), ${name.length}) == 0)) {
31
+ this.${name} = JSON.parseObjectValue<${type}>(value);
32
+ return;
33
+ }
34
+ `);
35
+ // @ts-ignore
36
+ //this.checkDecodeStmts.push(
37
+ // ' if (!values.has("${name}")) throw new Error("Key "${name}" was not found. Cannot instantiate object.");\n'
38
+ //);
28
39
  }
29
40
  visitClassDeclaration(node) {
30
41
  if (!node.members) {
@@ -38,7 +49,6 @@ class AsJSONTransform extends ClassDecorator {
38
49
  const stmt = this.encodeStmts[this.encodeStmts.length - 1];
39
50
  this.encodeStmts[this.encodeStmts.length - 1] = stmt.slice(0, stmt.length - 1);
40
51
  serializeFunc = `
41
- @inline
42
52
  __JSON_Serialize(): string {
43
53
  return \`{${this.encodeStmts.join("")}}\`;
44
54
  }
@@ -46,31 +56,50 @@ class AsJSONTransform extends ClassDecorator {
46
56
  }
47
57
  else {
48
58
  serializeFunc = `
49
- @inline
50
59
  __JSON_Serialize(): string {
51
60
  return "{}";
52
61
  }
53
62
  `;
54
63
  }
55
- const deserializeFunc = `
56
- @inline
57
- __JSON_Deserialize<T>(values: Map<string, string>): T {
58
- ${process.argv.includes("--debugJSON") ? this.checkDecodeStmts.join("else") : ""}
59
- return {
60
- ${
61
- // @ts-ignore
62
- this.decodeStmts.join("")}
64
+ /*const deserializeFunc = `
65
+ __JSON_Deserialize<T>(values: Map<string, string>): T {
66
+ ${
67
+ process.argv.includes("--debugJSON")
68
+ ? this.checkDecodeStmts.join("else")
69
+ : ""
70
+ }
71
+ return {
72
+ ${
73
+ // @ts-ignore
74
+ this.decodeStmts.join("")
75
+ }
76
+ }
63
77
  }
64
- }
78
+ `;*/
79
+ const setKeyFunc = `
80
+ __JSON_Set_Key(key: string, value: string): void {
81
+ ${
82
+ // @ts-ignore
83
+ this.setDataStmts.join("")}
84
+ throw new Error("Cannot find key: " + key);
85
+ }
65
86
  `;
87
+ //console.log(setKeyFunc, deserializeFunc, serializeFunc)
66
88
  this.encodeStmts = [];
67
- this.decodeStmts = [];
89
+ //this.decodeStmts = [];
90
+ this.setDataStmts = [];
91
+ //this.checkDecodeStmts = [];
68
92
  const serializedProperty = SimpleParser.parseClassMember(serializedProp, node);
69
93
  node.members.push(serializedProperty);
70
94
  const serializeMethod = SimpleParser.parseClassMember(serializeFunc, node);
71
95
  node.members.push(serializeMethod);
72
- const deserializeMethod = SimpleParser.parseClassMember(deserializeFunc, node);
73
- node.members.push(deserializeMethod);
96
+ //const deserializeMethod = SimpleParser.parseClassMember(
97
+ // deserializeFunc,
98
+ // node
99
+ //);
100
+ //node.members.push(deserializeMethod);
101
+ const setDataMethod = SimpleParser.parseClassMember(setKeyFunc, node);
102
+ node.members.push(setDataMethod);
74
103
  }
75
104
  get name() {
76
105
  return "json";
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@json-as/transform",
3
- "version": "0.5.3",
3
+ "version": "0.5.4",
4
4
  "description": "JSON encoder/decoder for AssemblyScript",
5
5
  "main": "./lib/index.js",
6
6
  "author": "Jairus Tanaka",
@@ -14,8 +14,9 @@ class AsJSONTransform extends ClassDecorator {
14
14
  public currentClass!: ClassDeclaration;
15
15
  public sources: Source[] = [];
16
16
  public encodeStmts: string[] = [];
17
- public decodeStmts: string[] = [];
18
- public checkDecodeStmts: string[] = [];
17
+ //public decodeStmts: string[] = [];
18
+ public setDataStmts: string[] = [];
19
+ //public checkDecodeStmts: string[] = [];
19
20
 
20
21
  visitMethodDeclaration(): void {}
21
22
  visitFieldDeclaration(node: FieldDeclaration): void {
@@ -33,14 +34,23 @@ class AsJSONTransform extends ClassDecorator {
33
34
  );
34
35
 
35
36
  // @ts-ignore
36
- this.decodeStmts.push(
37
- `${name}: JSON.parseObjectValue<${type}>(values.get("${name}")),\n`
38
- );
37
+ //this.decodeStmts.push(
38
+ // `${name}: JSON.parseObjectValue<${type}>(values.get("${name}")),\n`
39
+ //);
39
40
 
40
41
  // @ts-ignore
41
- this.checkDecodeStmts.push(
42
- ' if (!values.has("${name}")) throw new Error("Key "${name}" was not found. Cannot instantiate object.");\n'
42
+ this.setDataStmts.push(
43
+ `if (key.length === ${name.length} && (memory.compare(changetype<usize>("${name}"), changetype<usize>(key), ${name.length}) == 0)) {
44
+ this.${name} = JSON.parseObjectValue<${type}>(value);
45
+ return;
46
+ }
47
+ `
43
48
  );
49
+
50
+ // @ts-ignore
51
+ //this.checkDecodeStmts.push(
52
+ // ' if (!values.has("${name}")) throw new Error("Key "${name}" was not found. Cannot instantiate object.");\n'
53
+ //);
44
54
  }
45
55
  visitClassDeclaration(node: ClassDeclaration): void {
46
56
  if (!node.members) {
@@ -62,21 +72,18 @@ class AsJSONTransform extends ClassDecorator {
62
72
  stmt.length - 1
63
73
  );
64
74
  serializeFunc = `
65
- @inline
66
75
  __JSON_Serialize(): string {
67
76
  return \`{${this.encodeStmts.join("")}}\`;
68
77
  }
69
78
  `;
70
79
  } else {
71
80
  serializeFunc = `
72
- @inline
73
81
  __JSON_Serialize(): string {
74
82
  return "{}";
75
83
  }
76
84
  `;
77
85
  }
78
- const deserializeFunc = `
79
- @inline
86
+ /*const deserializeFunc = `
80
87
  __JSON_Deserialize<T>(values: Map<string, string>): T {
81
88
  ${
82
89
  process.argv.includes("--debugJSON")
@@ -90,9 +97,21 @@ class AsJSONTransform extends ClassDecorator {
90
97
  }
91
98
  }
92
99
  }
93
- `;
100
+ `;*/
101
+ const setKeyFunc = `
102
+ __JSON_Set_Key(key: string, value: string): void {
103
+ ${
104
+ // @ts-ignore
105
+ this.setDataStmts.join("")
106
+ }
107
+ throw new Error("Cannot find key: " + key);
108
+ }
109
+ `
110
+ //console.log(setKeyFunc, deserializeFunc, serializeFunc)
94
111
  this.encodeStmts = [];
95
- this.decodeStmts = [];
112
+ //this.decodeStmts = [];
113
+ this.setDataStmts = [];
114
+ //this.checkDecodeStmts = [];
96
115
  const serializedProperty = SimpleParser.parseClassMember(
97
116
  serializedProp,
98
117
  node
@@ -102,11 +121,16 @@ class AsJSONTransform extends ClassDecorator {
102
121
  const serializeMethod = SimpleParser.parseClassMember(serializeFunc, node);
103
122
  node.members.push(serializeMethod);
104
123
 
105
- const deserializeMethod = SimpleParser.parseClassMember(
106
- deserializeFunc,
124
+ //const deserializeMethod = SimpleParser.parseClassMember(
125
+ // deserializeFunc,
126
+ // node
127
+ //);
128
+ //node.members.push(deserializeMethod);
129
+ const setDataMethod = SimpleParser.parseClassMember(
130
+ setKeyFunc,
107
131
  node
108
132
  );
109
- node.members.push(deserializeMethod);
133
+ node.members.push(setDataMethod);
110
134
  }
111
135
  get name(): string {
112
136
  return "json";
package/tests/index.js DELETED
@@ -1,4 +0,0 @@
1
- import assert from "assert";
2
- import { add } from "../build/debug.js";
3
- assert.strictEqual(add(1, 2), 3);
4
- console.log("ok");
package/tests/test.js DELETED
@@ -1,17 +0,0 @@
1
- const fs = require("fs");
2
- const loader = require("@assemblyscript/loader");
3
- const { WASI } = require("wasi");
4
- const ConsoleImport = require('as-console/imports')
5
- const Console = new ConsoleImport()
6
- const wasiOptions = {};
7
- const wasi = new WASI(wasiOptions);
8
- const imports = {
9
- wasi_snapshot_preview1: wasi.wasiImport,
10
- ...Console.wasmImports
11
- };
12
- const wasmModule = loader.instantiateSync(
13
- fs.readFileSync(__dirname + "/output/test.wasm"),
14
- imports
15
- );
16
- Console.wasmExports = wasmModule.exports
17
- wasi.start(wasmModule);