///
import { bs } from "../modules/as-bs";
import { serializeString } from "./serialize/simple/string";
import { serializeArray } from "./serialize/simple/array";
import { serializeMap } from "./serialize/simple/map";
import { deserializeBoolean } from "./deserialize/simple/bool";
import { deserializeArray } from "./deserialize/simple/array";
import { deserializeFloat } from "./deserialize/simple/float";
import { deserializeObject } from "./deserialize/simple/object";
import { deserializeMap } from "./deserialize/simple/map";
import { deserializeDate } from "./deserialize/simple/date";
import { deserializeInteger } from "./deserialize/simple/integer";
import { deserializeString } from "./deserialize/simple/string";
import { serializeArbitrary } from "./serialize/simple/arbitrary";
import { Sink } from "./custom/sink";
import { NULL_WORD, QUOTE } from "./custom/chars";
import { dtoa_buffered, itoa_buffered } from "util/number";
import { serializeBool } from "./serialize/simple/bool";
import { serializeInteger } from "./serialize/simple/integer";
import { serializeFloat } from "./serialize/simple/float";
import { serializeObject } from "./serialize/simple/object";
import { ptrToStr } from "./util/ptrToStr";
import { bytes } from "./util";
export type Raw = string;
/**
* Offset of the 'storage' property in the JSON.Value class.
*/
// @ts-ignore: Decorator valid here
@inline const STORAGE = offsetof("storage");
/**
* JSON Encoder/Decoder for AssemblyScript
*/
export namespace JSON {
/**
* Serializes valid JSON data
* ```js
* JSON.stringify(data)
* ```
* @param data T
* @returns string
*/
export function stringify(data: T, out: string | null = null): string {
if (isBoolean()) {
if (out) {
if (data == true) {
out = changetype(__renew(changetype(out), 8));
store(changetype(out), 28429475166421108);
} else {
out = changetype(__renew(changetype(out), 10));
store(changetype(out), 32370086184550502);
store(changetype(out), 101, 8);
}
return out;
}
return data ? "true" : "false";
} else if (isInteger() && nameof() == "usize" && data == 0) {
if (out) {
out = changetype(__renew(changetype(out), 8));
store(changetype(out), 30399761348886638);
return out;
}
return NULL_WORD;
} else if (isInteger(data)) {
if (out) {
out = changetype(__renew(changetype(out), sizeof() << 3));
// @ts-ignore
const bytes = itoa_buffered(changetype(out), data) << 1;
return (out = changetype(__renew(changetype(out), bytes)));
}
return data.toString();
} else if (isFloat(data)) {
if (out) {
out = changetype(__renew(changetype(out), 64));
// @ts-ignore
const bytes = dtoa_buffered(changetype(out), data) << 1;
return (out = changetype(__renew(changetype(out), bytes)));
}
return data.toString();
// @ts-ignore: Function is generated by transform
} else if (isNullable() && changetype(data) == 0) {
if (out) {
out = changetype(__renew(changetype(out), 8));
store(changetype(out), 30399761348886638);
return out;
}
return NULL_WORD;
// @ts-ignore
} else if (isString>()) {
if (out) {
out = changetype(__renew(changetype(out), bytes(data) + 4));
// const oldSize = bs.byteLength;
const oldBuf = bs.buffer;
const newSize = bytes(data) + 4;
const newBuf = __new(newSize, idof());
bs.setBuffer(newBuf);
serializeString(changetype(data));
bs.setBuffer(oldBuf);
return changetype(newBuf);
}
serializeString(changetype(data));
return bs.out();
// @ts-ignore: Supplied by transform
} else if (isDefined(data.__SERIALIZE) && isDefined(data.__ALLOCATE)) {
// @ts-ignore
data.__ALLOCATE();
// @ts-ignore
data.__SERIALIZE(changetype(data));
return bs.out();
// @ts-ignore: Supplied by transform
} else if (data instanceof Date) {
out = out ? changetype(__renew(changetype(out), 52)) : changetype(__new(52, idof()));
store(changetype(out), QUOTE);
memory.copy(changetype(out) + 2, changetype(data.toISOString()), 48);
store(changetype(out), 50);
return out;
} else if (data instanceof Array) {
// @ts-ignore
serializeArray(changetype>(data));
return bs.out();
} else if (data instanceof Map) {
// @ts-ignore
serializeMap(changetype>(data));
return bs.out();
} else if (data instanceof JSON.Value) {
serializeArbitrary(data);
return bs.out();
} else if (data instanceof JSON.Box) {
return JSON.stringify(data.value);
} else {
ERROR(`Could not serialize data of type ${nameof()}. Make sure to add the correct decorators to classes.`);
}
}
/**
* Parses valid JSON strings into their original format
* ```js
* JSON.parse(data)
* ```
* @param data string
* @returns T
*/
export function parse(data: string): T {
const dataSize = bytes(data);
const dataPtr = changetype(data);
if (isBoolean()) {
return deserializeBoolean(dataPtr, dataPtr + dataSize) as T;
} else if (isInteger()) {
return deserializeInteger(dataPtr, dataPtr + dataSize);
} else if (isFloat()) {
return deserializeFloat(dataPtr, dataPtr + dataSize);
} else if (isNullable() && data.length == 4 && data == "null") {
// @ts-ignore
return null;
} else if (isString()) {
// @ts-ignore
return deserializeString(dataPtr, dataPtr + dataSize);
} else if (isArray()) {
// @ts-ignore
return deserializeArray>(dataPtr, dataPtr + dataSize, changetype(instantiate()));
}
let type: nonnull = changetype>(0);
// @ts-ignore: Defined by transform
if (isDefined(type.__DESERIALIZE) && isDefined(type.__INITIALIZE)) {
const out = __new(offsetof>(), idof>());
// @ts-ignore
changetype>(out).__INITIALIZE();
// @ts-ignore
return deserializeObject>(dataPtr, dataPtr + dataSize, out);
} else if (type instanceof Map) {
// @ts-ignore
return deserializeMap>(dataPtr, dataPtr + dataSize);
} else if (type instanceof Date) {
// @ts-ignore
return deserializeDate(dataPtr, dataPtr + dataSize);
} else if (type instanceof JSON.Box) {
// @ts-ignore
return new JSON.Box(JSON.parse>(data));
} else {
ERROR(`Could not deserialize data ${data} to type ${nameof()}. Make sure to add the correct decorators to classes.`);
}
}
/**
* Enum representing the different types supported by JSON.
*/
export enum Types {
Raw = 0,
U8 = 1,
U16 = 2,
U32 = 3,
U64 = 4,
F32 = 5,
F64 = 6,
Bool = 7,
String = 8,
Object = 9,
Array = 10,
Struct = 11,
}
export type Raw = string;
export class Value {
static METHODS: Map = new Map();
public type: i32;
// @ts-ignore
private storage: u64;
private constructor() {
unreachable();
}
/**
* Creates an JSON.Value instance from a given value.
* @param value - The value to be encapsulated.
* @returns An instance of JSON.Value.
*/
@inline static from(value: T): JSON.Value {
if (value instanceof JSON.Value) {
return value;
}
const out = changetype(__new(offsetof(), idof()));
out.set(value);
return out;
}
/**
* Sets the value of the JSON.Value instance.
* @param value - The value to be set.
*/
@inline set(value: T): void {
if (isBoolean()) {
this.type = JSON.Types.Bool;
store(changetype(this), value, STORAGE);
} else if (value instanceof u8 || value instanceof i8) {
this.type = JSON.Types.U8;
store(changetype(this), value, STORAGE);
} else if (value instanceof u16 || value instanceof i16) {
this.type = JSON.Types.U16;
store(changetype(this), value, STORAGE);
} else if (value instanceof u32 || value instanceof i32) {
this.type = JSON.Types.U32;
store(changetype(this), value, STORAGE);
} else if (value instanceof u64 || value instanceof i64) {
this.type = JSON.Types.U64;
store(changetype(this), value, STORAGE);
} else if (value instanceof f32) {
this.type = JSON.Types.F64;
store(changetype(this), value, STORAGE);
} else if (value instanceof f64) {
this.type = JSON.Types.F64;
store(changetype(this), value, STORAGE);
} else if (isString()) {
this.type = JSON.Types.String;
store(changetype(this), value, STORAGE);
} else if (value instanceof Map) {
if (idof() !== idof