🚀 Big News: Socket Acquires Coana to Bring Reachability Analysis to Every Appsec Team.Learn more →

json-as

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

json-as - npm Package Compare versions

Comparing version

to
0.4.5

@@ -0,0 +0,0 @@ {

{
"targets": {
"debug": {
"outFile": "build/debug.wasm",
"textFile": "build/debug.wat",
"sourceMap": true,
"debug": true
},
"release": {
"outFile": "build/release.wasm",
"textFile": "build/release.wat",
"sourceMap": true,
"optimizeLevel": 3,
"shrinkLevel": 0,
"converge": false,
"noAssert": false
},
"test": {
"outFile": "build/test.wasm",
"sourceMap": true,
"sourceMap": false,
"optimizeLevel": 0,

@@ -22,0 +7,0 @@ "shrinkLevel": 0,

@@ -1,2 +0,3 @@

import { JSON } from "..";
import { JSON, parseBooleanArray, parseObject, parseStringArray } from "..";
@json

@@ -17,2 +18,6 @@ class Vec2 {

bench("Parse String", () => {
blackbox(JSON.parse<string>(blackbox('"Hello"')));
});
bench("Stringify Boolean", () => {

@@ -22,2 +27,6 @@ blackbox(JSON.stringify(blackbox(true)));

bench("Parse Boolean", () => {
blackbox(JSON.parse<boolean>(blackbox("true")));
});
bench("Stringify Integer", () => {

@@ -27,2 +36,6 @@ blackbox(JSON.stringify(blackbox(314)));

bench("Parse Integer", () => {
blackbox(JSON.parse<i32>(blackbox("314")));
});
bench("Stringify Float", () => {

@@ -32,2 +45,6 @@ blackbox(JSON.stringify(blackbox(3.14)));

bench("Parse Float", () => {
blackbox(JSON.parse<f32>(blackbox("3.14")));
});
bench("Stringify Object (Vec2)", () => {

@@ -37,2 +54,6 @@ blackbox(JSON.stringify(vec));

bench("Parse Object (Vec2)", () => {
blackbox(parseObject<Vec2>(blackbox('{"x":0.0,"y":0.0}')));
});
bench("Stringify Array", () => {

@@ -42,34 +63,18 @@ blackbox(JSON.stringify(blackbox([1, 2, 3, 4, 5])));

bench("Parse String", () => {
blackbox(JSON.parse<string>(blackbox('"Hello"')));
bench("Parse Array", () => {
blackbox(JSON.parse<i32[]>(blackbox("[1,2,3,4]")));
});
bench("Parse Boolean", () => {
blackbox(JSON.parse<boolean>(blackbox("true")));
});
bench("Parse Integer", () => {
blackbox(JSON.parse<i32>(blackbox("314")));
});
bench("Parse Float", () => {
blackbox(JSON.parse<f32>(blackbox("3.14")));
});
bench("Parse Object (Vec2)", () => {
blackbox(JSON.parse<Vec2>(blackbox('{"x":0.0,"y":0.0}')));
});
bench("Parse Boolean Array", () => {
bench("Stringify Nested Array", () => {
blackbox(
JSON.parse<boolean[]>(blackbox("[true,false,true,false,true]"))
JSON.stringify<string[][]>(
blackbox([
["a", "b", "c"],
["d", "e", "f"],
])
)
);
});
bench("Parse Integer Array", () => {
blackbox(JSON.parse<u32[]>(blackbox("[1,2,3,4,5]")));
bench("Parse Nested Array", () => {
blackbox(JSON.parse<string[][]>(blackbox('[["a","b","c"],["d","e","f"]]')));
});
bench("Parse Float Array", () => {
blackbox(JSON.parse<f32[]>(blackbox("[1.0,2.0,3.0,4.0,5.0]")));
});
export const commaCode = ",".charCodeAt(0);
export const quoteCode = "\"".charCodeAt(0);
export const quoteCode = '"'.charCodeAt(0);
export const backSlashCode = "\\".charCodeAt(0);
export const forwardSlashCode = "/".charCodeAt(0);
export const leftBraceCode = "{".charCodeAt(0);

@@ -5,0 +6,0 @@ export const rightBraceCode = "}".charCodeAt(0);

import { StringSink } from "as-string-sink/assembly";
import { Variant } from "as-variant/assembly";
import { isSpace } from "assemblyscript/std/assembly/util/string";
import { stringify } from "as-console/assembly";
import {

@@ -7,2 +9,5 @@ backSlashCode,

commaCode,
eCode,
fCode,
forwardSlashCode,
leftBraceCode,

@@ -12,5 +17,6 @@ leftBracketCode,

rightBraceCode,
rightBracketCode
rightBracketCode,
tCode,
} from "./chars";
import { removeWhitespace } from "./util";
import { removeWhitespace, unsafeCharCodeAt } from "./util";

@@ -20,4 +26,24 @@ /**

*/
export namespace JSON {
export type _Variant = Variant;
export class JSON {
private static parseObjectValue<T>(data: string): T {
let type!: T;
if (isString<T>()) {
// @ts-ignore
return data.replaceAll('\\"', '"');
} else if (isBoolean<T>()) {
// @ts-ignore
return parseBoolean<T>(data);
} else if (isFloat<T>() || isInteger<T>()) {
return parseNumber<T>(data);
} else if (isArrayLike<T>()) {
// @ts-ignore
return parseArray<T>(data);
// @ts-ignore
} else if (isDefined(type.__JSON_Deserialize)) {
return parseObject<T>(data);
} else {
// @ts-ignore
return null;
}
}
/**

@@ -31,3 +57,3 @@ * Stringifies valid JSON data.

*/
export function stringify<T = Nullable | null>(data: T): string {
static stringify<T = Nullable | null>(data: T): string {
// String

@@ -84,4 +110,3 @@ if (isString<T>()) {

*/
export function parse<T = Variant>(data: string): T {
data = removeWhitespace(data);
static parse<T = Variant>(data: string): T {
let type!: T;

@@ -97,49 +122,7 @@ if (isString<T>()) {

} else if (isArrayLike<T>()) {
return parseArray<T>(data);
// @ts-ignore
return parseArray<T>(data.trimStart());
// @ts-ignore
} else if (isDefined(type.__JSON_Deserialize)) {
const len: u32 = data.length - 1
let schema!: T
const result = new Map<string, string>()
let lastPos: u32 = 1
let key: string = ''
let instr: boolean = false
let char: u32 = 0
let depth: u32 = 0
let fdepth: u32 = 0
for (let i: u32 = 1; i < len; i++) {
char = data.charCodeAt(i);
if (instr === false && char === quoteCode) instr = true;
else if (instr === true && char === quoteCode && data.charCodeAt(i - 1) !== "/".charCodeAt(0)) instr = false;
if (instr === false) {
if (char === leftBraceCode || char === leftBracketCode) depth++
if (char === rightBraceCode || char === rightBracketCode) fdepth++
}
if (depth !== 0 && depth === fdepth) {
//console.log(`Found Struct: ${data.slice(lastPos + 1, i + 1)}`)
result.set(key, data.slice(lastPos + 1, i + 1))
// Reset the depth
depth = 0
fdepth = 0
// Set new lastPos
lastPos = i + 1
}
if (!instr && depth === 0) {
if (char === colonCode) {
key = data.slice(lastPos + 1, i - 1)
//console.log(`Found Key: ${data.slice(lastPos + 1, i - 1)}`)
lastPos = i
} else if (char === commaCode) {
//console.log(`Found Comma: ${data.slice(lastPos + 1, i)}`)
if ((i - lastPos) > 0) result.set(key, data.slice(lastPos + 1, i))
lastPos = i + 1
}
}
}
if ((len - lastPos) > 1 && (len - lastPos) !== 0) {
result.set(key, data.slice(lastPos + 1, len))
}
// @ts-ignore
return schema.__JSON_Deserialize(result)
return parseObject<T>(data.trimStart());
} else {

@@ -152,6 +135,5 @@ // @ts-ignore

// @ts-ignore
@inline
function parseString(data: string): string {
function parseString(data: string): string {
return data.slice(1, data.length - 1).replaceAll('\\"', '"');

@@ -162,3 +144,3 @@ }

@inline
function parseBoolean<T extends boolean>(data: string): T {
function parseBoolean<T extends boolean>(data: string): T {
if (data.length > 3 && data.startsWith("true")) return <T>true;

@@ -168,5 +150,6 @@ else if (data.length > 4 && data.startsWith("false")) return <T>false;

}
// @ts-ignore
@inline
function parseNumber<T>(data: string): T {
function parseNumber<T>(data: string): T {
let type: T;

@@ -195,25 +178,196 @@ // @ts-ignore

export function parseObject<T>(data: string): T {
let schema!: T;
const result = new Map<string, string>();
let key: usize = 0;
let depth = 1;
let char = 0;
for (
let outerLoopIndex = 1;
outerLoopIndex < data.length - 1;
outerLoopIndex++
) {
char = unsafeCharCodeAt(data, outerLoopIndex);
if (char === leftBracketCode) {
for (
let arrayValueIndex = outerLoopIndex;
arrayValueIndex < data.length - 1;
arrayValueIndex++
) {
char = unsafeCharCodeAt(data, arrayValueIndex);
if (char === leftBracketCode) {
depth = depth << 1;
} else if (char === rightBracketCode) {
depth = depth >> 1;
if (depth === 1) {
++arrayValueIndex;
result.set(
changetype<string>(key),
data.slice(outerLoopIndex, arrayValueIndex)
);
outerLoopIndex = arrayValueIndex;
key = 0;
break;
}
}
}
} else if (char === leftBraceCode) {
for (
let objectValueIndex = outerLoopIndex;
objectValueIndex < data.length - 1;
objectValueIndex++
) {
char = unsafeCharCodeAt(data, objectValueIndex);
if (char === leftBraceCode) {
depth = depth << 1;
} else if (char === rightBraceCode) {
depth = depth >> 1;
if (depth === 1) {
++objectValueIndex;
result.set(
changetype<string>(key),
data.slice(outerLoopIndex, objectValueIndex)
);
outerLoopIndex = objectValueIndex;
key = 0;
break;
}
}
}
} else if (char === quoteCode) {
for (
let stringValueIndex = ++outerLoopIndex;
stringValueIndex < data.length - 1;
stringValueIndex++
) {
char = unsafeCharCodeAt(data, stringValueIndex);
if (
char === quoteCode &&
unsafeCharCodeAt(data, stringValueIndex - 1) !== backSlashCode
) {
if (key === 0) {
key = changetype<usize>(
data.slice(outerLoopIndex, stringValueIndex)
);
} else {
result.set(
changetype<string>(key),
data.slice(outerLoopIndex, stringValueIndex)
);
key = 0;
}
outerLoopIndex = ++stringValueIndex;
break;
}
}
} else if (
char === tCode &&
unsafeCharCodeAt(data, ++outerLoopIndex) === "r".charCodeAt(0) &&
unsafeCharCodeAt(data, ++outerLoopIndex) === "u".charCodeAt(0) &&
unsafeCharCodeAt(data, ++outerLoopIndex) === eCode
) {
result.set(changetype<string>(key), "true");
key = 0;
} else if (
char === fCode &&
unsafeCharCodeAt(data, ++outerLoopIndex) === "a".charCodeAt(0) &&
unsafeCharCodeAt(data, ++outerLoopIndex) === "l".charCodeAt(0) &&
unsafeCharCodeAt(data, ++outerLoopIndex) === "s".charCodeAt(0) &&
unsafeCharCodeAt(data, ++outerLoopIndex) === eCode
) {
result.set(changetype<string>(key), "false");
key = 0;
} else if (char >= 48 && char <= 57) {
let numberValueIndex = ++outerLoopIndex;
for (; numberValueIndex < data.length - 1; numberValueIndex++) {
char = unsafeCharCodeAt(data, numberValueIndex);
if (
char === commaCode ||
isSpace(char) ||
numberValueIndex == data.length - 2
) {
result.set(
changetype<string>(key),
data.slice(outerLoopIndex - 1, numberValueIndex)
);
outerLoopIndex = numberValueIndex;
key = 0;
break;
}
}
}
}
// @ts-ignore
return schema.__JSON_Deserialize(result);
}
// @ts-ignore
@inline
export function parseNumberArray<T>(data: string): T {
// @ts-ignore
export function parseArray<T extends unknown[]>(data: string): T {
// TODO: Replace with opt
let type!: valueof<T>;
if (type instanceof String) {
return <T>parseStringArray(data);
} else if (isFloat<valueof<T>>() || isInteger<valueof<T>>()) {
// @ts-ignore
return parseNumberArray<T>(data);
} else if (isBoolean<valueof<T>>()) {
// @ts-ignore
return parseBooleanArray<T>(data);
} else if (isArrayLike<valueof<T>>()) {
// @ts-ignore
return parseArrayArray<T>(data);
// @ts-ignore
} else if (isDefined(type.__JSON_Deserialize)) {
// @ts-ignore
return parseObjectArray<T>(data);
}
}
// @ts-ignore
@inline
export function parseStringArray(data: string): string[] {
const result: string[] = [];
let lastPos = 0;
let instr = false;
for (let i = 1; i < data.length - 1; i++) {
if (unsafeCharCodeAt(data, i) === quoteCode) {
if (instr === false) {
instr = true;
lastPos = i;
} else if (unsafeCharCodeAt(data, i - 1) !== backSlashCode) {
instr = false;
result.push(data.slice(lastPos + 1, i).replaceAll('\\"', '"'));
}
}
}
return result;
}
// @ts-ignore
@inline
export function parseBooleanArray<T extends boolean[]>(data: string): T {
const result = instantiate<T>();
if (data.length == 0) return result;
let lastPos: u32 = 1;
let i: u32 = 1;
let char: u32 = 0;
for (; i < u32(data.length - 1); i++) {
char = data.charCodeAt(i);
if (char == commaCode) {
// console.log(data.slice(lastPos, i))
// @ts-ignore
result.push(parseNumber<valueof<T>>(data.slice(lastPos, i).trim()));
lastPos = ++i;
let lastPos = 1;
let char = 0;
for (let i = 1; i < data.length - 1; i++) {
char = unsafeCharCodeAt(data, i);
/*// if char == "t" && i+3 == "e"
if (char === tCode && data.charCodeAt(i + 3) === eCode) {
//i += 3;
result.push(parseBoolean<valueof<T>>(data.slice(lastPos, i+2)));
//i++;
} else if (char === fCode && data.charCodeAt(i + 4) === eCode) {
//i += 4;
result.push(parseBoolean<valueof<T>>(data.slice(lastPos, i+3)));
//i++;
}*/
if (char === tCode || char === fCode) {
lastPos = i;
} else if (char === eCode) {
i++;
result.push(parseBoolean<valueof<T>>(data.slice(lastPos, i)));
}
}
//console.log(data.slice(lastPos, data.length - 1))
// @ts-ignore
result.push(
// @ts-ignore
parseNumber<valueof<T>>(data.slice(lastPos, data.length - 1).trimStart())
);
return result;

@@ -224,21 +378,23 @@ }

@inline
export function parseBooleanArray<T>(data: string): T {
export function parseNumberArray<T extends number[]>(data: string): T {
const result = instantiate<T>();
if (data.length == 0) return result;
let lastPos: u32 = 1;
let i: u32 = 1;
let char: u32 = 0;
for (; i < u32(data.length - 1); i++) {
char = data.charCodeAt(i);
if (char == commaCode) {
// @ts-ignore
result.push(parseBoolean<valueof<T>>(data.slice(lastPos, i).trimStart()));
lastPos = ++i;
let lastPos = 0;
let char = 0;
let i = 1;
for (; i < data.length - 1; i++) {
char = unsafeCharCodeAt(data, i);
if (lastPos === 0 && char >= 48 && char <= 57) {
lastPos = i;
} else if ((isSpace(char) || char == commaCode) && lastPos > 0) {
result.push(parseNumber<valueof<T>>(data.slice(lastPos, i)));
lastPos = 0;
}
}
// @ts-ignore
result.push(
// @ts-ignore
parseBoolean<valueof<T>>(data.slice(lastPos, data.length - 1).trimStart())
);
for (; i > lastPos; i--) {
char = unsafeCharCodeAt(data, i);
if (char !== rightBracketCode) {
result.push(parseNumber<valueof<T>>(data.slice(lastPos, i + 1)));
break;
}
}
return result;

@@ -249,75 +405,60 @@ }

@inline
export function parseArray<T>(data: string): T {
export function parseArrayArray<T extends unknown[][]>(data: string): T {
const result = instantiate<T>();
data = data.trim();
let len: u32 = data.length - 1;
let lastPos: u32 = 1;
let i: u32 = 1;
let char: u32 = 0;
// Is struct such as Object, or Array
let isStruct: boolean = false;
let isStr: boolean = false;
//let offset: u32 = 0;
// Depth for finding matching brackets
let inDepth: u32 = 0;
let outDepth: u32 = 0;
for (; i < len; i++) {
char = data.charCodeAt(i);
if (char == quoteCode && data.charCodeAt(i - 1) != backSlashCode)
isStr = !isStr;
if (char == leftBraceCode || char == leftBracketCode) {
inDepth++;
isStruct = true;
} else if (char == rightBraceCode || char == rightBracketCode) {
outDepth++;
isStruct = true;
let char = 0;
let lastPos = 0;
let depth = 1;
let i = 1;
// Find start of bracket
//for (; unsafeCharCodeAt(data, i) !== leftBracketCode; i++) {}
//i++;
for (; i < data.length - 1; i++) {
char = unsafeCharCodeAt(data, i);
if (char === leftBracketCode) {
if (depth === 1) {
lastPos = i;
}
// Shifting is 6% faster than incrementing
depth = depth << 1;
} else if (char === rightBracketCode) {
depth = depth >> 1;
if (depth === 1) {
i++;
result.push(JSON.parse<valueof<T>>(data.slice(lastPos, i)));
}
}
if (!isStr) {
if (!isStruct) {
// This removes whitespace before and after an element
/*if (offset != 0 && isSpace(char)) {
lastPos++;
} else {
if (isSpace(char)) offset++;
}*/
// This checks to see if we are dealing with structures such as Objects and Arrays
if (char == commaCode) {
// @ts-ignore
result.push(JSON.parse<valueof<T>>(data.slice(lastPos, i).trim()));
//offset = 0;
lastPos = i + 1;
}
} else {
if (inDepth == outDepth) {
i++;
//console.log(`Struct-${data.slice(lastPos, i).trim()}-`)
lastPos = i + 1;
inDepth = 0;
outDepth = 0;
isStruct = false;
}
}
return result;
}
// @ts-ignore
@inline
export function parseObjectArray<T extends unknown[][]>(data: string): T {
const result = instantiate<T>();
let char = 0;
let lastPos = 1;
let depth = 1;
let i = 1;
// Find start of bracket
//for (; unsafeCharCodeAt(data, i) !== leftBracketCode; i++) { }
//i++;
for (; i < data.length - 1; i++) {
char = unsafeCharCodeAt(data, i);
if (char === leftBraceCode) {
if (depth === 1) {
lastPos = i;
}
// Shifting is 6% faster than incrementing
depth = depth << 1;
} else if (char === rightBraceCode) {
depth = depth >> 1;
if (depth === 1) {
i++;
result.push(JSON.parse<valueof<T>>(data.slice(lastPos, i)));
}
}
}
/*char = data.charCodeAt(lastPos)
// Remove preceeding whitespace
while (isSpace(char)) {
lastPos++;
char = data.charCodeAt(lastPos);
}
char = data.charCodeAt(--len);
while (isSpace(char)) {
len--;
char = data.charCodeAt(len);
}*/
// @ts-ignore
// Handle empty arrays
data = data.slice(lastPos, len).trim();
// @ts-ignore
if (data.length != 0) result.push(JSON.parse<valueof<T>>(data));
//if (data.length != 0) console.log(`Trailing-${data.slice(lastPos, len).trim()}-`)
return result;
}
class Nullable { }
class Nullable {}
import "wasi";
import { JSON } from ".";
import {
JSON,
parseArrayArray,
parseNumberArray,
parseObject,
parseObjectArray,
} from ".";
import { removeWhitespace } from "./util";

@@ -8,4 +14,4 @@

class Vec2 {
x: f32
y: f32
x: f32;
y: f32;
}

@@ -16,7 +22,8 @@

class Player {
firstName: string
lastName: string
lastActive: i32[]
age: i32
pos: Vec2
firstName: string;
lastName: string;
lastActive: i32[];
age: i32;
pos: Vec2;
isVerified: boolean;
}

@@ -31,48 +38,51 @@

x: -3.4,
y: 1.2
}
}
y: 1.2,
},
isVerified: true,
};
const stringified = JSON.stringify<Player>(data);
// {
// "firstName": "Emmet",
// "lastName": "West",
// "lastActive": [8, 27, 2022],
// "age": 23,
// "pos": {
// "x": -3.4000000953674318,
// "y": 1.2000000476837159
// }
// }
console.log(`Stringified: ${stringified}`);
console.log(`Whitespace: ${removeWhitespace(`{
"firstName": "Emmet",
"lastName": "West",
"lastActive": [8, 27, 2022],
"age": 23,
"pos": {
"x": -3.4000000953674318,
"y": 1.2000000476837159
}
}`)}`)
const parsed = JSON.parse<Player>(`{
"firstName": "Emmet",
"lastName": "West",
"lastActive": [8, 27, 2022],
"age": 23,
"pos": {
"x": -3.4000000953674318,
"y": 1.2000000476837159
}
}`);
// Player {
// firstName: "Emmet",
// lastName: "West",
// lastActive: [8, 27, 2022],
// age: 23,
// pos: {
// x: -3.4000000953674318,
// y: 1.2000000476837159
// }
// }
console.log(`Parsed: ${JSON.stringify(parsed)}`);
const serialized = JSON.stringify<Player>(data);
console.log("Serialized: " + serialized);
const deserialized = JSON.parse<Player>(serialized);
console.log("Deserialized: " + JSON.stringify(deserialized));
/*
const parsed = JSON.parse<Player>(stringified);
console.log("Vec2 Parse: " + JSON.stringify<Player>(parsed));
console.log(
`Parsed String Array: ${JSON.stringify(
JSON.parse<string[]>(`\n[ "hello" , "world" ] `)
)}`
);
console.log(
`Parsed Boolean Array: ${JSON.stringify(
JSON.parse<boolean[]>(`\n[ false , true ] `)
)}`
);
console.log(
`Parsed Number Array: ${JSON.stringify(
JSON.parse<i32[]>(`[ 1 , 2\n ,3\n\t ]`)
)}`
);
console.log(
JSON.stringify<Vec2>(
load<Vec2>(changetype<usize>(data), offsetof<Player>("pos"))
)
);
console.log(
JSON.stringify<string[][]>(
parseArrayArray<string[][]>('[["a","b","c"],["d","e","f"]]')
)
);
console.log(
JSON.stringify<Player[][]>(
parseObjectArray<Player[][]>(
'[{"firstName":"Emmet","lastName":"West","lastActive":[8,7],"age":23,"pos":{"x":-3.4000000953674318,"y":1.2000000476837159}}]'
)
)
);
*/
import { StringSink } from "as-string-sink/assembly";
import { isSpace } from "assemblyscript/std/assembly/util/string";
import { backSlashCode, quoteCode } from "./chars";
// @ts-ignore
@inline
export function unsafeCharCodeAt(data: string, pos: i32): i32 {
return load<u16>(changetype<usize>(data) + ((<usize>pos) << 1));
}
export function removeWhitespace(data: string): string {
const result = new StringSink()
let instr = false;
for (let i = 0; i < data.length; i++) {
const char = data.charCodeAt(i);
if (instr === false && char === quoteCode) instr = true
else if (instr === true && char === quoteCode && data.charCodeAt(i - 1) !== backSlashCode) instr = false;
const result = new StringSink();
let instr = false;
for (let i = 0; i < data.length; i++) {
const char = data.charCodeAt(i);
if (instr === false && char === quoteCode) instr = true;
else if (
instr === true &&
char === quoteCode &&
data.charCodeAt(i - 1) !== backSlashCode
)
instr = false;
if (instr === false) {
if (!isSpace(char)) result.write(data.charAt(i))
} else {
result.write(data.charAt(i))
}
if (instr === false) {
if (!isSpace(char)) result.write(data.charAt(i));
} else {
result.write(data.charAt(i));
}
return result.toString()
}
}
return result.toString();
}
{
"name": "json-as",
"version": "0.4.4",
"version": "0.4.5",
"description": "JSON encoder/decoder for AssemblyScript",

@@ -17,3 +17,4 @@ "types": "assembly/index.ts",

"test:lunatic": "lunatic ./build/test.wasm",
"test:wasm3": "wasm3 ./build/test.wasm"
"test:wasm3": "wasm3 ./build/test.wasm",
"prettier": "as-prettier -w ."
},

@@ -41,3 +42,3 @@ "devDependencies": {

"deserialize",
"dynamic",
"dynamic",
"serde"

@@ -44,0 +45,0 @@ ],

@@ -56,2 +56,3 @@ # AS-JSON

pos: Vec2
isVerified: boolean
}

@@ -67,3 +68,4 @@

y: 1.2
}
},
isVerified: true
}

@@ -75,3 +77,3 @@

// "lastName": "West",
// "lastActive": [8, 27, 2022],
// "lastActive": [8, 27, 2022],
// "age": 23,

@@ -81,3 +83,4 @@ // "pos": {

// "y": 1.2000000476837159
// }
// },
// "isVerified": true
// }

@@ -95,3 +98,4 @@ console.log(`Stringified: ${stringified}`);

// y: 1.2000000476837159
// }
// },
// isVerified: true
// }

@@ -110,3 +114,3 @@ console.log(`Parsed: ${JSON.stringify(parsed)}`);

- Does this support whitespace?
Yes, as-json supports whitespace although the current implementation is deathly slow
Yes, as-json supports whitespace!
- How fast is it?

@@ -113,0 +117,0 @@ Really fast. For example, here are some benchmarks for ser/de a Vec2 with as-json

@@ -1,2 +0,2 @@

import { ClassDecorator, registerDecorator } from "visitor-as/dist/decorator.js";
import { ClassDecorator, registerDecorator, } from "visitor-as/dist/decorator.js";
import { getName } from "visitor-as/dist/utils.js";

@@ -54,3 +54,4 @@ import { SimpleParser } from "visitor-as/dist/index.js";

return {
${ // @ts-ignore
${
// @ts-ignore
this.decodeStmts.join("")}

@@ -57,0 +58,0 @@ }

{
"name": "@json-as/transform",
"version": "0.4.4",
"version": "0.4.5",
"description": "JSON encoder/decoder for AssemblyScript",

@@ -11,3 +11,2 @@ "main": "./lib/index.js",

"license": "MIT",
"scripts": {},
"devDependencies": {},

@@ -14,0 +13,0 @@ "dependencies": {

import {
ClassDeclaration,
FieldDeclaration,
MethodDeclaration,
Source
ClassDeclaration,
FieldDeclaration,
MethodDeclaration,
Source,
} from "assemblyscript/dist/assemblyscript";
import { ClassDecorator, registerDecorator } from "visitor-as/dist/decorator.js";
import {
ClassDecorator,
registerDecorator,
} from "visitor-as/dist/decorator.js";
import { getName } from "visitor-as/dist/utils.js";

@@ -12,45 +15,48 @@ import { SimpleParser } from "visitor-as/dist/index.js";

class AsJSONTransform extends ClassDecorator {
public currentClass!: ClassDeclaration;
public sources: Source[] = [];
public encodeStmts: string[] = [];
public decodeStmts: string[] = [];
public currentClass!: ClassDeclaration;
public sources: Source[] = [];
public encodeStmts: string[] = [];
public decodeStmts: string[] = [];
visitMethodDeclaration(node: MethodDeclaration): void {}
visitFieldDeclaration(node: FieldDeclaration): void {
const name = getName(node);
if (!node.type) {
throw new Error(`Field ${name} is missing a type declaration`);
}
visitMethodDeclaration(node: MethodDeclaration): void {}
visitFieldDeclaration(node: FieldDeclaration): void {
const name = getName(node);
if (!node.type) {
throw new Error(`Field ${name} is missing a type declaration`);
}
const type = getName(node.type);
const type = getName(node.type);
// @ts-ignore
this.encodeStmts.push(
`"${name}":\${JSON.stringify<${type}>(this.${name})},`
);
// @ts-ignore
this.encodeStmts.push(
`"${name}":\${JSON.stringify<${type}>(this.${name})},`
);
// @ts-ignore
this.decodeStmts.push(
`${name}: JSON.parse<${type}>(values.get("${name}")),\n`
);
// @ts-ignore
this.decodeStmts.push(
`${name}: JSON.parse<${type}>(values.get("${name}")),\n`
);
}
visitClassDeclaration(node: ClassDeclaration): void {
if (!node.members) {
return;
}
visitClassDeclaration(node: ClassDeclaration): void {
if (!node.members) {
return;
}
this.currentClass = node;
this.currentClass = node;
const name = getName(node);
const name = getName(node);
this.visit(node.members);
this.visit(node.members);
const serializedProp = `__JSON_Serialized: string = "";`
const serializedProp = `__JSON_Serialized: string = "";`;
let serializeFunc = ``
let serializeFunc = ``;
if (this.encodeStmts.length > 0) {
const stmt = this.encodeStmts[this.encodeStmts.length - 1]!
this.encodeStmts[this.encodeStmts.length - 1] = stmt!.slice(0, stmt.length - 1)
serializeFunc = `
if (this.encodeStmts.length > 0) {
const stmt = this.encodeStmts[this.encodeStmts.length - 1]!;
this.encodeStmts[this.encodeStmts.length - 1] = stmt!.slice(
0,
stmt.length - 1
);
serializeFunc = `
@inline

@@ -60,5 +66,5 @@ __JSON_Serialize(): string {

}
`
} else {
serializeFunc = `
`;
} else {
serializeFunc = `
@inline

@@ -68,31 +74,39 @@ __JSON_Serialize(): string {

}
`
}
`;
}
const deserializeFunc = `
const deserializeFunc = `
@inline
__JSON_Deserialize(values: Map<string, string>): ${name} {
return {
${// @ts-ignore
this.decodeStmts.join("")}
${
// @ts-ignore
this.decodeStmts.join("")
}
}
}
`;
this.encodeStmts = [];
this.decodeStmts = [];
//console.log(serializeFunc, deserializeFunc)
const serializedProperty = SimpleParser.parseClassMember(serializedProp, node);
node.members.push(serializedProperty);
this.encodeStmts = [];
this.decodeStmts = [];
//console.log(serializeFunc, deserializeFunc)
const serializedProperty = SimpleParser.parseClassMember(
serializedProp,
node
);
node.members.push(serializedProperty);
const serializeMethod = SimpleParser.parseClassMember(serializeFunc, node);
node.members.push(serializeMethod);
const serializeMethod = SimpleParser.parseClassMember(serializeFunc, node);
node.members.push(serializeMethod);
const deserializeMethod = SimpleParser.parseClassMember(deserializeFunc, node);
node.members.push(deserializeMethod);
}
get name(): string {
return "json";
}
const deserializeMethod = SimpleParser.parseClassMember(
deserializeFunc,
node
);
node.members.push(deserializeMethod);
}
get name(): string {
return "json";
}
}
export default registerDecorator(new AsJSONTransform());
export default registerDecorator(new AsJSONTransform());