json-as 0.5.65 → 0.6.0
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 +1 -0
- package/assembly/__tests__/as-json.spec.ts +1 -1
- package/assembly/src/json.ts +176 -2
- package/assembly/test.ts +14 -14
- package/package.json +6 -7
- package/transform/package.json +1 -1
- package/transform/src/index.ts +9 -8
package/README.md
CHANGED
|
@@ -189,7 +189,7 @@ class HttpResp {
|
|
|
189
189
|
|
|
190
190
|
describe("Deser externals", () => {
|
|
191
191
|
it("should deserialize valid JSON strings", () => {
|
|
192
|
-
canDeser<Map4>('
|
|
192
|
+
canDeser<Map4>('{"a":\r"\\\\",\n\r"b":"}","c":"][","d"\t:\t"\\""}', { a: '\\', b: '}', c: '][', d: '"' })
|
|
193
193
|
canDeser<Vec3>('{"x":0.4,"y":1.4,"z":0.0}', { x: 0.4, y: 1.4, z: 0 })
|
|
194
194
|
canDeser<HttpResp>('{"statusCode":200,"headers":[["Conn\\\\ection","close"],["Content-Length","375"],["ETag","W/\\"177-/Ihew5Z+fiI8NLbTM2Wyphl/PFY\\""]],\n"body":"{\\n \\\"args\\\": {},\\n \\\"headers\\\": {\\n \\\"content-length\\\": \\\"0\\\",\\n \\\"accept\\\": \\\"*/*\\\" \\n}}"}',
|
|
195
195
|
{
|
package/assembly/src/json.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { StringSink } from "as-string-sink/assembly";
|
|
2
2
|
import { isSpace } from "util/string";
|
|
3
|
+
import { E_INVALIDDATE } from "util/error";
|
|
3
4
|
import {
|
|
4
5
|
backSlashCode,
|
|
5
6
|
commaCode,
|
|
@@ -101,6 +102,87 @@ export namespace JSON {
|
|
|
101
102
|
);
|
|
102
103
|
}
|
|
103
104
|
}
|
|
105
|
+
/**
|
|
106
|
+
* Stringifies valid JSON data.
|
|
107
|
+
* ```js
|
|
108
|
+
* JSON.stringify<T>(data)
|
|
109
|
+
* ```
|
|
110
|
+
* @param data T
|
|
111
|
+
* @returns string
|
|
112
|
+
*/
|
|
113
|
+
// @ts-ignore: Decorator
|
|
114
|
+
@inline export function stringifyTo<T>(data: T, out: string): void {
|
|
115
|
+
// String
|
|
116
|
+
if (isString<T>() && data != null) {
|
|
117
|
+
out = serializeString(data as string);
|
|
118
|
+
return;
|
|
119
|
+
} else if (isBoolean<T>()) {
|
|
120
|
+
out = data ? "true" : "false";
|
|
121
|
+
return;
|
|
122
|
+
} else if (isNullable<T>() && data == null) {
|
|
123
|
+
out = "null";
|
|
124
|
+
return;
|
|
125
|
+
// @ts-ignore
|
|
126
|
+
} else if ((isInteger<T>() || isFloat<T>()) && isFinite(data)) {
|
|
127
|
+
// @ts-ignore
|
|
128
|
+
out = data.toString();
|
|
129
|
+
return;
|
|
130
|
+
// @ts-ignore: Hidden function
|
|
131
|
+
} else if (isDefined(data.__JSON_Serialize)) {
|
|
132
|
+
// @ts-ignore: Hidden function
|
|
133
|
+
out = data.__JSON_Serialize();
|
|
134
|
+
return;
|
|
135
|
+
} else if (data instanceof Date) {
|
|
136
|
+
out = data.toISOString();
|
|
137
|
+
return;
|
|
138
|
+
} else if (isArrayLike<T>()) {
|
|
139
|
+
// @ts-ignore
|
|
140
|
+
if (data.length == 0) {
|
|
141
|
+
out = emptyArrayWord;
|
|
142
|
+
return;
|
|
143
|
+
// @ts-ignore
|
|
144
|
+
} else if (isString<valueof<T>>()) {
|
|
145
|
+
out = "[";
|
|
146
|
+
// @ts-ignore
|
|
147
|
+
for (let i = 0; i < data.length - 1; i++) {
|
|
148
|
+
// @ts-ignore
|
|
149
|
+
out += serializeString(unchecked(data[i]));
|
|
150
|
+
out += commaWord;
|
|
151
|
+
}
|
|
152
|
+
// @ts-ignore
|
|
153
|
+
out += serializeString(unchecked(data[data.length - 1]));
|
|
154
|
+
out += rightBracketWord;
|
|
155
|
+
return;
|
|
156
|
+
// @ts-ignore
|
|
157
|
+
} else if (isBoolean<valueof<T>>()) {
|
|
158
|
+
// @ts-ignore
|
|
159
|
+
out = leftBracketWord + data.join(commaWord) + rightBracketWord;
|
|
160
|
+
return;
|
|
161
|
+
// @ts-ignore
|
|
162
|
+
} else if (isFloat<valueof<T>>() || isInteger<valueof<T>>()) {
|
|
163
|
+
// @ts-ignore
|
|
164
|
+
out = leftBracketWord + data.join(commaWord) + rightBracketWord;
|
|
165
|
+
return;
|
|
166
|
+
} else {
|
|
167
|
+
let result = new StringSink(leftBracketWord);
|
|
168
|
+
// @ts-ignore
|
|
169
|
+
for (let i = 0; i < data.length - 1; i++) {
|
|
170
|
+
// @ts-ignore
|
|
171
|
+
result.write(JSON.stringify(unchecked(data[i])));
|
|
172
|
+
result.write(commaWord);
|
|
173
|
+
}
|
|
174
|
+
// @ts-ignore
|
|
175
|
+
result.write(JSON.stringify(unchecked(data[data.length - 1])));
|
|
176
|
+
result.write(rightBracketWord);
|
|
177
|
+
out = result.toString();
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
} else {
|
|
181
|
+
throw new Error(
|
|
182
|
+
`Could not serialize data of type ${nameof<T>()}. Make sure to add the correct decorators to classes.`
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
104
186
|
/**
|
|
105
187
|
* Parses valid JSON strings into their original format.
|
|
106
188
|
* ```js
|
|
@@ -133,7 +215,7 @@ export namespace JSON {
|
|
|
133
215
|
return parseObject<T>(data.trimStart());
|
|
134
216
|
} else if (idof<nonnull<T>>() == idof<Date>()) {
|
|
135
217
|
// @ts-ignore
|
|
136
|
-
return
|
|
218
|
+
return parseDate(data);
|
|
137
219
|
} else {
|
|
138
220
|
// @ts-ignore
|
|
139
221
|
throw new Error(
|
|
@@ -210,7 +292,7 @@ export namespace JSON {
|
|
|
210
292
|
return parseObject<T>(data.trimStart());
|
|
211
293
|
} else if (idof<nonnull<T>>() == idof<Date>()) {
|
|
212
294
|
// @ts-ignore
|
|
213
|
-
return
|
|
295
|
+
return parseDate(data);
|
|
214
296
|
} else {
|
|
215
297
|
// @ts-ignore
|
|
216
298
|
throw new Error(
|
|
@@ -630,3 +712,95 @@ export namespace JSON {
|
|
|
630
712
|
}
|
|
631
713
|
return result;
|
|
632
714
|
}
|
|
715
|
+
|
|
716
|
+
// @ts-ignore: decorator
|
|
717
|
+
@inline const
|
|
718
|
+
MILLIS_PER_DAY = 1000 * 60 * 60 * 24,
|
|
719
|
+
MILLIS_PER_HOUR = 1000 * 60 * 60,
|
|
720
|
+
MILLIS_PER_MINUTE = 1000 * 60,
|
|
721
|
+
MILLIS_PER_SECOND = 1000,
|
|
722
|
+
|
|
723
|
+
YEARS_PER_EPOCH = 400,
|
|
724
|
+
DAYS_PER_EPOCH = 146097,
|
|
725
|
+
EPOCH_OFFSET = 719468, // Jan 1, 1970
|
|
726
|
+
MILLIS_LIMIT = 8640000000000000;
|
|
727
|
+
|
|
728
|
+
function parseDate(dateTimeString: string): Date {
|
|
729
|
+
if (!dateTimeString.length) throw new RangeError(E_INVALIDDATE);
|
|
730
|
+
var
|
|
731
|
+
hour: i32 = 0,
|
|
732
|
+
min: i32 = 0,
|
|
733
|
+
sec: i32 = 0,
|
|
734
|
+
ms: i32 = 0;
|
|
735
|
+
|
|
736
|
+
let dateString = dateTimeString;
|
|
737
|
+
let posT = dateTimeString.indexOf("T");
|
|
738
|
+
if (~posT) {
|
|
739
|
+
// includes a time component
|
|
740
|
+
let timeString: string;
|
|
741
|
+
dateString = dateTimeString.substring(0, posT);
|
|
742
|
+
timeString = dateTimeString.substring(posT + 1);
|
|
743
|
+
// parse the HH-MM-SS component
|
|
744
|
+
let timeParts = timeString.split(":");
|
|
745
|
+
let len = timeParts.length;
|
|
746
|
+
if (len <= 1) throw new RangeError(E_INVALIDDATE);
|
|
747
|
+
|
|
748
|
+
hour = i32.parse(timeParts[0]);
|
|
749
|
+
min = i32.parse(timeParts[1]);
|
|
750
|
+
if (len >= 3) {
|
|
751
|
+
let secAndMs = timeParts[2];
|
|
752
|
+
let posDot = secAndMs.indexOf(".");
|
|
753
|
+
if (~posDot) {
|
|
754
|
+
// includes milliseconds
|
|
755
|
+
sec = i32.parse(secAndMs.substring(0, posDot));
|
|
756
|
+
ms = i32.parse(secAndMs.substring(posDot + 1));
|
|
757
|
+
} else {
|
|
758
|
+
sec = i32.parse(secAndMs);
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
// parse the YYYY-MM-DD component
|
|
763
|
+
let parts = dateString.split("-");
|
|
764
|
+
let year = i32.parse(parts[0]);
|
|
765
|
+
let month = 1, day = 1;
|
|
766
|
+
let len = parts.length;
|
|
767
|
+
if (len >= 2) {
|
|
768
|
+
month = i32.parse(parts[1]);
|
|
769
|
+
if (len >= 3) {
|
|
770
|
+
day = i32.parse(parts[2]);
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
return new Date(epochMillis(year, month, day, hour, min, sec, ms));
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
function epochMillis(
|
|
777
|
+
year: i32,
|
|
778
|
+
month: i32,
|
|
779
|
+
day: i32,
|
|
780
|
+
hour: i32,
|
|
781
|
+
minute: i32,
|
|
782
|
+
second: i32,
|
|
783
|
+
milliseconds: i32
|
|
784
|
+
): i64 {
|
|
785
|
+
return (
|
|
786
|
+
daysSinceEpoch(year, month, day) * MILLIS_PER_DAY +
|
|
787
|
+
hour * MILLIS_PER_HOUR +
|
|
788
|
+
minute * MILLIS_PER_MINUTE +
|
|
789
|
+
second * MILLIS_PER_SECOND +
|
|
790
|
+
milliseconds
|
|
791
|
+
);
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
function daysSinceEpoch(y: i32, m: i32, d: i32): i64 {
|
|
795
|
+
y -= i32(m <= 2);
|
|
796
|
+
let era = <u32>floorDiv(y, YEARS_PER_EPOCH);
|
|
797
|
+
let yoe = <u32>y - era * YEARS_PER_EPOCH; // [0, 399]
|
|
798
|
+
let doy = <u32>(153 * (m + (m > 2 ? -3 : 9)) + 2) / 5 + d - 1; // [0, 365]
|
|
799
|
+
let doe = yoe * 365 + yoe / 4 - yoe / 100 + doy; // [0, 146096]
|
|
800
|
+
return <i64><i32>(era * 146097 + doe - EPOCH_OFFSET);
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
// @ts-ignore: decorator
|
|
804
|
+
@inline function floorDiv<T extends number>(a: T, b: T): T {
|
|
805
|
+
return (a - (a < 0 ? b - 1 : 0)) / b as T;
|
|
806
|
+
}
|
package/assembly/test.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { bench, blackbox } from "as-bench/assembly/bench";
|
|
2
1
|
import { JSON } from "./src/json";
|
|
2
|
+
|
|
3
3
|
// @ts-ignore
|
|
4
4
|
@json
|
|
5
5
|
class Vec3 {
|
|
6
|
-
x: f64;
|
|
7
|
-
y: f64;
|
|
8
|
-
z: f64;
|
|
6
|
+
x: f64 = 3.4;
|
|
7
|
+
y: f64 = 1.2;
|
|
8
|
+
z: f64 = 8.3;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
// @ts-ignore
|
|
@@ -13,22 +13,18 @@ class Vec3 {
|
|
|
13
13
|
class Player {
|
|
14
14
|
firstName: string;
|
|
15
15
|
lastName: string;
|
|
16
|
-
lastActive:
|
|
16
|
+
lastActive: Date;
|
|
17
17
|
age: i32;
|
|
18
18
|
pos: Vec3 | null;
|
|
19
19
|
isVerified: boolean;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
const vec
|
|
23
|
-
x: 3.4,
|
|
24
|
-
y: 1.2,
|
|
25
|
-
z: 8.3,
|
|
26
|
-
}
|
|
22
|
+
const vec = new Vec3();
|
|
27
23
|
|
|
28
24
|
const player: Player = {
|
|
29
25
|
firstName: "Emmet",
|
|
30
26
|
lastName: "West",
|
|
31
|
-
lastActive:
|
|
27
|
+
lastActive: new Date(0),
|
|
32
28
|
age: 23,
|
|
33
29
|
pos: {
|
|
34
30
|
x: 3.4,
|
|
@@ -38,13 +34,17 @@ const player: Player = {
|
|
|
38
34
|
isVerified: true,
|
|
39
35
|
}
|
|
40
36
|
|
|
41
|
-
|
|
37
|
+
let out = "";
|
|
38
|
+
|
|
39
|
+
JSON.stringifyTo(vec, out);
|
|
40
|
+
|
|
41
|
+
console.log("Original: " + out);
|
|
42
42
|
//console.log("Revised: " + vec.__JSON_Deserialize('{"x":3,"y":1,"z":8}').__JSON_Serialize());
|
|
43
|
-
console.log("Implemented: " + JSON.stringify(JSON.parse<Vec3>('{
|
|
43
|
+
console.log("Implemented: " + JSON.stringify(JSON.parse<Vec3>('{}')));
|
|
44
44
|
|
|
45
45
|
console.log("Original: " + JSON.stringify(player));
|
|
46
46
|
//console.log("Revised: " + vec.__JSON_Deserialize('{"x":3,"y":1,"z":8}').__JSON_Serialize());
|
|
47
|
-
console.log("Implemented: " + JSON.stringify(JSON.parse<Player>('{"firstName":"Emmet","lastName":"West","lastActive":
|
|
47
|
+
console.log("Implemented: " + JSON.stringify(JSON.parse<Player>('{"firstName":"Emmet","lastName":"West","lastActive":2023-11-16T04:06:35.108285303Z,"age":23,"pos":{"x":3.4,"y":1.2,"z":8.3},"isVerified":true}')));
|
|
48
48
|
/*
|
|
49
49
|
// 9,325,755
|
|
50
50
|
bench("Stringify Object (Vec3)", () => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "json-as",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "JSON encoder/decoder for AssemblyScript",
|
|
5
5
|
"types": "assembly/index.ts",
|
|
6
6
|
"author": "Jairus Tanaka",
|
|
@@ -16,8 +16,7 @@
|
|
|
16
16
|
"scripts": {
|
|
17
17
|
"test:aspect": "asp",
|
|
18
18
|
"bench:astral": "astral --optimizeLevel 3 --shrinkLevel 0 --converge --noAssert --uncheckedBehavior never --runtime stub",
|
|
19
|
-
"build:test": "asc assembly/test.ts -o build/test.wasm --transform ./transform
|
|
20
|
-
"build:test:debug": "asc assembly/test.ts -o build/test.wasm --transform ./transform --config ./node_modules/@assemblyscript/wasi-shim/asconfig.json --optimizeLevel 0 --shrinkLevel 0 --noAssert --uncheckedBehavior always --runtime stub",
|
|
19
|
+
"build:test": "asc assembly/test.ts -o build/test.wasm --transform ./transform --config ./node_modules/@assemblyscript/wasi-shim/asconfig.json --optimizeLevel 0 --shrinkLevel 0 --noAssert --uncheckedBehavior always --runtime stub",
|
|
21
20
|
"build:bench": "asc bench/benchmark.ts -o bench/benchmark.wasm --transform ./transform --config ./node_modules/@assemblyscript/wasi-shim/asconfig.json --optimizeLevel 3 --shrinkLevel 0 --converge --noAssert --uncheckedBehavior always --runtime stub",
|
|
22
21
|
"bench:wasmtime": "wasmtime ./bench/benchmark.wasm",
|
|
23
22
|
"bench:wavm": "wavm run ./bench/benchmark.wasm",
|
|
@@ -33,14 +32,14 @@
|
|
|
33
32
|
"@as-tral/cli": "^2.0.1",
|
|
34
33
|
"@assemblyscript/wasi-shim": "^0.1.0",
|
|
35
34
|
"as-bench": "^0.0.0-alpha",
|
|
36
|
-
"assemblyscript": "^0.27.
|
|
35
|
+
"assemblyscript": "^0.27.18",
|
|
37
36
|
"assemblyscript-prettier": "^3.0.1",
|
|
38
37
|
"benchmark": "^2.1.4",
|
|
39
38
|
"kati": "^0.6.2",
|
|
40
39
|
"microtime": "^3.1.1",
|
|
41
|
-
"prettier": "^3.0
|
|
42
|
-
"tinybench": "^2.5.
|
|
43
|
-
"typescript": "^5.
|
|
40
|
+
"prettier": "^3.1.0",
|
|
41
|
+
"tinybench": "^2.5.1",
|
|
42
|
+
"typescript": "^5.2.2",
|
|
44
43
|
"visitor-as": "^0.11.4"
|
|
45
44
|
},
|
|
46
45
|
"dependencies": {
|
package/transform/package.json
CHANGED
package/transform/src/index.ts
CHANGED
|
@@ -18,6 +18,7 @@ class SchemaData {
|
|
|
18
18
|
public encodeStmts: string[] = [];
|
|
19
19
|
public setDataStmts: string[] = [];
|
|
20
20
|
}
|
|
21
|
+
|
|
21
22
|
class AsJSONTransform extends BaseVisitor {
|
|
22
23
|
public schemasList: SchemaData[] = [];
|
|
23
24
|
public currentClass!: SchemaData;
|
|
@@ -137,18 +138,18 @@ class AsJSONTransform extends BaseVisitor {
|
|
|
137
138
|
`
|
|
138
139
|
);
|
|
139
140
|
} else {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
141
|
+
this.currentClass.encodeStmts.push(
|
|
142
|
+
`"${name}":\${JSON.stringify<${type}>(this.${name})},`
|
|
143
|
+
);
|
|
144
|
+
// @ts-ignore
|
|
145
|
+
this.currentClass.setDataStmts.push(
|
|
146
|
+
`if (key.equals("${name}")) {
|
|
146
147
|
this.${name} = __parseObjectValue<${type}>(val_start ? data.slice(val_start, val_end) : data);
|
|
147
148
|
return;
|
|
148
149
|
}
|
|
149
150
|
`
|
|
150
|
-
|
|
151
|
-
|
|
151
|
+
);
|
|
152
|
+
}
|
|
152
153
|
}
|
|
153
154
|
}
|
|
154
155
|
|