108 lines
2.9 KiB
TypeScript

export class Utils {
public static numberToHex(n: number): string {
const hex = n.toString(16);
return hex.length === 1 ? `0${hex}` : hex;
}
public static bufToHex(buf: DataView | Uint8Array | number[], separator: string = " "): string {
const arr: number[] = buf instanceof DataView ? this.dataViewToNumberArray(buf) : Array.from(buf);
return arr.map((n) => Utils.numberToHex(n)).join(separator);
}
public static hexToBuf(str: string): Uint8Array {
const match = str.match(/[\da-f]{2}/gi);
if (!match) {
return new Uint8Array();
}
return new Uint8Array(
match.map((h) => {
return parseInt(h, 16);
})
);
}
public static dataViewToNumberArray(dw: DataView): number[] {
const a: number[] = [];
for (let i = 0; i < dw.byteLength; i++) {
a.push(dw.getUint8(i));
}
return a;
}
public static dataViewToU8Array(dw: DataView): Uint8Array {
return Uint8Array.from(this.dataViewToNumberArray(dw));
}
public static u8ArrayToString(arr: Uint8Array): string {
return new TextDecoder().decode(arr);
}
/** Count non-zero bits in the byte array */
public static countSetBits(arr: Uint8Array): number {
// not so efficient, but readable
let count: number = 0;
arr.forEach((value) => {
// shift until value becomes zero
while (value > 0) {
// check last bit
if ((value & 1) === 1) {
count++;
}
value >>= 1;
}
});
return count;
}
/** Big endian */
public static u16ToBytes(n: number): [number, number] {
const h = (n >> 8) & 0xff;
const l = n % 256 & 0xff;
return [h, l];
}
/** Big endian */
public static bytesToI16(arr: Uint8Array): number {
Validators.u8ArrayLengthEquals(arr, 2);
return arr[0] * 256 + arr[1];
}
public static u8ArraysEqual(a: Uint8Array, b: Uint8Array): boolean {
return a.length === b.length && a.every((el, i) => el === b[i]);
}
public static sleep(ms: number): Promise<undefined> {
return new Promise((resolve) => setTimeout(resolve, ms));
}
public static isBluetoothSupported(): boolean {
return typeof navigator.bluetooth?.requestDevice !== "undefined";
}
public static isSerialSupported(): boolean {
return typeof navigator.serial?.requestPort !== "undefined";
}
}
export class Validators {
public static u8ArraysEqual(a: Uint8Array, b: Uint8Array, message?: string): void {
if (!Utils.u8ArraysEqual(a, b)) {
throw new Error(message ?? "Arrays must be equal");
}
}
public static u8ArrayLengthEquals(a: Uint8Array, len: number, message?: string): void {
if (a.length !== len) {
throw new Error(message ?? `Array length must be ${len}`);
}
}
public static u8ArrayLengthAtLeast(a: Uint8Array, len: number, message?: string): void {
if (a.length < len) {
throw new Error(message ?? `Array length must be at least ${len}`);
}
}
}