From 7cfdc88ba19790008d22ea4379e10cbfe1a31b56 Mon Sep 17 00:00:00 2001 From: Chris Duncan Date: Tue, 30 Jun 2026 13:53:19 -0700 Subject: [PATCH] Refactor hex converter to merge array with byte converter, fix minimum padding, limit max size, and deprecate unused bin conversion. --- src/lib/convert/hex.ts | 65 +++++++++++++++--------------------------- 1 file changed, 23 insertions(+), 42 deletions(-) diff --git a/src/lib/convert/hex.ts b/src/lib/convert/hex.ts index 43be081..b356de4 100644 --- a/src/lib/convert/hex.ts +++ b/src/lib/convert/hex.ts @@ -1,62 +1,43 @@ //! SPDX-FileCopyrightText: 2025 Chris Duncan //! SPDX-License-Identifier: GPL-3.0-or-later -import { dec } from './dec' - export const hex = Object.freeze({ - /** - * 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 - */ - 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 - */ - 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 + * @param {number} [padding=1] - Minimum length of the resulting array padded as necessary with starting 0x00 bytes * @returns {ArrayBuffer} Buffer representation of the input value */ - toBuffer (hex: string, padding: number = 0): ArrayBuffer { + toBuffer (hex: string, padding: number = 1): ArrayBuffer { return this.toBytes(hex, padding).buffer }, /** - * Convert a hexadecimal string to a Uint8Array of bytes. + * Convert a hexadecimal string to a Uint8Array of bytes. The result must be + * at least one byte and no more than 4 GiB. * * @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 + * @param {number} [padding=1] - Minimum length of the resulting array padded as necessary with starting 0x00 bytes * @returns {Uint8Array} Byte array representation of the input value */ - toBytes (hex: string, padding: number = 0): Uint8Array { - return new Uint8Array(this.toArray(hex, padding)) + toBytes (hex: string, padding: number = 1): Uint8Array { + if (typeof hex !== 'string' || !/^[0-9a-f]+$/i.test(hex)) { + throw new TypeError('Invalid string when converting hex to array', { cause: hex }) + } + if (typeof padding !== 'number' || padding < 1 || padding > 0xffffffff) { + throw new TypeError('Invalid padding when converting hex to array', { cause: padding }) + } + if (hex.length & 1) 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 offset = diff & ~(diff >> 31) + const length = hexArray.length + offset + const bytes = new Uint8Array(length) + bytes.set(hex.match(/.{2}/g)?.map(b => parseInt(b, 16)) ?? [], offset) + return bytes }, }) -- 2.52.0