Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add I32LEB128 #11

Merged
merged 16 commits into from
Apr 21, 2023
2 changes: 1 addition & 1 deletion types/array/array.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,6 @@ export class ArrayType<T> implements SizedType<T[]>, ViewableType<T[]> {
});
}

return array as T[];
return array;
}
}
12 changes: 10 additions & 2 deletions types/string/fixed_length.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,22 @@ export class FixedLengthString implements SizedType<string> {

read(dataView: DataView, byteOffset = 0): string {
return decoder.decode(
new Uint8Array(dataView.buffer, byteOffset, byteOffset + this.byteLength),
new Uint8Array(
dataView.buffer,
dataView.byteOffset + byteOffset,
this.byteLength - byteOffset,
),
);
}

write(value: string, dataView: DataView, byteOffset = 0) {
encoder.encodeInto(
value,
new Uint8Array(dataView.buffer, byteOffset, this.byteLength),
new Uint8Array(
dataView.buffer,
dataView.byteOffset + byteOffset,
this.byteLength - byteOffset,
),
);
}
}
40 changes: 40 additions & 0 deletions types/varint/mod.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { Type } from "../types.ts";

const SEGMENT_BITS = 0x7F;
const CONTINUE_BIT = 0x80;

export class Leb128Varint implements Type<number> {
MierenManz marked this conversation as resolved.
Show resolved Hide resolved
read(dataView: DataView, byteOffset = 0): number {
let value = 0, position = 0;
while (true) {
const currentByte = dataView.getInt8(byteOffset);
value |= (currentByte & SEGMENT_BITS) << position;

if ((currentByte & CONTINUE_BIT) === 0) break;

position += 7;
byteOffset++;

if (position >= 32) {
throw new Error("VarInt is too big");
MierenManz marked this conversation as resolved.
Show resolved Hide resolved
}
}

return value;
}

write(value: number, dataView: DataView, byteOffset = 0): void {
while (true) {
if ((value & ~SEGMENT_BITS) === 0) {
dataView.setInt8(byteOffset, value);
return;
}

dataView.setInt8(byteOffset, value & SEGMENT_BITS | CONTINUE_BIT);
byteOffset++;
value >>>= 7;
}
}
}

export const leb128Varint = new Leb128Varint();
MierenManz marked this conversation as resolved.
Show resolved Hide resolved
70 changes: 70 additions & 0 deletions types/varint/mod_test.ts
MierenManz marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { Leb128Varint } from "./mod.ts";
import { assertEquals } from "https://deno.land/[email protected]/testing/asserts.ts";

Deno.test({
name: "Read Positive varint",
fn: () => {
let data = Uint8Array.of(127);
let result = new Leb128Varint().read(new DataView(data.buffer));
assertEquals(result, 127);

data = Uint8Array.of(128, 1);
result = new Leb128Varint().read(new DataView(data.buffer));
assertEquals(result, 128);

data = Uint8Array.of(221, 199, 1);
result = new Leb128Varint().read(new DataView(data.buffer));
assertEquals(result, 25565);

data = Uint8Array.of(255, 255, 255, 255, 7);
result = new Leb128Varint().read(new DataView(data.buffer));
assertEquals(result, 2147483647);
},
});

Deno.test({
name: "Read Negative varint",
fn: () => {
let data = Uint8Array.of(255, 255, 255, 255, 15);
let result = new Leb128Varint().read(new DataView(data.buffer));
assertEquals(result, -1);

data = Uint8Array.of(128, 128, 128, 128, 8);
result = new Leb128Varint().read(new DataView(data.buffer));
assertEquals(result, -2147483648);
},
});

Deno.test({
name: "Write Positive varint",
fn: () => {
let data = new Uint8Array(1);
new Leb128Varint().write(127, new DataView(data.buffer));
assertEquals(data, Uint8Array.of(127));

data = new Uint8Array(2);
new Leb128Varint().write(128, new DataView(data.buffer));
assertEquals(data, Uint8Array.of(128, 1));

data = new Uint8Array(3);
new Leb128Varint().write(25565, new DataView(data.buffer));
assertEquals(data, Uint8Array.of(221, 199, 1));

data = new Uint8Array(5);
new Leb128Varint().write(2147483647, new DataView(data.buffer));
assertEquals(data, Uint8Array.of(255, 255, 255, 255, 7));
},
});

Deno.test({
name: "Write Negative varint",
fn: () => {
let data = new Uint8Array(5);
new Leb128Varint().write(-1, new DataView(data.buffer));
assertEquals(data, Uint8Array.of(255, 255, 255, 255, 15));

data = new Uint8Array(5);
new Leb128Varint().write(-2147483648, new DataView(data.buffer));
assertEquals(data, Uint8Array.of(128, 128, 128, 128, 8));
},
});