From 8765a71766c19b67de20f7a9acdb0eab7cf817c0 Mon Sep 17 00:00:00 2001 From: kajacx Date: Sun, 16 Jun 2024 18:29:10 +0200 Subject: [PATCH 1/9] Prepare entries --- assembly/sized_reader.ts | 213 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 213 insertions(+) create mode 100644 assembly/sized_reader.ts diff --git a/assembly/sized_reader.ts b/assembly/sized_reader.ts new file mode 100644 index 0000000..010ab93 --- /dev/null +++ b/assembly/sized_reader.ts @@ -0,0 +1,213 @@ +import { DataReader } from "./datareader"; +import { Format } from "./format"; +import { E_INVALIDLENGTH } from "util/error"; + +export class SizedReader { + private reader: DataReader; + + constructor(reader: DataReader) { + this.reader = reader; + } + + nextEntry(): Entry { + const marker = this.reader.getUint8(); + // Fix int: 0b1xxxxxx + if (marker < 0b1000000) { + return new FixInt(marker); + // Fix map: 0b1000xxxx + } else if (marker < 0b10010000) { + return new FixMap(marker & 0b00001111); + // Fix array: 0b1001xxxx + } else if (marker < 0b10100000) { + return new FixArr(marker & 0b00001111); + return new FixStr(marker & 0b00001111); + } else if (marker == 0b11000000) { + return new Null(); + // } else if (marker == 0b110) + } + } +} + +export abstract class Entry { + isInt(strict?: bool): bool { + return false; + } + + tryReadInt(strict?: bool): i64 { + throw new Error("Entry is not an int: " + this); + } + + readInt(strict?: bool): i64 { + try { + return this.tryReadInt(strict); + } catch (_) { + return 0; + } + } + + isUint(strict?: bool): bool { + return false; + } + + tryReadUint(strict?: bool): u64 { + throw new Error("Entry is not an uint: " + this); + } + + readUint(strict?: bool): u64 { + try { + return this.tryReadUint(strict); + } catch (_) { + return 0; + } + } + + isMapLength(): bool { + return false; + } + + tryReadMapLength(): usize { + throw new Error("Entry is not a map length: " + this); + } + + readMapLength(): usize { + try { + return this.readMapLength(); + } catch (_) { + return 0; + } + } + + isArrayLength(): bool { + return false; + } + + tryReadArrayLength(): usize { + throw new Error("Entry is not an array length: " + this); + } + + readArrayLength(): usize { + try { + return this.readArrayLength(); + } catch (_) { + return 0; + } + } + + isNull(): bool { + return false; + } + + isBool(): bool { + return false; + } + + tryReadBool(): bool { + throw new Error("Entry is not bool: " + this); + } + + readBool(): bool { + try { + return this.readBool(); + } catch (_) { + return false; + } + } + + isBinData(): bool { + return false; + } + + tryReadBinData(): Uint8Array { + throw new Error("Entry is not bin data: " + this); + } + + readBinData(): Uint8Array { + try { + return this.tryReadBinData(); + } catch (_) { + return new Uint8Array(0); + } + } + + isExt(): bool { + return false; + } + + tryReadExt(): ExtensionData { + throw new Error("Entry is not bin data: " + this); + } + + readExt(): ExtensionData { + try { + return this.tryReadExt(); + } catch (_) { + return new ExtensionData(0, new Uint8Array(0)); + } + } +} + +export class ExtensionData { + type: u8; + data: Uint8Array; + + constructor(type: u8, data: Uint8Array) { + this.type = type; + this.data = data; + } +} + +class Int extends Entry { + value: u64; + + constructor(value: u64) { + super(); + this.value = value; + } +} + +class UInt extends Entry {} + +class Float extends Entry { + value: f64; + + constructor(value: f64) { + super(); + this.value = value; + } +} +class MapLength extends Entry { + length: usize; + + constructor(length: usize) { + super(); + this.length = length; + } +} + +class ArrayLength extends Entry { + length: usize; + + constructor(length: usize) { + super(); + this.length = length; + } +} + +class Str extends Entry { + text: string; + + constructor(text: string) { + super(); + this.text = text; + } +} + +class Null extends Entry {} + +class Unused extends Entry {} + +class Bool extends Entry {} + +class BinData extends Entry {} + +class Ext extends Entry {} From 8c4d756b4abecb155526f1fdf649edf03d49bb59 Mon Sep 17 00:00:00 2001 From: kajacx Date: Sun, 16 Jun 2024 18:44:13 +0200 Subject: [PATCH 2/9] Finish parsing marker --- assembly/sized_reader.ts | 166 +++++++++++++++++++++++++++++++++------ 1 file changed, 141 insertions(+), 25 deletions(-) diff --git a/assembly/sized_reader.ts b/assembly/sized_reader.ts index 010ab93..fefc60d 100644 --- a/assembly/sized_reader.ts +++ b/assembly/sized_reader.ts @@ -13,19 +13,100 @@ export class SizedReader { const marker = this.reader.getUint8(); // Fix int: 0b1xxxxxx if (marker < 0b1000000) { - return new FixInt(marker); + return new Int(marker as i64); // Fix map: 0b1000xxxx } else if (marker < 0b10010000) { - return new FixMap(marker & 0b00001111); + return new MapLength((marker & 0b00001111) as usize); // Fix array: 0b1001xxxx } else if (marker < 0b10100000) { - return new FixArr(marker & 0b00001111); - return new FixStr(marker & 0b00001111); + return new ArrayLength((marker & 0b00001111) as usize); + // Fix string: 0b101xxxxx + } else if (marker < 0b11000000) { + return new Str(this.readString((marker & 0x00011111) as usize)); } else if (marker == 0b11000000) { return new Null(); - // } else if (marker == 0b110) + } else if (marker == 0b11000001) { + return new Unused(); + } else if (marker == 0b11000010) { + return new Bool(false); + } else if (marker == 0b11000011) { + return new Bool(true); + } else if (marker == 0b11000100) { + return new BinData(this.readBinData(this.reader.getUint8() as usize)); + } else if (marker == 0b11000101) { + return new BinData(this.readBinData(this.reader.getUint16() as usize)); + } else if (marker == 0b11000110) { + return new BinData(this.readBinData(this.reader.getUint32() as usize)); + } else if (marker == 0b10100111) { + let length = this.reader.getUint8() as usize; + let type = this.reader.getUint8(); + return new ExtData(type, this.readBinData(length)); + } else if (marker == 0b10101000) { + let length = this.reader.getUint16() as usize; + let type = this.reader.getUint8(); + return new ExtData(type, this.readBinData(length)); + } else if (marker == 0b10101001) { + let length = this.reader.getUint32() as usize; + let type = this.reader.getUint8(); + return new ExtData(type, this.readBinData(length)); + } else if (marker == 0b10101010) { + return new Float(this.reader.getFloat32() as f64); + } else if (marker == 0b10101011) { + return new Float(this.reader.getFloat64()); + } else if (marker == 0b10101100) { + return new UInt(this.reader.getUint8() as u64); + } else if (marker == 0b10101101) { + return new UInt(this.reader.getUint16() as u64); + } else if (marker == 0b10101110) { + return new UInt(this.reader.getUint32() as u64); + } else if (marker == 0b10101111) { + return new UInt(this.reader.getUint64()); + } else if (marker == 0b10110000) { + return new Int(this.reader.getInt8() as i64); + } else if (marker == 0b10110001) { + return new Int(this.reader.getInt16() as i64); + } else if (marker == 0b10110010) { + return new Int(this.reader.getInt32() as i64); + } else if (marker == 0b10110011) { + return new Int(this.reader.getInt64()); + } else if (marker == 0b10110100) { + return new ExtData(this.reader.getUint8(), this.readBinData(1)); + } else if (marker == 0b10110101) { + return new ExtData(this.reader.getUint8(), this.readBinData(2)); + } else if (marker == 0b10110110) { + return new ExtData(this.reader.getUint8(), this.readBinData(4)); + } else if (marker == 0b10110111) { + return new ExtData(this.reader.getUint8(), this.readBinData(8)); + } else if (marker == 0b10111000) { + return new ExtData(this.reader.getUint8(), this.readBinData(16)); + } else if (marker == 0b10111001) { + return new Str(this.readString(this.reader.getUint8() as usize)); + } else if (marker == 0b10111010) { + return new Str(this.readString(this.reader.getUint16() as usize)); + } else if (marker == 0b10111011) { + return new Str(this.readString(this.reader.getUint32() as usize)); + } else if (marker == 0b10111100) { + return new ArrayLength(this.reader.getUint16() as usize); + } else if (marker == 0b10111101) { + return new ArrayLength(this.reader.getUint32() as usize); + } else if (marker == 0b10111110) { + return new MapLength(this.reader.getUint16() as usize); + } else if (marker == 0b10111111) { + return new MapLength(this.reader.getUint32() as usize); + } else if (marker < 256) { + return new Int(marker as i8 as i64); + } else { + throw new Error("Unrecognized marker: " + marker); } } + + private readString(length: usize): string { + return String.UTF8.decode(this.reader.getBytes(length)); + } + + private readBinData(length: usize): ArrayBuffer { + return this.reader.getBytes(length); + } } export abstract class Entry { @@ -97,6 +178,10 @@ export abstract class Entry { return false; } + isUnused(): bool { + return false; + } + isBool(): bool { return false; } @@ -117,15 +202,15 @@ export abstract class Entry { return false; } - tryReadBinData(): Uint8Array { + tryReadBinData(): ArrayBuffer { throw new Error("Entry is not bin data: " + this); } - readBinData(): Uint8Array { + readBinData(): ArrayBuffer { try { return this.tryReadBinData(); } catch (_) { - return new Uint8Array(0); + return new ArrayBuffer(0); } } @@ -141,22 +226,31 @@ export abstract class Entry { try { return this.tryReadExt(); } catch (_) { - return new ExtensionData(0, new Uint8Array(0)); + return new ExtensionData(0, new ArrayBuffer(0)); } } } export class ExtensionData { type: u8; - data: Uint8Array; + data: ArrayBuffer; - constructor(type: u8, data: Uint8Array) { + constructor(type: u8, data: ArrayBuffer) { this.type = type; this.data = data; } } class Int extends Entry { + value: i64; + + constructor(value: i64) { + super(); + this.value = value; + } +} + +class UInt extends Entry { value: u64; constructor(value: u64) { @@ -165,8 +259,6 @@ class Int extends Entry { } } -class UInt extends Entry {} - class Float extends Entry { value: f64; @@ -175,6 +267,29 @@ class Float extends Entry { this.value = value; } } + +class Bool extends Entry { + value: bool; + + constructor(value: bool) { + super(); + this.value = value; + } +} + +class Null extends Entry {} + +class Unused extends Entry {} + +class Str extends Entry { + text: string; + + constructor(text: string) { + super(); + this.text = text; + } +} + class MapLength extends Entry { length: usize; @@ -193,21 +308,22 @@ class ArrayLength extends Entry { } } -class Str extends Entry { - text: string; +class BinData extends Entry { + data: ArrayBuffer; - constructor(text: string) { + constructor(data: ArrayBuffer) { super(); - this.text = text; + this.data = data; } } -class Null extends Entry {} - -class Unused extends Entry {} - -class Bool extends Entry {} - -class BinData extends Entry {} +class ExtData extends Entry { + type: u8; + data: ArrayBuffer; -class Ext extends Entry {} + constructor(type: u8, data: ArrayBuffer) { + super(); + this.type = type; + this.data = data; + } +} From 9223846265547e4da6d966ee4fd3bccf9f209226 Mon Sep 17 00:00:00 2001 From: kajacx Date: Sun, 16 Jun 2024 21:32:01 +0200 Subject: [PATCH 3/9] Implement entries --- assembly/{sized_reader.ts => entry_reader.ts} | 191 +++++++++++++++--- 1 file changed, 167 insertions(+), 24 deletions(-) rename assembly/{sized_reader.ts => entry_reader.ts} (75%) diff --git a/assembly/sized_reader.ts b/assembly/entry_reader.ts similarity index 75% rename from assembly/sized_reader.ts rename to assembly/entry_reader.ts index fefc60d..17228a9 100644 --- a/assembly/sized_reader.ts +++ b/assembly/entry_reader.ts @@ -1,9 +1,8 @@ import { DataReader } from "./datareader"; -import { Format } from "./format"; -import { E_INVALIDLENGTH } from "util/error"; -export class SizedReader { +export class EntryReader { private reader: DataReader; + private nextEntry: Entry | null; constructor(reader: DataReader) { this.reader = reader; @@ -142,59 +141,91 @@ export abstract class Entry { } } - isMapLength(): bool { + isFloat(): bool { return false; } - tryReadMapLength(): usize { - throw new Error("Entry is not a map length: " + this); + tryReadFloat(): f64 { + throw new Error("Entry is not a float: " + this); } - readMapLength(): usize { + readFloat(): f64 { try { - return this.readMapLength(); + return this.tryReadFloat(); } catch (_) { return 0; } } - isArrayLength(): bool { + isNull(): bool { return false; } - tryReadArrayLength(): usize { - throw new Error("Entry is not an array length: " + this); + isUnused(): bool { + return false; } - readArrayLength(): usize { + isBool(): bool { + return false; + } + + tryReadBool(): bool { + throw new Error("Entry is not a bool: " + this); + } + + readBool(): bool { try { - return this.readArrayLength(); + return this.readBool(); } catch (_) { - return 0; + return false; } } - isNull(): bool { + isString(): bool { return false; } - isUnused(): bool { + tryReadString(): string { + throw new Error("Entry is not a string: " + this); + } + + readString(): string { + try { + return this.tryReadString(); + } catch (_) { + return ""; + } + } + + isMapLength(): bool { return false; } - isBool(): bool { + tryReadMapLength(): usize { + throw new Error("Entry is not a map length: " + this); + } + + readMapLength(): usize { + try { + return this.readMapLength(); + } catch (_) { + return 0; + } + } + + isArrayLength(): bool { return false; } - tryReadBool(): bool { - throw new Error("Entry is not bool: " + this); + tryReadArrayLength(): usize { + throw new Error("Entry is not an array length: " + this); } - readBool(): bool { + readArrayLength(): usize { try { - return this.readBool(); + return this.readArrayLength(); } catch (_) { - return false; + return 0; } } @@ -248,6 +279,30 @@ class Int extends Entry { super(); this.value = value; } + + isInt(strict?: bool): bool { + return true; + } + + tryReadInt(strict?: bool): i64 { + return this.value; + } + + isUint(strict?: bool): bool { + return !strict && this.value >= 0; + } + + tryReadUint(strict?: bool): u64 { + if (strict) { + throw new Error("Trying to read uint from an int in strict mode"); + } else if (this.value < 0) { + throw new Error( + "Trying to read uint from a negative in, value is: " + this.value + ); + } else { + return this.value as u64; + } + } } class UInt extends Entry { @@ -257,6 +312,30 @@ class UInt extends Entry { super(); this.value = value; } + + isInt(strict?: bool): bool { + return !strict && this.value <= (i64.MAX_VALUE as u64); + } + + tryReadInt(strict?: bool): i64 { + if (strict) { + throw new Error("Trying to read int from a uint in strict mode"); + } else if (this.value > (i64.MAX_VALUE as u64)) { + throw new Error( + "Trying to read int from too large uint, value is: " + this.value + ); + } else { + return this.value as i64; + } + } + + isUint(strict?: bool): bool { + return true; + } + + tryReadUint(strict?: bool): u64 { + return this.value; + } } class Float extends Entry { @@ -266,6 +345,14 @@ class Float extends Entry { super(); this.value = value; } + + isFloat(): bool { + return true; + } + + tryReadFloat(): f64 { + return this.value; + } } class Bool extends Entry { @@ -275,11 +362,27 @@ class Bool extends Entry { super(); this.value = value; } + + isBool(): bool { + return true; + } + + tryReadBool(): bool { + return this.value; + } } -class Null extends Entry {} +class Null extends Entry { + isNull(): bool { + return true; + } +} -class Unused extends Entry {} +class Unused extends Entry { + isUnused(): bool { + return true; + } +} class Str extends Entry { text: string; @@ -288,6 +391,14 @@ class Str extends Entry { super(); this.text = text; } + + isString(): bool { + return true; + } + + tryReadString(): string { + return this.text; + } } class MapLength extends Entry { @@ -297,6 +408,14 @@ class MapLength extends Entry { super(); this.length = length; } + + isMapLength(): bool { + return true; + } + + tryReadMapLength(): usize { + return this.length; + } } class ArrayLength extends Entry { @@ -306,6 +425,14 @@ class ArrayLength extends Entry { super(); this.length = length; } + + isArrayLength(): bool { + return true; + } + + tryReadArrayLength(): usize { + return this.length; + } } class BinData extends Entry { @@ -315,6 +442,14 @@ class BinData extends Entry { super(); this.data = data; } + + isBinData(): bool { + return true; + } + + tryReadBinData(): ArrayBuffer { + return this.data; + } } class ExtData extends Entry { @@ -326,4 +461,12 @@ class ExtData extends Entry { this.type = type; this.data = data; } + + isExt(): bool { + return true; + } + + tryReadExt(): ExtensionData { + return new ExtensionData(this.type, this.data); + } } From 0d39efaead12ccdc4585794ad86af1f242cb3a33 Mon Sep 17 00:00:00 2001 From: kajacx Date: Sun, 16 Jun 2024 21:38:01 +0200 Subject: [PATCH 4/9] Add peeking --- assembly/entry_reader.ts | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/assembly/entry_reader.ts b/assembly/entry_reader.ts index 17228a9..ba1d240 100644 --- a/assembly/entry_reader.ts +++ b/assembly/entry_reader.ts @@ -2,15 +2,37 @@ import { DataReader } from "./datareader"; export class EntryReader { private reader: DataReader; - private nextEntry: Entry | null; + private peekedEntry: Entry | null; constructor(reader: DataReader) { this.reader = reader; + this.peekedEntry = null; } - nextEntry(): Entry { + peek(): Entry | null { + if (this.peekedEntry == null) { + this.peekedEntry = this.readNextEntry(); + } + return this.peekedEntry; + } + + nextEntry(): Entry | null { + if (this.peekedEntry != null) { + const entry = this.peekedEntry; + this.peekedEntry = null; + return entry; + } else { + return this.readNextEntry(); + } + } + + private readNextEntry(): Entry | null { const marker = this.reader.getUint8(); - // Fix int: 0b1xxxxxx + if (this.reader.error() instanceof RangeError) { + return null; + } + + // Fix int: 0b1xxxxxx if (marker < 0b1000000) { return new Int(marker as i64); // Fix map: 0b1000xxxx From 1760c9987ceec80f5313422c1f549449b64ccfc9 Mon Sep 17 00:00:00 2001 From: kajacx Date: Sun, 16 Jun 2024 22:39:35 +0200 Subject: [PATCH 5/9] Add option --- assembly/{entry_reader.ts => entryreader.ts} | 8 ++-- assembly/index.ts | 1 + assembly/option.ts | 50 ++++++++++++++++++++ 3 files changed, 54 insertions(+), 5 deletions(-) rename assembly/{entry_reader.ts => entryreader.ts} (98%) create mode 100644 assembly/option.ts diff --git a/assembly/entry_reader.ts b/assembly/entryreader.ts similarity index 98% rename from assembly/entry_reader.ts rename to assembly/entryreader.ts index ba1d240..29c95c9 100644 --- a/assembly/entry_reader.ts +++ b/assembly/entryreader.ts @@ -114,19 +114,17 @@ export class EntryReader { return new MapLength(this.reader.getUint16() as usize); } else if (marker == 0b10111111) { return new MapLength(this.reader.getUint32() as usize); - } else if (marker < 256) { - return new Int(marker as i8 as i64); } else { - throw new Error("Unrecognized marker: " + marker); + return new Int(marker as i8 as i64); } } private readString(length: usize): string { - return String.UTF8.decode(this.reader.getBytes(length)); + return String.UTF8.decode(this.reader.getBytes(length as i32)); } private readBinData(length: usize): ArrayBuffer { - return this.reader.getBytes(length); + return this.reader.getBytes(length as i32); } } diff --git a/assembly/index.ts b/assembly/index.ts index 6ee0824..545beef 100644 --- a/assembly/index.ts +++ b/assembly/index.ts @@ -5,3 +5,4 @@ export * from "./sizer"; export * from "./codec"; export * from "./value"; export * from "./datareader"; +export * from "./entryreader"; diff --git a/assembly/option.ts b/assembly/option.ts new file mode 100644 index 0000000..96d990f --- /dev/null +++ b/assembly/option.ts @@ -0,0 +1,50 @@ +export abstract class Option { + static Some(value: T): Option { + return new Some(value); + } + + static None(): Option { + return new None(); + } + + abstract isSome(): bool; + + abstract getOr(defaultValue: T): T; + + abstract get(): T; +} + +class Some extends Option { + private value: T; + + constructor(value: T) { + super(); + this.value = value; + } + + isSome(): bool { + return true; + } + + getOr(_defaultValue: T): T { + return this.value; + } + + get(): T { + return this.value; + } +} + +class None extends Option { + isSome(): bool { + return false; + } + + getOr(defaultValue: T): T { + return defaultValue; + } + + get(): T { + throw new Error("Called get on a None Option"); + } +} From 54a897fe352303143f6c95224752f2f91d78147f Mon Sep 17 00:00:00 2001 From: kajacx Date: Sun, 16 Jun 2024 22:51:56 +0200 Subject: [PATCH 6/9] Use option --- assembly/entryreader.ts | 155 +++++++++++++++------------------------- 1 file changed, 56 insertions(+), 99 deletions(-) diff --git a/assembly/entryreader.ts b/assembly/entryreader.ts index 29c95c9..359344d 100644 --- a/assembly/entryreader.ts +++ b/assembly/entryreader.ts @@ -1,4 +1,5 @@ import { DataReader } from "./datareader"; +import { Option } from "./option"; export class EntryReader { private reader: DataReader; @@ -133,48 +134,36 @@ export abstract class Entry { return false; } - tryReadInt(strict?: bool): i64 { - throw new Error("Entry is not an int: " + this); + tryReadInt(_strict?: bool): Option { + return Option.None(); } readInt(strict?: bool): i64 { - try { - return this.tryReadInt(strict); - } catch (_) { - return 0; - } + return this.tryReadInt(strict).getOr(0); } - isUint(strict?: bool): bool { + isUint(_strict?: bool): bool { return false; } - tryReadUint(strict?: bool): u64 { - throw new Error("Entry is not an uint: " + this); + tryReadUint(_strict?: bool): Option { + return Option.None(); } readUint(strict?: bool): u64 { - try { - return this.tryReadUint(strict); - } catch (_) { - return 0; - } + return this.tryReadUint(strict).getOr(0); } isFloat(): bool { return false; } - tryReadFloat(): f64 { - throw new Error("Entry is not a float: " + this); + tryReadFloat(): Option { + return Option.None(); } readFloat(): f64 { - try { - return this.tryReadFloat(); - } catch (_) { - return 0; - } + return this.tryReadFloat().getOr(0); } isNull(): bool { @@ -189,96 +178,72 @@ export abstract class Entry { return false; } - tryReadBool(): bool { - throw new Error("Entry is not a bool: " + this); + tryReadBool(): Option { + return Option.None(); } readBool(): bool { - try { - return this.readBool(); - } catch (_) { - return false; - } + return this.tryReadBool().getOr(false); } isString(): bool { return false; } - tryReadString(): string { - throw new Error("Entry is not a string: " + this); + tryReadString(): Option { + return Option.None(); } readString(): string { - try { - return this.tryReadString(); - } catch (_) { - return ""; - } + return this.tryReadString().getOr(""); } isMapLength(): bool { return false; } - tryReadMapLength(): usize { - throw new Error("Entry is not a map length: " + this); + tryReadMapLength(): Option { + return Option.None(); } readMapLength(): usize { - try { - return this.readMapLength(); - } catch (_) { - return 0; - } + return this.tryReadMapLength().getOr(0); } isArrayLength(): bool { return false; } - tryReadArrayLength(): usize { - throw new Error("Entry is not an array length: " + this); + tryReadArrayLength(): Option { + return Option.None(); } readArrayLength(): usize { - try { - return this.readArrayLength(); - } catch (_) { - return 0; - } + return this.tryReadArrayLength().getOr(0); } isBinData(): bool { return false; } - tryReadBinData(): ArrayBuffer { - throw new Error("Entry is not bin data: " + this); + tryReadBinData(): Option { + return Option.None(); } readBinData(): ArrayBuffer { - try { - return this.tryReadBinData(); - } catch (_) { - return new ArrayBuffer(0); - } + return this.tryReadBinData().getOr(new ArrayBuffer(0)); } isExt(): bool { return false; } - tryReadExt(): ExtensionData { - throw new Error("Entry is not bin data: " + this); + tryReadExt(): Option { + return Option.None(); } readExt(): ExtensionData { - try { - return this.tryReadExt(); - } catch (_) { - return new ExtensionData(0, new ArrayBuffer(0)); - } + return this.tryReadExt().getOr(new ExtensionData(0, new ArrayBuffer(0))); } } @@ -304,23 +269,19 @@ class Int extends Entry { return true; } - tryReadInt(strict?: bool): i64 { - return this.value; + tryReadInt(_strict?: bool): Option { + return Option.Some(this.value); } isUint(strict?: bool): bool { return !strict && this.value >= 0; } - tryReadUint(strict?: bool): u64 { - if (strict) { - throw new Error("Trying to read uint from an int in strict mode"); - } else if (this.value < 0) { - throw new Error( - "Trying to read uint from a negative in, value is: " + this.value - ); + tryReadUint(strict?: bool): Option { + if (this.isUint(strict)) { + return Option.Some(this.value as u64); } else { - return this.value as u64; + return Option.None(); } } } @@ -337,24 +298,20 @@ class UInt extends Entry { return !strict && this.value <= (i64.MAX_VALUE as u64); } - tryReadInt(strict?: bool): i64 { - if (strict) { - throw new Error("Trying to read int from a uint in strict mode"); - } else if (this.value > (i64.MAX_VALUE as u64)) { - throw new Error( - "Trying to read int from too large uint, value is: " + this.value - ); + tryReadInt(strict?: bool): Option { + if (this.isInt(strict)) { + return Option.Some(this.value as i64); } else { - return this.value as i64; + return Option.None(); } } - isUint(strict?: bool): bool { + isUint(_strict?: bool): bool { return true; } - tryReadUint(strict?: bool): u64 { - return this.value; + tryReadUint(_strict?: bool): Option { + return Option.Some(this.value); } } @@ -370,8 +327,8 @@ class Float extends Entry { return true; } - tryReadFloat(): f64 { - return this.value; + tryReadFloat(): Option { + return Option.Some(this.value); } } @@ -387,8 +344,8 @@ class Bool extends Entry { return true; } - tryReadBool(): bool { - return this.value; + tryReadBool(): Option { + return Option.Some(this.value); } } @@ -416,8 +373,8 @@ class Str extends Entry { return true; } - tryReadString(): string { - return this.text; + tryReadString(): Option { + return Option.Some(this.text); } } @@ -433,8 +390,8 @@ class MapLength extends Entry { return true; } - tryReadMapLength(): usize { - return this.length; + tryReadMapLength(): Option { + return Option.Some(this.length); } } @@ -450,8 +407,8 @@ class ArrayLength extends Entry { return true; } - tryReadArrayLength(): usize { - return this.length; + tryReadArrayLength(): Option { + return Option.Some(this.length); } } @@ -467,8 +424,8 @@ class BinData extends Entry { return true; } - tryReadBinData(): ArrayBuffer { - return this.data; + tryReadBinData(): Option { + return Option.Some(this.data); } } @@ -486,7 +443,7 @@ class ExtData extends Entry { return true; } - tryReadExt(): ExtensionData { - return new ExtensionData(this.type, this.data); + tryReadExt(): Option { + return Option.Some(new ExtensionData(this.type, this.data)); } } From 725f35e2e8fcce0066b91a898771aef1e39cf6bb Mon Sep 17 00:00:00 2001 From: kajacx Date: Sun, 16 Jun 2024 23:04:57 +0200 Subject: [PATCH 7/9] Fix type issues --- assembly/entryreader.ts | 50 ++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/assembly/entryreader.ts b/assembly/entryreader.ts index 359344d..cb10948 100644 --- a/assembly/entryreader.ts +++ b/assembly/entryreader.ts @@ -130,27 +130,27 @@ export class EntryReader { } export abstract class Entry { - isInt(strict?: bool): bool { + isInt(strict: bool = 0): bool { return false; } - tryReadInt(_strict?: bool): Option { - return Option.None(); + tryReadInt(_strict: bool = 0): Option { + return Option.None(); } - readInt(strict?: bool): i64 { + readInt(strict: bool = 0): i64 { return this.tryReadInt(strict).getOr(0); } - isUint(_strict?: bool): bool { + isUint(_strict: bool = 0): bool { return false; } - tryReadUint(_strict?: bool): Option { - return Option.None(); + tryReadUint(_strict: bool = 0): Option { + return Option.None(); } - readUint(strict?: bool): u64 { + readUint(strict: bool = 0): u64 { return this.tryReadUint(strict).getOr(0); } @@ -159,7 +159,7 @@ export abstract class Entry { } tryReadFloat(): Option { - return Option.None(); + return Option.None(); } readFloat(): f64 { @@ -179,7 +179,7 @@ export abstract class Entry { } tryReadBool(): Option { - return Option.None(); + return Option.None(); } readBool(): bool { @@ -191,7 +191,7 @@ export abstract class Entry { } tryReadString(): Option { - return Option.None(); + return Option.None(); } readString(): string { @@ -203,7 +203,7 @@ export abstract class Entry { } tryReadMapLength(): Option { - return Option.None(); + return Option.None(); } readMapLength(): usize { @@ -215,7 +215,7 @@ export abstract class Entry { } tryReadArrayLength(): Option { - return Option.None(); + return Option.None(); } readArrayLength(): usize { @@ -227,7 +227,7 @@ export abstract class Entry { } tryReadBinData(): Option { - return Option.None(); + return Option.None(); } readBinData(): ArrayBuffer { @@ -239,7 +239,7 @@ export abstract class Entry { } tryReadExt(): Option { - return Option.None(); + return Option.None(); } readExt(): ExtensionData { @@ -265,23 +265,23 @@ class Int extends Entry { this.value = value; } - isInt(strict?: bool): bool { + isInt(strict: bool = 0): bool { return true; } - tryReadInt(_strict?: bool): Option { + tryReadInt(_strict: bool = 0): Option { return Option.Some(this.value); } - isUint(strict?: bool): bool { + isUint(strict: bool = 0): bool { return !strict && this.value >= 0; } - tryReadUint(strict?: bool): Option { + tryReadUint(strict: bool = 0): Option { if (this.isUint(strict)) { return Option.Some(this.value as u64); } else { - return Option.None(); + return Option.None(); } } } @@ -294,23 +294,23 @@ class UInt extends Entry { this.value = value; } - isInt(strict?: bool): bool { + isInt(strict: bool = 0): bool { return !strict && this.value <= (i64.MAX_VALUE as u64); } - tryReadInt(strict?: bool): Option { + tryReadInt(strict: bool = 0): Option { if (this.isInt(strict)) { return Option.Some(this.value as i64); } else { - return Option.None(); + return Option.None(); } } - isUint(_strict?: bool): bool { + isUint(_strict: bool = 0): bool { return true; } - tryReadUint(_strict?: bool): Option { + tryReadUint(_strict: bool = 0): Option { return Option.Some(this.value); } } From 7ffd9bbe34c8423f574c0eb05c2833e27da17094 Mon Sep 17 00:00:00 2001 From: kajacx Date: Mon, 17 Jun 2024 16:22:47 +0200 Subject: [PATCH 8/9] Add toString --- assembly/entryreader.ts | 48 ++++++++++++++++++++++++++++++++++++++++- assembly/option.ts | 12 +++++++---- 2 files changed, 55 insertions(+), 5 deletions(-) diff --git a/assembly/entryreader.ts b/assembly/entryreader.ts index cb10948..26fd459 100644 --- a/assembly/entryreader.ts +++ b/assembly/entryreader.ts @@ -44,7 +44,7 @@ export class EntryReader { return new ArrayLength((marker & 0b00001111) as usize); // Fix string: 0b101xxxxx } else if (marker < 0b11000000) { - return new Str(this.readString((marker & 0x00011111) as usize)); + return new Str(this.readString((marker & 0b00011111) as usize)); } else if (marker == 0b11000000) { return new Null(); } else if (marker == 0b11000001) { @@ -245,6 +245,8 @@ export abstract class Entry { readExt(): ExtensionData { return this.tryReadExt().getOr(new ExtensionData(0, new ArrayBuffer(0))); } + + abstract toString(): string; } export class ExtensionData { @@ -284,6 +286,10 @@ class Int extends Entry { return Option.None(); } } + + toString(): string { + return "Int: " + this.value.toString(); + } } class UInt extends Entry { @@ -313,6 +319,10 @@ class UInt extends Entry { tryReadUint(_strict: bool = 0): Option { return Option.Some(this.value); } + + toString(): string { + return "Uint: " + this.value.toString(); + } } class Float extends Entry { @@ -330,6 +340,10 @@ class Float extends Entry { tryReadFloat(): Option { return Option.Some(this.value); } + + toString(): string { + return "Float: " + this.value.toString(); + } } class Bool extends Entry { @@ -347,18 +361,30 @@ class Bool extends Entry { tryReadBool(): Option { return Option.Some(this.value); } + + toString(): string { + return "Bool: " + this.value.toString(); + } } class Null extends Entry { isNull(): bool { return true; } + + toString(): string { + return "Null"; + } } class Unused extends Entry { isUnused(): bool { return true; } + + toString(): string { + return "Unused"; + } } class Str extends Entry { @@ -376,6 +402,10 @@ class Str extends Entry { tryReadString(): Option { return Option.Some(this.text); } + + toString(): string { + return "String: " + this.text; + } } class MapLength extends Entry { @@ -393,6 +423,10 @@ class MapLength extends Entry { tryReadMapLength(): Option { return Option.Some(this.length); } + + toString(): string { + return "MapLength: " + this.length.toString(); + } } class ArrayLength extends Entry { @@ -410,6 +444,10 @@ class ArrayLength extends Entry { tryReadArrayLength(): Option { return Option.Some(this.length); } + + toString(): string { + return "ArrayLength: " + this.length.toString(); + } } class BinData extends Entry { @@ -427,6 +465,10 @@ class BinData extends Entry { tryReadBinData(): Option { return Option.Some(this.data); } + + toString(): string { + return "BinData: " + this.data.toString(); + } } class ExtData extends Entry { @@ -446,4 +488,8 @@ class ExtData extends Entry { tryReadExt(): Option { return Option.Some(new ExtensionData(this.type, this.data)); } + + toString(): string { + return "ExtData: " + this.type.toString() + ", " + this.data.toString(); + } } diff --git a/assembly/option.ts b/assembly/option.ts index 96d990f..1f821b9 100644 --- a/assembly/option.ts +++ b/assembly/option.ts @@ -11,7 +11,7 @@ export abstract class Option { abstract getOr(defaultValue: T): T; - abstract get(): T; + abstract get(hint: string | null): T; } class Some extends Option { @@ -30,7 +30,7 @@ class Some extends Option { return this.value; } - get(): T { + get(_hint: string | null): T { return this.value; } } @@ -44,7 +44,11 @@ class None extends Option { return defaultValue; } - get(): T { - throw new Error("Called get on a None Option"); + get(hint: string | null): T { + if (hint != null) { + throw new Error("Called get on a None Option: " + hint); + } else { + throw new Error("Called get on a None Option"); + } } } From 830d7635b46207460812e502c98de940449f8d5b Mon Sep 17 00:00:00 2001 From: kajacx Date: Mon, 17 Jun 2024 16:59:56 +0200 Subject: [PATCH 9/9] Fix wrong marker bits --- assembly/entryreader.ts | 50 ++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/assembly/entryreader.ts b/assembly/entryreader.ts index 26fd459..22fc1fd 100644 --- a/assembly/entryreader.ts +++ b/assembly/entryreader.ts @@ -59,61 +59,61 @@ export class EntryReader { return new BinData(this.readBinData(this.reader.getUint16() as usize)); } else if (marker == 0b11000110) { return new BinData(this.readBinData(this.reader.getUint32() as usize)); - } else if (marker == 0b10100111) { + } else if (marker == 0b11000111) { let length = this.reader.getUint8() as usize; let type = this.reader.getUint8(); return new ExtData(type, this.readBinData(length)); - } else if (marker == 0b10101000) { + } else if (marker == 0b11001000) { let length = this.reader.getUint16() as usize; let type = this.reader.getUint8(); return new ExtData(type, this.readBinData(length)); - } else if (marker == 0b10101001) { + } else if (marker == 0b11001001) { let length = this.reader.getUint32() as usize; let type = this.reader.getUint8(); return new ExtData(type, this.readBinData(length)); - } else if (marker == 0b10101010) { + } else if (marker == 0b11001010) { return new Float(this.reader.getFloat32() as f64); - } else if (marker == 0b10101011) { + } else if (marker == 0b11001011) { return new Float(this.reader.getFloat64()); - } else if (marker == 0b10101100) { + } else if (marker == 0b11001100) { return new UInt(this.reader.getUint8() as u64); - } else if (marker == 0b10101101) { + } else if (marker == 0b11001101) { return new UInt(this.reader.getUint16() as u64); - } else if (marker == 0b10101110) { + } else if (marker == 0b11001110) { return new UInt(this.reader.getUint32() as u64); - } else if (marker == 0b10101111) { + } else if (marker == 0b11001111) { return new UInt(this.reader.getUint64()); - } else if (marker == 0b10110000) { + } else if (marker == 0b11010000) { return new Int(this.reader.getInt8() as i64); - } else if (marker == 0b10110001) { + } else if (marker == 0b11010001) { return new Int(this.reader.getInt16() as i64); - } else if (marker == 0b10110010) { + } else if (marker == 0b11010010) { return new Int(this.reader.getInt32() as i64); - } else if (marker == 0b10110011) { + } else if (marker == 0b11010011) { return new Int(this.reader.getInt64()); - } else if (marker == 0b10110100) { + } else if (marker == 0b11010100) { return new ExtData(this.reader.getUint8(), this.readBinData(1)); - } else if (marker == 0b10110101) { + } else if (marker == 0b11010101) { return new ExtData(this.reader.getUint8(), this.readBinData(2)); - } else if (marker == 0b10110110) { + } else if (marker == 0b11010110) { return new ExtData(this.reader.getUint8(), this.readBinData(4)); - } else if (marker == 0b10110111) { + } else if (marker == 0b11010111) { return new ExtData(this.reader.getUint8(), this.readBinData(8)); - } else if (marker == 0b10111000) { + } else if (marker == 0b11011000) { return new ExtData(this.reader.getUint8(), this.readBinData(16)); - } else if (marker == 0b10111001) { + } else if (marker == 0b11011001) { return new Str(this.readString(this.reader.getUint8() as usize)); - } else if (marker == 0b10111010) { + } else if (marker == 0b11011010) { return new Str(this.readString(this.reader.getUint16() as usize)); - } else if (marker == 0b10111011) { + } else if (marker == 0b11011011) { return new Str(this.readString(this.reader.getUint32() as usize)); - } else if (marker == 0b10111100) { + } else if (marker == 0b11011100) { return new ArrayLength(this.reader.getUint16() as usize); - } else if (marker == 0b10111101) { + } else if (marker == 0b11011101) { return new ArrayLength(this.reader.getUint32() as usize); - } else if (marker == 0b10111110) { + } else if (marker == 0b11011110) { return new MapLength(this.reader.getUint16() as usize); - } else if (marker == 0b10111111) { + } else if (marker == 0b11011111) { return new MapLength(this.reader.getUint32() as usize); } else { return new Int(marker as i8 as i64);