Skip to content

Commit 9e6e56d

Browse files
feat: 128 bit types (#19)
Co-authored-by: Elias Sjögreen <[email protected]>
1 parent bca52d5 commit 9e6e56d

File tree

4 files changed

+128
-0
lines changed

4 files changed

+128
-0
lines changed

types/primitive/i128.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { AlignedType } from "../types.ts";
2+
import { endianess } from "../../utils.ts";
3+
4+
export class I128 implements AlignedType<bigint> {
5+
byteLength = 16;
6+
byteAlign = 16;
7+
endian;
8+
9+
constructor(endian: boolean = endianess) {
10+
this.endian = endian;
11+
}
12+
13+
read(dataView: DataView, byteOffset = 0): bigint {
14+
const hi = dataView.getBigInt64(byteOffset, this.endian);
15+
const lo = dataView.getBigInt64(byteOffset + 8, this.endian);
16+
return this.endian ? (lo << 64n) | hi : (hi << 64n) | lo;
17+
}
18+
19+
write(value: bigint, dataView: DataView, byteOffset = 0) {
20+
const lo = value & 0xffffffffffffffffn;
21+
const hi = value >> 64n;
22+
dataView.setBigInt64(byteOffset, this.endian ? hi : lo, this.endian);
23+
dataView.setBigInt64(byteOffset + 8, this.endian ? lo : hi, this.endian);
24+
return dataView.buffer;
25+
}
26+
}
27+
28+
export const i128 = new I128();
29+
export const i128le = new I128(true);
30+
export const i128be = new I128(false);

types/primitive/i128_test.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { i128be, i128le } from "./i128.ts";
2+
import { assertEquals } from "std/testing/asserts.ts";
3+
4+
Deno.test("i128", async ({ step }) => {
5+
const buff = new ArrayBuffer(16);
6+
const dt = new DataView(buff);
7+
const value = 12n;
8+
9+
await step("read", () => {
10+
// Little endian
11+
const lo = value & 0xffffffffffffffffn;
12+
const hi = value >> 64n;
13+
dt.setBigInt64(0, lo, true);
14+
dt.setBigInt64(8, hi, true);
15+
assertEquals(value, i128le.read(dt));
16+
// Big endian
17+
dt.setBigInt64(0, hi, false);
18+
dt.setBigInt64(8, lo, false);
19+
assertEquals(value, i128be.read(dt));
20+
});
21+
22+
await step("write", () => {
23+
// Little endian
24+
i128le.write(value, dt);
25+
let lo = dt.getBigInt64(0, true);
26+
let hi = dt.getBigInt64(8, true);
27+
assertEquals(value, (lo << 64n) | hi);
28+
// Big endian
29+
i128be.write(value, dt);
30+
lo = dt.getBigInt64(8, false);
31+
hi = dt.getBigInt64(0, false);
32+
assertEquals(value, (lo << 64n) | hi);
33+
});
34+
});

types/primitive/u128.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { AlignedType } from "../types.ts";
2+
import { endianess } from "../../utils.ts";
3+
4+
export class U128 implements AlignedType<bigint> {
5+
byteLength = 16;
6+
byteAlign = 16;
7+
endian;
8+
9+
constructor(endian: boolean = endianess) {
10+
this.endian = endian;
11+
}
12+
13+
read(dataView: DataView, byteOffset = 0): bigint {
14+
const hi = dataView.getBigUint64(byteOffset, this.endian);
15+
const lo = dataView.getBigUint64(byteOffset + 8, this.endian);
16+
return this.endian ? (lo << 64n) | hi : (hi << 64n) | lo;
17+
}
18+
19+
write(value: bigint, dataView: DataView, byteOffset = 0) {
20+
const lo = value & 0xffffffffffffffffn;
21+
const hi = value >> 64n;
22+
dataView.setBigUint64(byteOffset, this.endian ? hi : lo, this.endian);
23+
dataView.setBigUint64(byteOffset + 8, this.endian ? lo : hi, this.endian);
24+
return dataView.buffer;
25+
}
26+
}
27+
28+
export const u128 = new U128();
29+
export const u128le = new U128(true);
30+
export const u128be = new U128(false);

types/primitive/u128_test.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { u128be, u128le } from "./u128.ts";
2+
import { assertEquals } from "std/testing/asserts.ts";
3+
4+
Deno.test("u128", async ({ step }) => {
5+
const buff = new ArrayBuffer(16);
6+
const dt = new DataView(buff);
7+
const value = 12n;
8+
9+
await step("read", () => {
10+
// Little endian
11+
const lo = value & 0xffffffffffffffffn;
12+
const hi = value >> 64n;
13+
dt.setBigUint64(0, lo, true);
14+
dt.setBigUint64(8, hi, true);
15+
assertEquals(value, u128le.read(dt));
16+
// Big endian
17+
dt.setBigUint64(0, hi, false);
18+
dt.setBigUint64(8, lo, false);
19+
assertEquals(value, u128be.read(dt));
20+
});
21+
22+
await step("write", () => {
23+
// Little endian
24+
u128le.write(value, dt);
25+
let lo = dt.getBigInt64(0, true);
26+
let hi = dt.getBigInt64(8, true);
27+
assertEquals(value, (lo << 64n) | hi);
28+
// Big endian
29+
u128be.write(value, dt);
30+
lo = dt.getBigInt64(8, false);
31+
hi = dt.getBigInt64(0, false);
32+
assertEquals(value, (lo << 64n) | hi);
33+
});
34+
});

0 commit comments

Comments
 (0)