diff --git a/assembly/__benches__/misc.bench.ts b/assembly/__benches__/misc.bench.ts index 4520fd4..c2668d9 100644 --- a/assembly/__benches__/misc.bench.ts +++ b/assembly/__benches__/misc.bench.ts @@ -9,7 +9,7 @@ const srcStart = changetype(str); const srcEnd = srcStart + bytes(str); bs.ensureSize(2048); bench("Deserialize String (Simple)", () => { - deserializeString(str2); + deserializeStrin(str2); }); // bench("Deserialize String (SIMD)", () => { // (str2, bs.buffer); diff --git a/assembly/custom/util.ts b/assembly/custom/util.ts index b38333f..415f331 100644 --- a/assembly/custom/util.ts +++ b/assembly/custom/util.ts @@ -2,34 +2,6 @@ import { isSpace } from "util/string"; import { BACK_SLASH, QUOTE } from "./chars"; import { Sink } from "./sink"; -// @ts-ignore: Decorator -export function isMap(): bool { - let type = changetype(0); - return type instanceof Map; -} - -// @ts-ignore: Decorator -@inline export function unsafeCharCodeAt(data: string, pos: i32): i32 { - return load(changetype(data) + ((pos) << 1)); -} - -/** - * A terrible function which finds the depth of a certain array. - * Suffers no overhead besides function calling and a if/else. - * @returns depth of array - */ - -// @ts-ignore: Decorator -export function getArrayDepth(depth: i32 = 1): i32 { - if (!isArray()) { - return 0; - } else if (isArray>()) { - depth++; - return getArrayDepth>(depth); - } else { - return depth; - } -} /** Scientific Notation Integer Parsing - SNIP * This is absolutely the fastest algorithm I could think of while adding full support for Scientific Notation diff --git a/assembly/deserialize/simple/arbitrary.ts b/assembly/deserialize/simple/arbitrary.ts index c955585..c16ddd2 100644 --- a/assembly/deserialize/simple/arbitrary.ts +++ b/assembly/deserialize/simple/arbitrary.ts @@ -7,7 +7,7 @@ import { deserializeObject } from "./object"; import { deserializeString } from "./string"; // @ts-ignore -@inline export function deserializeArbitrary(data: string): JSON.Value { +@inline export function deserializeArbitrary(srcStart: usize, srcEnd: usize, dst: usize = 0): JSON.Value { const firstChar = unsafeCharCodeAt(data, 0); if (firstChar == 34) return JSON.Value.from(deserializeString(data)); diff --git a/assembly/deserialize/simple/date.ts b/assembly/deserialize/simple/date.ts index 0ae071f..c5b5902 100644 --- a/assembly/deserialize/simple/date.ts +++ b/assembly/deserialize/simple/date.ts @@ -1,30 +1,12 @@ -import { QUOTE } from "../../custom/chars"; +import { ptrToStr } from "../../util/ptrToStr"; // @ts-ignore: Decorator valid here -@inline export function deserializeDate(dateTimeString: string): Date { +@inline export function deserializeDate(srcStart: usize, srcEnd: usize): Date { // Use AssemblyScript's date parser - const d = Date.fromString(dateTimeString); + const d = Date.fromString(ptrToStr(srcStart, srcEnd)); // Return a new object instead of the one that the parser returned. // This may seem redundant, but addreses the issue when Date // is globally aliased to wasi_Date (or some other superclass). return new Date(d.getTime()); -} - -// @ts-ignore: Decorator valid here -@inline export function deserializeDate_NEW(srcStart: usize, srcEnd: usize): Date { - // Use AssemblyScript's date parser - const d = Date.fromString(str(srcStart, srcEnd)); - - // Return a new object instead of the one that the parser returned. - // This may seem redundant, but addreses the issue when Date - // is globally aliased to wasi_Date (or some other superclass). - return new Date(d.getTime()); -} - -function str(start: usize, end: usize): string { - const size = end - start; - const out = __new(size, idof()); - memory.copy(out, start, size); - return changetype(out); } \ No newline at end of file diff --git a/assembly/deserialize/simple/integer.ts b/assembly/deserialize/simple/integer.ts index aaa2bad..874a961 100644 --- a/assembly/deserialize/simple/integer.ts +++ b/assembly/deserialize/simple/integer.ts @@ -1,13 +1,6 @@ -import { snip_fast } from "../../custom/util"; -import { strToInt } from "../../util/strToInt"; +import { atoi } from "../../util/atoi"; // @ts-ignore: Decorator valid here -@inline export function deserializeInteger(data: string): T { - // @ts-ignore - return snip_fast(data); -} - -// @ts-ignore: Decorator valid here -@inline export function deserializeInteger_NEW(srcStart: usize, srcEnd: usize): T { - return strToInt(srcStart, srcEnd); +@inline export function deserializeInteger(srcStart: usize, srcEnd: usize): T { + return atoi(srcStart, srcEnd); } \ No newline at end of file diff --git a/assembly/deserialize/simple/map.ts b/assembly/deserialize/simple/map.ts index 072b165..101ca9f 100644 --- a/assembly/deserialize/simple/map.ts +++ b/assembly/deserialize/simple/map.ts @@ -2,11 +2,10 @@ import { JSON } from "../.."; import { BACK_SLASH, COMMA, CHAR_F, BRACE_LEFT, BRACKET_LEFT, CHAR_N, QUOTE, BRACE_RIGHT, BRACKET_RIGHT, CHAR_T, COLON } from "../../custom/chars"; import { isSpace } from "../../util"; -export function deserializeMap>(srcStart: usize, srcEnd: usize, dst: T | null = null): T { +export function deserializeMap>(srcStart: usize, srcEnd: usize, dst: usize): T { + const out = changetype(dst); // @ts-ignore: type - if (!isString>() && !isInteger>()) ERROR("Map key must be of type string | number!"); - dst = dst || changetype>(__new(offsetof>(), idof>())); - console.log("Data: " + str(srcStart, srcEnd)); + if (!isString>() && !isInteger>() && !isFloat>()) ERROR("Map key must also be a valid JSON key!"); const srcPtr = srcStart; let key: string | null = null; @@ -23,20 +22,20 @@ export function deserializeMap>(srcStart: usize, srcEnd: if (code == QUOTE && load(srcStart - 2) !== BACK_SLASH) { if (isKey) { key = sliceTo(lastIndex, srcStart); - console.log("Key: " + key); while (isSpace((code = load((srcStart += 2))))) { /* empty */ } if (code !== COLON) throw new Error("Expected ':' after key at position " + (srcStart - srcPtr).toString()); isKey = false; } else { - isKey = true; // i don't like this + isKey = true; lastIndex = srcStart + 2; } } // isKey = !isKey; srcStart += 2; } else { + // @ts-ignore: type if (isString>() && code == QUOTE) { lastIndex = srcStart; srcStart += 2; @@ -46,21 +45,22 @@ export function deserializeMap>(srcStart: usize, srcEnd: while (isSpace(load((srcStart += 2)))) { /* empty */ } - console.log("Value (string): " + str(lastIndex, srcStart)); - dst.set(key, JSON.__deserialize>(lastIndex, srcStart)); + // @ts-ignore: type + out.set(key, JSON.__deserialize>(lastIndex, srcStart)); key = null; break; } srcStart += 2; } + // @ts-ignore: type } else if (!isBoolean>() && isInteger>() && code - 48 <= 9 || code == 45) { lastIndex = srcStart; srcStart += 2; while (srcStart < srcEnd) { const code = load(srcStart); if (code == COMMA || isSpace(code) || code == BRACE_RIGHT) { - dst.set(key, JSON.__deserialize>(lastIndex, srcStart)); - console.log("Value (number): " + str(lastIndex, srcStart)); + // @ts-ignore: type + out.set(key, JSON.__deserialize>(lastIndex, srcStart)); while (isSpace(load((srcStart += 2)))) { /* empty */ } @@ -69,6 +69,7 @@ export function deserializeMap>(srcStart: usize, srcEnd: } srcStart += 2; } + // @ts-ignore: type } else if (isArray>() && code == BRACKET_LEFT) { lastIndex = srcStart; depth++; @@ -77,7 +78,8 @@ export function deserializeMap>(srcStart: usize, srcEnd: const code = load(srcStart); if (((code ^ BRACE_RIGHT) | (code ^ BRACKET_RIGHT)) == 32) { if (--depth == 0) { - dst.set(key, JSON.__deserialize>(lastIndex, srcStart)); + // @ts-ignore: type + out.set(key, JSON.__deserialize>(lastIndex, srcStart)); while (isSpace(load((srcStart += 2)))) { /* empty */ } @@ -87,6 +89,7 @@ export function deserializeMap>(srcStart: usize, srcEnd: } else if (code == BRACKET_LEFT) depth++; srcStart += 2; } + // @ts-ignore: type } else if (isDefined(changetype>>(0).__DESERIALIZE) && code == BRACE_LEFT) { lastIndex = srcStart; depth++; @@ -95,7 +98,8 @@ export function deserializeMap>(srcStart: usize, srcEnd: const code = load(srcStart); if (code == BRACE_RIGHT) { if (--depth == 0) { - dst.set(key, JSON.__deserialize>(lastIndex, srcStart)); + // @ts-ignore: type + out.set(key, JSON.__deserialize>(lastIndex, srcStart)); while (isSpace(load((srcStart += 2)))) { /* empty */ } @@ -105,19 +109,21 @@ export function deserializeMap>(srcStart: usize, srcEnd: } else if (code == BRACE_LEFT) depth++; srcStart += 2; } + // @ts-ignore: type } else if (isBoolean>() && code == CHAR_T) { if (load(srcStart) == 28429475166421108) { - dst.set(key, JSON.__deserialize>(srcStart, srcStart += 8)); - console.log("Value (bool): " + str(srcStart - 8, srcStart)); + // @ts-ignore: type + out.set(key, JSON.__deserialize>(srcStart, srcStart += 8)); while (isSpace(load((srcStart += 2)))) { /* empty */ } key = null; } + // @ts-ignore: type } else if (isBoolean>() && code == CHAR_F) { if (load(srcStart, 2) == 28429466576093281) { - dst.set(key, JSON.__deserialize>(srcStart, srcStart += 10)); - console.log("Value (bool): " + str(srcStart - 10, srcStart)); + // @ts-ignore: type + out.set(key, JSON.__deserialize>(srcStart, srcStart += 10)); while (isSpace(load((srcStart += 2)))) { /* empty */ } @@ -125,25 +131,19 @@ export function deserializeMap>(srcStart: usize, srcEnd: } } else if ((isNullable() || nameof() == "usize") && code == CHAR_N) { if (load(srcStart) == 30399761348886638) { - dst.set(key, JSON.__deserialize>(srcStart, srcStart += 8)); - console.log("Value (null): " + str(srcStart - 8, srcStart)); + // @ts-ignore: type + out.set(key, JSON.__deserialize>(srcStart, srcStart += 8)); while (isSpace(load((srcStart += 2)))) { /* empty */ } } } else { - throw new Error("Unexpected character " + String.fromCharCode(code) +" or type " + nameof>() + " does not match found type!") + // @ts-ignore: type + throw new Error("Unexpected character " + String.fromCharCode(code) + " or type " + nameof>() + " does not match found type!") } } } - return dst; -} - -function str(start: usize, end: usize): string { - const size = end - start; - const out = __new(size, idof()); - memory.copy(out, start, size); - return changetype(out); + return out; } // @ts-ignore: Decorator valid here diff --git a/assembly/deserialize/simple/object.ts b/assembly/deserialize/simple/object.ts index 0f79129..479de5b 100644 --- a/assembly/deserialize/simple/object.ts +++ b/assembly/deserialize/simple/object.ts @@ -1,9 +1,7 @@ import { BACK_SLASH, COMMA, CHAR_F, BRACE_LEFT, BRACKET_LEFT, CHAR_N, QUOTE, BRACE_RIGHT, BRACKET_RIGHT, CHAR_T, COLON } from "../../custom/chars"; import { isSpace } from "../../util"; -export function deserializeObject(srcStart: usize, srcEnd: usize, dst: nonnull = changetype>(__new(offsetof>(), idof>()))): T { - console.log("Data: " + str(srcStart, srcEnd)); - +export function deserializeObject(srcStart: usize, srcEnd: usize, dst: usize): T { const srcPtr = srcStart; let keyStart: usize = 0; diff --git a/assembly/deserialize/simple/string.ts b/assembly/deserialize/simple/string.ts index 12c1155..0358b97 100644 --- a/assembly/deserialize/simple/string.ts +++ b/assembly/deserialize/simple/string.ts @@ -2,7 +2,7 @@ import { BACK_SLASH } from "../../custom/chars"; import { DESERIALIZE_ESCAPE_TABLE, ESCAPE_HEX_TABLE } from "../../globals/tables"; // @ts-ignore: Decorator valid here -@inline export function deserializeString(srcStart: usize, srcEnd: usize, dst: usize = __new(srcEnd - srcStart - 4, idof())): string { +@inline export function deserializeString(srcStart: usize, srcEnd: usize, dst: usize): string { let dstPtr = dst; let lastPtr = srcStart; while (srcStart < srcEnd) { diff --git a/assembly/globals/tables.ts b/assembly/globals/tables.ts index c2d8caa..0d27328 100644 --- a/assembly/globals/tables.ts +++ b/assembly/globals/tables.ts @@ -411,3 +411,37 @@ export const ESCAPE_HEX_TABLE = 14, 15, // 48-54 ]) - 48; + +export const POW_TEN_TABLE_32 = memory.data([ + 1, + 10, + 1_000, + 10_000, + 100_000, + 1_000_000, + 10_000_000, + 100_000_000, + 1_000_000_000 +]); + +export const POW_TEN_TABLE_64 = memory.data([ + 1, + 10, + 1_000, + 10_000, + 100_000, + 1_000_000, + 10_000_000, + 100_000_000, + 1_000_000_000, + 10_000_000_000, + 100_000_000_000, + 1_000_000_000_000, + 10_000_000_000_000, + 100_000_000_000_000, + 1_000_000_000_000_000, + 10_000_000_000_000_000, + 100_000_000_000_000_000, + 1_000_000_000_000_000_000, + 10_000_000_000_000_000_000 +]); \ No newline at end of file diff --git a/assembly/index.ts b/assembly/index.ts index a9c5102..14dcdd7 100644 --- a/assembly/index.ts +++ b/assembly/index.ts @@ -1,4 +1,6 @@ /// +import { bs } from "as-bs"; + import { serializeString } from "./serialize/simple/string"; import { serializeArray } from "./serialize/simple/array"; import { serializeMap } from "./serialize/simple/map"; @@ -9,19 +11,19 @@ import { deserializeObject } from "./deserialize/simple/object"; import { deserializeMap } from "./deserialize/simple/map"; import { deserializeDate } from "./deserialize/simple/date"; import { deserializeInteger, deserializeInteger_NEW } from "./deserialize/simple/integer"; -import { deserializeString, deserializeString } from "./deserialize/simple/string"; +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 { bs } from "as-bs"; 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"; -class Nullable {} +class Nullable { } export type Raw = string; @@ -320,7 +322,7 @@ export namespace JSON { * Box for primitive types */ export class Box { - constructor(public value: T) {} + constructor(public value: T) { } /** * Creates a reference to a primitive type * This means that it can create a nullable primitive @@ -368,7 +370,7 @@ export namespace JSON { } else if (src instanceof JSON.Value) { serializeArbitrary(src); } else { - ERROR(`Could not serialize src of type ${nameof()}. Make sure to add the correct decorators to classes.`); + ERROR(`Could not serialize provided data. Make sure to add the correct decorators to classes.`); } } export function __deserialize(srcStart: usize, srcEnd: usize, dst: usize = 0): T { @@ -384,9 +386,17 @@ export namespace JSON { return deserializeString(srcStart, srcEnd, dst); } else { let type: nonnull = changetype>(0); - if (type instanceof Map) { + // @ts-ignore: declared by transform + if (isDefined(type.__DESERIALIZE)) { + return deserializeObject(srcStart, srcEnd); + } else if (type instanceof Map) { + // @ts-ignore: type + return deserializeMap(srcStart, srcEnd, dst); + } else if (type instanceof Date) { // @ts-ignore: type - return deserializeMap(srcStart, srcEnd, dst) + return deserializeDate(srcStart, srcEnd); + } else { + ERROR(`Could not deserialize data '${ptrToStr(srcStart, srcEnd).slice(0, 100)}' to type. Make sure to add the correct decorators to classes.`); } } } diff --git a/assembly/serialize/simd/string.ts b/assembly/serialize/simd/string.ts index ec77ad0..284f1c5 100644 --- a/assembly/serialize/simd/string.ts +++ b/assembly/serialize/simd/string.ts @@ -1,4 +1,4 @@ -import { OBJECT, TOTAL_OVERHEAD } from "rt/common"; +import { bs } from "as-bs"; import { BACK_SLASH } from "../../custom/chars"; import { SERIALIZE_ESCAPE_TABLE } from "../../globals/tables"; @@ -10,22 +10,22 @@ const SPLAT_0 = i16x8.splat(0); /* 0 */ /** * Serializes strings into their JSON counterparts using SIMD operations - * @param src string to serialize - * @param dst buffer to write to - * @returns number of bytes written + * @param srcStart pointer to begin serializing at + * @param srcEnd pointer to end serialization at + * @param bs.offset pointer to write to */ -export function serializeString_SIMD(src: string, dst: usize): usize { - let src_ptr = changetype(src); - let dst_ptr = changetype(dst) + 2; +// @ts-ignore: Decorator valid here +@inline export function serializeString_SIMD(srcStart: usize, srcEnd: usize, staticSize: bool): void { + const srcSize = srcEnd - srcStart; + if (!staticSize) bs.ensureSize(srcSize + 4); + const srcEnd16 = srcEnd - 15; - const src_end = src_ptr + changetype(changetype(src) - TOTAL_OVERHEAD).rtSize; - const src_end_15 = src_end - 15; + store(changetype(bs.offset), 34); /* " */ + bs.offset += 2; - store(changetype(dst), 34); /* " */ - - while (src_ptr < src_end_15) { - const block = v128.load(src_ptr); - v128.store(dst_ptr, block); + while (srcStart < srcEnd16) { + const block = v128.load(srcStart); + v128.store(bs.offset, block); const backslash_indices = i16x8.eq(block, SPLAT_92); const quote_indices = i16x8.eq(block, SPLAT_34); @@ -36,8 +36,8 @@ export function serializeString_SIMD(src: string, dst: usize): usize { while (mask != 0) { const lane_index = ctz(mask) << 1; - const dst_offset = dst_ptr + lane_index; - const src_offset = src_ptr + lane_index; + const dst_offset = bs.offset + lane_index; + const src_offset = srcStart + lane_index; const code = load(src_offset) << 2; const escaped = load(SERIALIZE_ESCAPE_TABLE + code); @@ -47,23 +47,23 @@ export function serializeString_SIMD(src: string, dst: usize): usize { store(dst_offset, 13511005048209500); store(dst_offset, escaped, 8); v128.store(dst_offset, v128.load(src_offset, 2), 12); - dst_ptr += 10; + bs.offset += 10; } else { store(dst_offset, escaped); v128.store(dst_offset, v128.load(src_offset, 2), 4); - dst_ptr += 2; + bs.offset += 2; } } - src_ptr += 16; - dst_ptr += 16; + srcStart += 16; + bs.offset += 16; } - let rem = src_end - src_ptr; + let rem = srcEnd - srcStart; if (rem & 8) { - const block = v128.load64_zero(src_ptr); - v128.store64_lane(dst_ptr, block, 0); + const block = v128.load64_zero(srcStart); + v128.store64_lane(bs.offset, block, 0); const backslash_indices = i16x8.eq(block, SPLAT_92); const quote_indices = i16x8.eq(block, SPLAT_34); @@ -74,8 +74,8 @@ export function serializeString_SIMD(src: string, dst: usize): usize { let mask = i16x8.bitmask(sieve); while (mask != 0) { let lane_index = ctz(mask) << 1; - const dst_offset = dst_ptr + lane_index; - const src_offset = src_ptr + lane_index; + const dst_offset = bs.offset + lane_index; + const src_offset = srcStart + lane_index; const code = load(src_offset) << 2; const escaped = load(SERIALIZE_ESCAPE_TABLE + code); mask &= mask - 1; @@ -84,26 +84,26 @@ export function serializeString_SIMD(src: string, dst: usize): usize { store(dst_offset, 13511005048209500); store(dst_offset, escaped, 8); while (lane_index < 6) { - store(dst_ptr + lane_index, load(src_ptr + lane_index, 2), 12); + store(bs.offset + lane_index, load(srcStart + lane_index, 2), 12); lane_index += 2; } - dst_ptr += 10; + bs.offset += 10; } else { store(dst_offset, escaped); while (lane_index < 6) { - store(dst_ptr + lane_index, load(src_ptr + lane_index, 2), 4); + store(bs.offset + lane_index, load(srcStart + lane_index, 2), 4); lane_index += 2; } - dst_ptr += 2; + bs.offset += 2; } } - dst_ptr += 8; - src_ptr += 8; + bs.offset += 8; + srcStart += 8; } if (rem & 4) { - const block = load(src_ptr); + const block = load(srcStart); const codeA = block & 0xffff; const codeB = (block >> 16) & 0xffff; @@ -111,55 +111,55 @@ export function serializeString_SIMD(src: string, dst: usize): usize { const escaped = load(SERIALIZE_ESCAPE_TABLE + (codeA << 2)); if ((escaped & 0xffff) != BACK_SLASH) { - store(dst_ptr, 13511005048209500); - store(dst_ptr, escaped, 8); - dst_ptr += 12; + store(bs.offset, 13511005048209500); + store(bs.offset, escaped, 8); + bs.offset += 12; } else { - store(dst_ptr, escaped); - dst_ptr += 4; + store(bs.offset, escaped); + bs.offset += 4; } } else { - store(dst_ptr, codeA); - dst_ptr += 2; + store(bs.offset, codeA); + bs.offset += 2; } if (codeB == 92 || codeB == 34 || codeB < 32) { const escaped = load(SERIALIZE_ESCAPE_TABLE + (codeB << 2)); if ((escaped & 0xffff) != BACK_SLASH) { - store(dst_ptr, 13511005048209500); - store(dst_ptr, escaped, 8); - dst_ptr += 12; + store(bs.offset, 13511005048209500); + store(bs.offset, escaped, 8); + bs.offset += 12; } else { - store(dst_ptr, escaped); - dst_ptr += 4; + store(bs.offset, escaped); + bs.offset += 4; } } else { - store(dst_ptr, codeB); - dst_ptr += 2; + store(bs.offset, codeB); + bs.offset += 2; } - src_ptr += 4; + srcStart += 4; } if (rem & 2) { - const code = load(src_ptr); + const code = load(srcStart); if (code == 92 || code == 34 || code < 32) { const escaped = load(SERIALIZE_ESCAPE_TABLE + (code << 2)); if ((escaped & 0xffff) != BACK_SLASH) { - store(dst_ptr, 13511005048209500); - store(dst_ptr, escaped, 8); - dst_ptr += 12; + store(bs.offset, 13511005048209500); + store(bs.offset, escaped, 8); + bs.offset += 12; } else { - store(dst_ptr, escaped); - dst_ptr += 4; + store(bs.offset, escaped); + bs.offset += 4; } } else { - store(dst_ptr, code); - dst_ptr += 2; + store(bs.offset, code); + bs.offset += 2; } } - store(dst_ptr, 34); /* " */ - return dst_ptr - changetype(dst) + 2; + bs.offset += 2; + store(bs.offset, 34); /* " */ } diff --git a/assembly/serialize/simple/string.ts b/assembly/serialize/simple/string.ts index 6a3477e..f7ac883 100644 --- a/assembly/serialize/simple/string.ts +++ b/assembly/serialize/simple/string.ts @@ -10,7 +10,7 @@ import { SERIALIZE_ESCAPE_TABLE } from "../../globals/tables"; * @returns void */ // @ts-ignore: Decorator -@inline export function serializeString(src: string, staticSize: bool = false): void { +@inline export function serializeString(src: string, staticSize: bool): void { const srcSize = bytes(src); if (!staticSize) bs.ensureSize(srcSize + 4); diff --git a/assembly/test.ts b/assembly/test.ts index 25e9196..f76df5c 100644 --- a/assembly/test.ts +++ b/assembly/test.ts @@ -1,18 +1,6 @@ -import { JSON } from "."; -import { deserializeMap } from "./deserialize/simple/map"; -import { deserializeObject } from "./deserialize/simple/object"; -import { bytes } from "./util"; - -@json -class Vec3 { - a: i16 = 1 - ab: i16 = 2; - abc: i16 = 3; - abcd: i16 = 4; - abcde: i16 = 5; +function cups(n: i32): void { + let i = 0; + while (++i <= n) console.log(i.toString() + " cups of coffee on the wall"); } -const serialized = JSON.stringify(new Vec3()); -console.log("Serialized: " + serialized); -const deserialized = deserializeObject(changetype(serialized), changetype(serialized) + bytes(serialized)); -console.log("Deserialized: " + JSON.stringify(deserialized)); \ No newline at end of file +cups(99); \ No newline at end of file diff --git a/assembly/tsconfig.json b/assembly/tsconfig.json index 2ed0bb1..f3cd60c 100644 --- a/assembly/tsconfig.json +++ b/assembly/tsconfig.json @@ -1,6 +1,6 @@ { "extends": "assemblyscript/std/assembly.json", - "include": ["./**/*.ts"], + "include": ["./**/*.ts", "util/atoi"], "compilerOptions": { "experimentalDecorators": true, "emitDecoratorMetadata": true diff --git a/assembly/util/strToInt.ts b/assembly/util/atoi.ts similarity index 86% rename from assembly/util/strToInt.ts rename to assembly/util/atoi.ts index 8883690..2b5aa94 100644 --- a/assembly/util/strToInt.ts +++ b/assembly/util/atoi.ts @@ -1,10 +1,10 @@ /** - * Strtol optimized for JSON integers + * ATOI optimized for non-exponential integers * @param str * @returns */ // @ts-ignore: Decorator valid here -@inline export function strToInt(srcStart: usize, srcEnd: usize): T { +@inline export function atoi(srcStart: usize, srcEnd: usize): T { // @ts-ignore: type let val: T = 0; if (isSigned()) { diff --git a/assembly/util/getArrayDepth.ts b/assembly/util/getArrayDepth.ts new file mode 100644 index 0000000..3d7429d --- /dev/null +++ b/assembly/util/getArrayDepth.ts @@ -0,0 +1,17 @@ +/** + * A terrible function which ascertains the depth of a certain array + * Depending on the optimization level, this can be essentially nop + * @returns depth of array + */ + +// @ts-ignore: Decorator +export function getArrayDepth(depth: i32 = 1): i32 { + if (!isArray()) { + return 0; + } else if (isArray>()) { + depth++; + return getArrayDepth>(depth); + } else { + return depth; + } +} \ No newline at end of file diff --git a/assembly/util/index.ts b/assembly/util/index.ts index 5897d04..2d1f209 100644 --- a/assembly/util/index.ts +++ b/assembly/util/index.ts @@ -1,5 +1,5 @@ export * from "./isSpace"; -export * from "./strToInt"; +export * from "./atoi"; export * from "./concat"; export * from "./bytes"; export * from "./nextPowerOf2"; diff --git a/assembly/util/ptrToStr.ts b/assembly/util/ptrToStr.ts new file mode 100644 index 0000000..7b755ab --- /dev/null +++ b/assembly/util/ptrToStr.ts @@ -0,0 +1,7 @@ +// @ts-ignore: decorator +@inline export function ptrToStr(start: usize, end: usize): string { + const size = end - start; + const out = __new(size, idof()); + memory.copy(out, start, size); + return changetype(out); +} \ No newline at end of file diff --git a/assembly/util/snp.ts b/assembly/util/snp.ts new file mode 100644 index 0000000..3274336 --- /dev/null +++ b/assembly/util/snp.ts @@ -0,0 +1,71 @@ +// e -> 101 +// E -> 69 +// - -> 45 +// . -> 46 + +import { POW_TEN_TABLE_32, POW_TEN_TABLE_64 } from "../globals/tables"; +import { atoi } from "./atoi"; + +// @ts-ignore: Decorator valid here +@inline function snp(srcStart: usize, srcEnd: usize): T { + // @ts-ignore: type + let val: T = 0; + let char = load(srcStart) - 48; + if (isFloat()) { + while (srcStart < srcEnd) { + + } + } else if (isInteger()) { + if (isSigned() && char == 65533) { + srcStart += 2; + while (srcStart < srcEnd) { + char = load(srcStart) - 48; + if (char < 10) { + // @ts-ignore: type + val = (val * 10 + char) as T; + } else if (char == 101 || char == 69) { + srcStart += 2; + char = load(srcStart); + if (char == 45) { + // @ts-ignore: type + return -(val / pow10(atoi(srcStart + 2, srcEnd))); + } else { + // @ts-ignore: type + return -(val * pow10(atoi(srcStart, srcEnd))); + } + } + srcStart += 2; + } + return -val as T; + } else { + while (srcStart < srcEnd) { + char = load(srcStart) - 48; // this operation is repeated twice + if (char < 10) { + // @ts-ignore: type + val = (val * 10 + char) as T; + } else if (char == 101 || char == 69) { + srcStart += 2; + char = load(srcStart); + if (char == 45) { + // @ts-ignore: type + return val / pow10(atoi(srcStart + 2, srcEnd)); + } else { + // @ts-ignore: type + return val * pow10(atoi(srcStart, srcEnd)); + } + } + srcStart += 2; + } + return val as T; + } + } +} + +// @ts-ignore: Decorator valid here +@inline function pow10(x: u16): T { + if (sizeof() == 8) { + return load(POW_TEN_TABLE_64 + x); + } else { + return load(POW_TEN_TABLE_32 + x); + } +} \ No newline at end of file