From 15390e8356497b7e6b622e3009060c2a144a671e Mon Sep 17 00:00:00 2001 From: Chris Duncan Date: Mon, 29 Jun 2026 14:59:31 -0700 Subject: [PATCH] Extract conversion functions into dedicated directory. --- src/lib/convert.ts | 362 -------------------------------------- src/lib/convert/base32.ts | 53 ++++++ src/lib/convert/bin.ts | 20 +++ src/lib/convert/bytes.ts | 105 +++++++++++ src/lib/convert/dec.ts | 74 ++++++++ src/lib/convert/hex.ts | 62 +++++++ src/lib/convert/index.ts | 21 +++ src/lib/convert/obj.ts | 18 ++ src/lib/convert/utf8.ts | 38 ++++ 9 files changed, 391 insertions(+), 362 deletions(-) delete mode 100644 src/lib/convert.ts create mode 100644 src/lib/convert/base32.ts create mode 100644 src/lib/convert/bin.ts create mode 100644 src/lib/convert/bytes.ts create mode 100644 src/lib/convert/dec.ts create mode 100644 src/lib/convert/hex.ts create mode 100644 src/lib/convert/index.ts create mode 100644 src/lib/convert/obj.ts create mode 100644 src/lib/convert/utf8.ts diff --git a/src/lib/convert.ts b/src/lib/convert.ts deleted file mode 100644 index 801f96e..0000000 --- a/src/lib/convert.ts +++ /dev/null @@ -1,362 +0,0 @@ -//! SPDX-FileCopyrightText: 2025 Chris Duncan -//! SPDX-License-Identifier: GPL-3.0-or-later - -import { ALPHABET } from './constants' - -export class base32 { - /** - * Convert a base32 string to a Uint8Array of bytes. - * - * @param {string} base32 - String to convert - * @returns {Uint8Array} Byte array representation of the input string - */ - static toBytes (base32: string): Uint8Array { - const leftover = (base32.length * 5) % 8 - const offset = leftover === 0 - ? 0 - : 8 - leftover - let bits = 0 - let value = 0 - let letter = -1 - let index = 0 - let output = new Uint8Array(Math.ceil((base32.length * 5) / 8)) - for (let i = 0; i < base32.length; i++) { - letter = ALPHABET.indexOf(base32[i]) - if (letter < 0) { - throw new RangeError('Invalid base32 character', { cause: base32[i] }) - } - value = (value << 5) | letter - bits += 5 - if (bits >= 8) { - output[index++] = (value >>> (bits + offset - 8)) & 255 - bits -= 8 - } - } - if (bits > 0) { - output[index++] = (value << (bits + offset - 8)) & 255 - } - if (leftover !== 0) { - output = output.slice(1) - } - return output - } - - /** - * Convert a base32 string to an ArrayBuffer. - * - * @param {string} base32 - String to convert - * @returns {Uint8Array} Byte array representation of the input string - */ - static toBuffer (base32: string): ArrayBuffer { - return this.toBytes(base32).buffer - } -} - -export class bin { - /** - * Convert a binary string to a Uint8Array of bytes. - * - * @param {string} bin - String to convert - * @returns {Uint8Array} Byte array representation of the input string - */ - static toBytes (bin: string): Uint8Array { - const bytes: number[] = [] - while (bin.length > 0) { - const bits = bin.substring(0, 8) - bytes.push(parseInt(bits, 2)) - bin = bin.substring(8) - } - return new Uint8Array(bytes) - } -} - -export class bytes { - static decoder: TextDecoder = new TextDecoder() - - /** - * Write zeroes to memory to erase bytes and then transfers the buffer to - * render it inaccessible to any process. - * - * @param bytes - Buffer or bytes to erase - */ - static erase (bytes?: ArrayBuffer | Uint8Array | null): void { - if (bytes == null) return - if (bytes instanceof ArrayBuffer && bytes.byteLength === 0) return - if (bytes instanceof Uint8Array && bytes.buffer.byteLength === 0) return - bytes = bytes instanceof ArrayBuffer ? new Uint8Array(bytes) : bytes - bytes.fill(0) - } - - /** - * Convert a Uint8Aarray of bytes to a base32 string. - * - * @param {Uint8Array} bytes - Byte array to convert - * @returns {string} Base32 string representation of the input bytes - */ - static toBase32 (bytes: ArrayBuffer | Uint8Array): string { - if (bytes instanceof ArrayBuffer) bytes = new Uint8Array(bytes) - const leftover = (bytes.length * 8) % 5 - const offset = leftover === 0 - ? 0 - : 5 - leftover - let value = 0 - let output = '' - let bits = 0 - for (let i = 0; i < bytes.length; i++) { - value = (value << 8) | bytes[i] - bits += 8 - while (bits >= 5) { - output += ALPHABET[(value >>> (bits + offset - 5)) & 31] - bits -= 5 - } - } - if (bits > 0) { - output += ALPHABET[(value << (5 - (bits + offset))) & 31] - } - return output - } - - /** - * Convert a Uint8Array of bytes to a binary string. - * - * @param {Uint8Array} bytes - Byte array to convert - * @returns {string} Binary string representation of the input value - */ - static toBin (bytes: Uint8Array): string { - return [...bytes].map(b => b.toString(2).padStart(8, '0')).join('') - } - - /** - * Sum an array of bytes to a decimal integer. If the result is larger than - * Number.MAX_SAFE_INTEGER, it will be returned as a bigint. - * - * @param {Uint8Array} bytes - Byte array to convert - * @returns {bigint|number} Decimal sum of the literal byte values - */ - static toDec (bytes: Uint8Array): bigint | number { - let decimal = 0n - for (let i = bytes.byteLength; i > 0; i--) { - decimal += BigInt(bytes[i - 1]) << (BigInt(bytes.byteLength - i) * 8n) - } - if (decimal > 9007199254740991n) { - return decimal - } else { - return Number(decimal) - } - } - - /** - * Convert a Uint8Array of bytes to a hexadecimal string. - * - * @param {Uint8Array} bytes - Byte array to convert - * @returns {string} Hexadecimal string representation of the input bytes - */ - static toHex (bytes: ArrayBuffer | Uint8Array): string { - if (bytes instanceof ArrayBuffer) bytes = new Uint8Array(bytes) - if (bytes.buffer instanceof ArrayBuffer && bytes.buffer.byteLength === 0) return '' - return [...bytes] - .map(byte => byte.toString(16).padStart(2, '0')) - .join('') - .toUpperCase() - } - - /** - * Convert a Uint8Array of bytes to a UTF-8 text string. - * - * @param {Uint8Array} bytes - Byte array to convert - * @returns {string} UTF-8 encoded text string - */ - static toUtf8 (bytes: Uint8Array): string { - return this.decoder.decode(bytes) - } -} - -export class dec { - /** - * Convert a decimal integer to a binary string. - * - * @param {bigint|number|string} decimal - Integer to convert - * @param {number} [padding=0] - Minimum length of the resulting string padded as necessary with starting zeroes - * @returns {string} Binary string representation of the input decimal - */ - static toBin (decimal: bigint | number | string, padding: number = 0): string { - if (typeof padding !== 'number') { - throw new TypeError('Invalid padding') - } - try { - return BigInt(decimal) - .toString(2) - .padStart(padding, '0') - } catch (err) { - throw new RangeError('Invalid decimal integer') - } - } - - /** - * Convert a decimal integer to a Uint8Array of bytes. Fractional part is truncated. - * - * @param {bigint|number|string} decimal - Integer to convert - * @param {number} [padding=0] - Minimum length of the resulting array padded as necessary with starting 0x00 bytes - * @returns {Uint8Array} Byte array representation of the input decimal - */ - static toBytes (decimal: bigint | number | string, padding: number = 0): Uint8Array { - if (decimal == null) { - throw new TypeError(`Failed to convert '${decimal}' from decimal to bytes`) - } - if (typeof padding !== 'number') { - throw new TypeError('Invalid padding') - } - let integer = BigInt(decimal) - const bytes: number[] = (integer === 0n) ? [0] : [] - while (integer > 0) { - const lsb = BigInt.asUintN(8, integer) - bytes.push(Number(lsb)) - integer >>= 8n - } - const result = new Uint8Array(Math.max(padding, bytes.length)) - result.set(bytes) - return (result.reverse()) - } - - /** - * Convert a decimal integer to a hexadecimal string. - * - * @param {(bigint|number|string)} decimal - Integer to convert - * @param {number} [padding=0] - Minimum length of the resulting string padded as necessary with starting zeroes - * @returns {string} Hexadecimal string representation of the input decimal - */ - static toHex (decimal: bigint | number | string, padding: number = 0): string { - if (decimal == null) { - throw new TypeError(`Failed to convert '${decimal}' from decimal to hex`) - } - if (typeof padding !== 'number') { - throw new TypeError('Invalid padding') - } - try { - return BigInt(decimal) - .toString(16) - .padStart(padding, '0') - .toUpperCase() - } catch (err) { - throw new RangeError('Invalid decimal integer') - } - } -} - -export class hex { - /** - * Convert a hexadecimal string to an array of decimal byte values. - * - * @param {string} hex - Hexadecimal number string to convert - * @param {number}[padding=0] - Minimum length of the resulting array padded as necessary with starting 0 values - * @returns {number[]} Decimal array representation of the input value - */ - static toArray (hex: string, padding: number = 0): number[] { - if (typeof hex !== 'string' || !/^[A-Fa-f0-9]+$/i.test(hex)) { - throw new TypeError('Invalid string when converting hex to array', { cause: hex }) - } - if (typeof padding !== 'number') { - throw new TypeError('Invalid padding when converting hex to array', { cause: padding }) - } - if ((hex.length & 1) !== 0) hex = `0${hex}` - const hexArray = hex.match(/.{2}/g) - if (hexArray == null) { - throw new RangeError('Invalid hex string when converting to array', { cause: hexArray }) - } - const diff = padding - hexArray.length - const pad = new Array(diff > 0 ? diff : 0).fill(0) - return pad.concat(hexArray.map(v => parseInt(v, 16))) - } - - /** - * Convert a hexadecimal string to a binary string. - * - * @param {string} hex - Hexadecimal number string to convert - * @returns {string} Binary string representation of the input value - */ - static toBin (hex: string): string { - return [...hex].map(c => dec.toBin(parseInt(c, 16), 4)).join('') - } - - /** - * Convert a hexadecimal string to an ArrayBuffer. - * - * @param {string} hex - Hexadecimal number string to convert - * @param {number} [padding=0] - Minimum length of the resulting array padded as necessary with starting 0x00 bytes - * @returns {ArrayBuffer} Buffer representation of the input value - */ - static toBuffer (hex: string, padding: number = 0): ArrayBuffer { - return this.toBytes(hex, padding).buffer - } - - /** - * Convert a hexadecimal string to a Uint8Array of bytes. - * - * @param {string} hex - Hexadecimal number string to convert - * @param {number} [padding=0] - Minimum length of the resulting array padded as necessary with starting 0x00 bytes - * @returns {Uint8Array} Byte array representation of the input value - */ - static toBytes (hex: string, padding: number = 0): Uint8Array { - return new Uint8Array(this.toArray(hex, padding)) - } -} - -export class obj { - /** - * Convert a numerically-indexed object of 8-bit values to a Uint8Array of bytes. - * - * @param {object} obj - Object to convert - * @returns {Uint8Array} Byte array representation of the input object - */ - static toBytes (obj: { [key: number]: number }): Uint8Array { - const values = Object.keys(obj) - .map(key => +key) - .sort((a, b) => a - b) - .map(i => obj[i]) - return new Uint8Array(values) - } -} - -export class utf8 { - static encoder: TextEncoder = new TextEncoder() - - /** - * Convert a UTF-8 text string to an ArrayBuffer. - * - * @param {string} utf8 - String to convert - * @returns {ArrayBuffer} Buffer representation of the input string - */ - static toBuffer (utf8: string): ArrayBuffer { - return this.toBytes(utf8).buffer - } - - /** - * Convert a UTF-8 text string to a Uint8Array of bytes. - * - * @param {string} utf8 - String to convert - * @returns {Uint8Array} Byte array representation of the input string - */ - static toBytes (utf8: string): Uint8Array { - return this.encoder.encode(utf8) as Uint8Array - } - - /** - * Convert a string to a hexadecimal representation - * - * @param {string} utf8 - String to convert - * @returns {string} Hexadecimal representation of the input string - */ - static toHex (utf8: string): string { - return bytes.toHex(this.toBytes(utf8)) - } -} - -export default ` - const base32 = ${base32} - const bin = ${bin} - const bytes = ${bytes} - const dec = ${dec} - const hex = ${hex} - const obj = ${obj} - const utf8 = ${utf8} -` diff --git a/src/lib/convert/base32.ts b/src/lib/convert/base32.ts new file mode 100644 index 0000000..93cb99c --- /dev/null +++ b/src/lib/convert/base32.ts @@ -0,0 +1,53 @@ +//! SPDX-FileCopyrightText: 2025 Chris Duncan +//! SPDX-License-Identifier: GPL-3.0-or-later + +import { ALPHABET } from '../constants' + +export class base32 { + /** + * Convert a base32 string to a Uint8Array of bytes. + * + * @param {string} base32 - String to convert + * @returns {Uint8Array} Byte array representation of the input string + */ + static toBytes (base32: string): Uint8Array { + const leftover = (base32.length * 5) % 8 + const offset = leftover === 0 + ? 0 + : 8 - leftover + let bits = 0 + let value = 0 + let letter = -1 + let index = 0 + let output = new Uint8Array(Math.ceil((base32.length * 5) / 8)) + for (let i = 0; i < base32.length; i++) { + letter = ALPHABET.indexOf(base32[i]) + if (letter < 0) { + throw new RangeError('Invalid base32 character', { cause: base32[i] }) + } + value = (value << 5) | letter + bits += 5 + if (bits >= 8) { + output[index++] = (value >>> (bits + offset - 8)) & 255 + bits -= 8 + } + } + if (bits > 0) { + output[index++] = (value << (bits + offset - 8)) & 255 + } + if (leftover !== 0) { + output = output.slice(1) + } + return output + } + + /** + * Convert a base32 string to an ArrayBuffer. + * + * @param {string} base32 - String to convert + * @returns {Uint8Array} Byte array representation of the input string + */ + static toBuffer (base32: string): ArrayBuffer { + return this.toBytes(base32).buffer + } +} diff --git a/src/lib/convert/bin.ts b/src/lib/convert/bin.ts new file mode 100644 index 0000000..548d7e3 --- /dev/null +++ b/src/lib/convert/bin.ts @@ -0,0 +1,20 @@ +//! SPDX-FileCopyrightText: 2025 Chris Duncan +//! SPDX-License-Identifier: GPL-3.0-or-later + +export class bin { + /** + * Convert a binary string to a Uint8Array of bytes. + * + * @param {string} bin - String to convert + * @returns {Uint8Array} Byte array representation of the input string + */ + static toBytes (bin: string): Uint8Array { + const bytes: number[] = [] + while (bin.length > 0) { + const bits = bin.substring(0, 8) + bytes.push(parseInt(bits, 2)) + bin = bin.substring(8) + } + return new Uint8Array(bytes) + } +} diff --git a/src/lib/convert/bytes.ts b/src/lib/convert/bytes.ts new file mode 100644 index 0000000..fe63fc1 --- /dev/null +++ b/src/lib/convert/bytes.ts @@ -0,0 +1,105 @@ +//! SPDX-FileCopyrightText: 2025 Chris Duncan +//! SPDX-License-Identifier: GPL-3.0-or-later + +import { ALPHABET } from '../constants' + +export class bytes { + static decoder: TextDecoder = new TextDecoder() + + /** + * Write zeroes to memory to erase bytes and then transfers the buffer to + * render it inaccessible to any process. + * + * @param bytes - Buffer or bytes to erase + */ + static erase (bytes?: ArrayBuffer | Uint8Array | null): void { + if (bytes == null) return + if (bytes instanceof ArrayBuffer && bytes.byteLength === 0) return + if (bytes instanceof Uint8Array && bytes.buffer.byteLength === 0) return + bytes = bytes instanceof ArrayBuffer ? new Uint8Array(bytes) : bytes + bytes.fill(0) + } + + /** + * Convert a Uint8Aarray of bytes to a base32 string. + * + * @param {Uint8Array} bytes - Byte array to convert + * @returns {string} Base32 string representation of the input bytes + */ + static toBase32 (bytes: ArrayBuffer | Uint8Array): string { + if (bytes instanceof ArrayBuffer) bytes = new Uint8Array(bytes) + const leftover = (bytes.length * 8) % 5 + const offset = leftover === 0 + ? 0 + : 5 - leftover + let value = 0 + let output = '' + let bits = 0 + for (let i = 0; i < bytes.length; i++) { + value = (value << 8) | bytes[i] + bits += 8 + while (bits >= 5) { + output += ALPHABET[(value >>> (bits + offset - 5)) & 31] + bits -= 5 + } + } + if (bits > 0) { + output += ALPHABET[(value << (5 - (bits + offset))) & 31] + } + return output + } + + /** + * Convert a Uint8Array of bytes to a binary string. + * + * @param {Uint8Array} bytes - Byte array to convert + * @returns {string} Binary string representation of the input value + */ + static toBin (bytes: Uint8Array): string { + return [...bytes].map(b => b.toString(2).padStart(8, '0')).join('') + } + + /** + * Sum an array of bytes to a decimal integer. If the result is larger than + * Number.MAX_SAFE_INTEGER, it will be returned as a bigint. + * + * @param {Uint8Array} bytes - Byte array to convert + * @returns {bigint|number} Decimal sum of the literal byte values + */ + static toDec (bytes: Uint8Array): bigint | number { + let decimal = 0n + for (let i = bytes.byteLength; i > 0; i--) { + decimal += BigInt(bytes[i - 1]) << (BigInt(bytes.byteLength - i) * 8n) + } + if (decimal > 9007199254740991n) { + return decimal + } else { + return Number(decimal) + } + } + + /** + * Convert a Uint8Array of bytes to a hexadecimal string. + * + * @param {Uint8Array} bytes - Byte array to convert + * @returns {string} Hexadecimal string representation of the input bytes + */ + static toHex (bytes: ArrayBuffer | Uint8Array): string { + if (bytes instanceof ArrayBuffer) bytes = new Uint8Array(bytes) + if (bytes.buffer instanceof ArrayBuffer && bytes.buffer.byteLength === 0) return '' + return [...bytes] + .map(byte => byte.toString(16).padStart(2, '0')) + .join('') + .toUpperCase() + } + + /** + * Convert a Uint8Array of bytes to a UTF-8 text string. + * + * @param {Uint8Array} bytes - Byte array to convert + * @returns {string} UTF-8 encoded text string + */ + static toUtf8 (bytes: Uint8Array): string { + return this.decoder.decode(bytes) + } +} diff --git a/src/lib/convert/dec.ts b/src/lib/convert/dec.ts new file mode 100644 index 0000000..15016cf --- /dev/null +++ b/src/lib/convert/dec.ts @@ -0,0 +1,74 @@ +//! SPDX-FileCopyrightText: 2025 Chris Duncan +//! SPDX-License-Identifier: GPL-3.0-or-later + +export class dec { + /** + * Convert a decimal integer to a binary string. + * + * @param {bigint|number|string} decimal - Integer to convert + * @param {number} [padding=0] - Minimum length of the resulting string padded as necessary with starting zeroes + * @returns {string} Binary string representation of the input decimal + */ + static toBin (decimal: bigint | number | string, padding: number = 0): string { + if (typeof padding !== 'number') { + throw new TypeError('Invalid padding') + } + try { + return BigInt(decimal) + .toString(2) + .padStart(padding, '0') + } catch (err) { + throw new RangeError('Invalid decimal integer') + } + } + + /** + * Convert a decimal integer to a Uint8Array of bytes. Fractional part is truncated. + * + * @param {bigint|number|string} decimal - Integer to convert + * @param {number} [padding=0] - Minimum length of the resulting array padded as necessary with starting 0x00 bytes + * @returns {Uint8Array} Byte array representation of the input decimal + */ + static toBytes (decimal: bigint | number | string, padding: number = 0): Uint8Array { + if (decimal == null) { + throw new TypeError(`Failed to convert '${decimal}' from decimal to bytes`) + } + if (typeof padding !== 'number') { + throw new TypeError('Invalid padding') + } + let integer = BigInt(decimal) + const bytes: number[] = (integer === 0n) ? [0] : [] + while (integer > 0) { + const lsb = BigInt.asUintN(8, integer) + bytes.push(Number(lsb)) + integer >>= 8n + } + const result = new Uint8Array(Math.max(padding, bytes.length)) + result.set(bytes) + return (result.reverse()) + } + + /** + * Convert a decimal integer to a hexadecimal string. + * + * @param {(bigint|number|string)} decimal - Integer to convert + * @param {number} [padding=0] - Minimum length of the resulting string padded as necessary with starting zeroes + * @returns {string} Hexadecimal string representation of the input decimal + */ + static toHex (decimal: bigint | number | string, padding: number = 0): string { + if (decimal == null) { + throw new TypeError(`Failed to convert '${decimal}' from decimal to hex`) + } + if (typeof padding !== 'number') { + throw new TypeError('Invalid padding') + } + try { + return BigInt(decimal) + .toString(16) + .padStart(padding, '0') + .toUpperCase() + } catch (err) { + throw new RangeError('Invalid decimal integer') + } + } +} diff --git a/src/lib/convert/hex.ts b/src/lib/convert/hex.ts new file mode 100644 index 0000000..adb072d --- /dev/null +++ b/src/lib/convert/hex.ts @@ -0,0 +1,62 @@ +//! SPDX-FileCopyrightText: 2025 Chris Duncan +//! SPDX-License-Identifier: GPL-3.0-or-later + +import { dec } from './dec' + +export class hex { + /** + * Convert a hexadecimal string to an array of decimal byte values. + * + * @param {string} hex - Hexadecimal number string to convert + * @param {number}[padding=0] - Minimum length of the resulting array padded as necessary with starting 0 values + * @returns {number[]} Decimal array representation of the input value + */ + static toArray (hex: string, padding: number = 0): number[] { + if (typeof hex !== 'string' || !/^[A-Fa-f0-9]+$/i.test(hex)) { + throw new TypeError('Invalid string when converting hex to array', { cause: hex }) + } + if (typeof padding !== 'number') { + throw new TypeError('Invalid padding when converting hex to array', { cause: padding }) + } + if ((hex.length & 1) !== 0) hex = `0${hex}` + const hexArray = hex.match(/.{2}/g) + if (hexArray == null) { + throw new RangeError('Invalid hex string when converting to array', { cause: hexArray }) + } + const diff = padding - hexArray.length + const pad = new Array(diff > 0 ? diff : 0).fill(0) + return pad.concat(hexArray.map(v => parseInt(v, 16))) + } + + /** + * Convert a hexadecimal string to a binary string. + * + * @param {string} hex - Hexadecimal number string to convert + * @returns {string} Binary string representation of the input value + */ + static toBin (hex: string): string { + return [...hex].map(c => dec.toBin(parseInt(c, 16), 4)).join('') + } + + /** + * Convert a hexadecimal string to an ArrayBuffer. + * + * @param {string} hex - Hexadecimal number string to convert + * @param {number} [padding=0] - Minimum length of the resulting array padded as necessary with starting 0x00 bytes + * @returns {ArrayBuffer} Buffer representation of the input value + */ + static toBuffer (hex: string, padding: number = 0): ArrayBuffer { + return this.toBytes(hex, padding).buffer + } + + /** + * Convert a hexadecimal string to a Uint8Array of bytes. + * + * @param {string} hex - Hexadecimal number string to convert + * @param {number} [padding=0] - Minimum length of the resulting array padded as necessary with starting 0x00 bytes + * @returns {Uint8Array} Byte array representation of the input value + */ + static toBytes (hex: string, padding: number = 0): Uint8Array { + return new Uint8Array(this.toArray(hex, padding)) + } +} diff --git a/src/lib/convert/index.ts b/src/lib/convert/index.ts new file mode 100644 index 0000000..32f761a --- /dev/null +++ b/src/lib/convert/index.ts @@ -0,0 +1,21 @@ +//! SPDX-FileCopyrightText: 2025 Chris Duncan +//! SPDX-License-Identifier: GPL-3.0-or-later + +import { base32 } from './base32' +import { bin } from './bin' +import { bytes } from './bytes' +import { dec } from './dec' +import { hex } from './hex' +import { obj } from './obj' +import { utf8 } from './utf8' + +export { base32, bin, bytes, dec, hex, obj, utf8 } +export default ` + const base32 = ${base32} + const bin = ${bin} + const bytes = ${bytes} + const dec = ${dec} + const hex = ${hex} + const obj = ${obj} + const utf8 = ${utf8} +` diff --git a/src/lib/convert/obj.ts b/src/lib/convert/obj.ts new file mode 100644 index 0000000..55cb994 --- /dev/null +++ b/src/lib/convert/obj.ts @@ -0,0 +1,18 @@ +//! SPDX-FileCopyrightText: 2025 Chris Duncan +//! SPDX-License-Identifier: GPL-3.0-or-later + +export class obj { + /** + * Convert a numerically-indexed object of 8-bit values to a Uint8Array of bytes. + * + * @param {object} obj - Object to convert + * @returns {Uint8Array} Byte array representation of the input object + */ + static toBytes (obj: { [key: number]: number }): Uint8Array { + const values = Object.keys(obj) + .map(key => +key) + .sort((a, b) => a - b) + .map(i => obj[i]) + return new Uint8Array(values) + } +} diff --git a/src/lib/convert/utf8.ts b/src/lib/convert/utf8.ts new file mode 100644 index 0000000..6c40c2b --- /dev/null +++ b/src/lib/convert/utf8.ts @@ -0,0 +1,38 @@ +//! SPDX-FileCopyrightText: 2025 Chris Duncan +//! SPDX-License-Identifier: GPL-3.0-or-later + +import { bytes } from './bytes' + +export class utf8 { + static encoder: TextEncoder = new TextEncoder() + + /** + * Convert a UTF-8 text string to an ArrayBuffer. + * + * @param {string} utf8 - String to convert + * @returns {ArrayBuffer} Buffer representation of the input string + */ + static toBuffer (utf8: string): ArrayBuffer { + return this.toBytes(utf8).buffer + } + + /** + * Convert a UTF-8 text string to a Uint8Array of bytes. + * + * @param {string} utf8 - String to convert + * @returns {Uint8Array} Byte array representation of the input string + */ + static toBytes (utf8: string): Uint8Array { + return this.encoder.encode(utf8) as Uint8Array + } + + /** + * Convert a string to a hexadecimal representation + * + * @param {string} utf8 - String to convert + * @returns {string} Hexadecimal representation of the input string + */ + static toHex (utf8: string): string { + return bytes.toHex(this.toBytes(utf8)) + } +} -- 2.52.0