From f959d2995a2ee088a142d2073f415eeaa311b9c3 Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Mon, 25 Sep 2023 18:24:16 +0000 Subject: [PATCH] utils: optimize hexToBytes by 4% --- src/utils.ts | 40 ++++++++++++++++++---------------------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/src/utils.ts b/src/utils.ts index 8e92236..87609f6 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -37,21 +37,13 @@ export function bytesToHex(bytes: Uint8Array): string { return hex; } -// We use very optimized technique to convert hex string to byte array -const enum HexC { - ZERO = 48, // 0 - NINE = 57, // 9 - A_UP = 65, // A - F_UP = 70, // F - A_LO = 97, // a - F_LO = 102, // f -} - -function charCodeToBase16(char: number) { - if (char >= HexC.ZERO && char <= HexC.NINE) return char - HexC.ZERO; - else if (char >= HexC.A_UP && char <= HexC.F_UP) return char - (HexC.A_UP - 10); - else if (char >= HexC.A_LO && char <= HexC.F_LO) return char - (HexC.A_LO - 10); - throw new Error('Invalid byte sequence'); +// We use optimized technique to convert hex string to byte array +const asciis = { _0: 48, _9: 57, _A: 65, _F: 70, _a: 97, _f: 102 } as const; +function asciiToBase16(char: number): number | undefined { + if (char >= asciis._0 && char <= asciis._9) return char - asciis._0; + if (char >= asciis._A && char <= asciis._F) return char - (asciis._A - 10); + if (char >= asciis._a && char <= asciis._f) return char - (asciis._a - 10); + return; } /** @@ -59,14 +51,18 @@ function charCodeToBase16(char: number) { */ export function hexToBytes(hex: string): Uint8Array { if (typeof hex !== 'string') throw new Error('hex string expected, got ' + typeof hex); - const len = hex.length; - if (len % 2) throw new Error('padded hex string expected, got unpadded hex of length ' + len); - const al = len / 2; + const hl = hex.length; + const al = hl / 2; + if (hl % 2) throw new Error('padded hex string expected, got unpadded hex of length ' + hl); const array = new Uint8Array(al); - for (let i = 0, j = 0; i < al; i++) { - const n1 = charCodeToBase16(hex.charCodeAt(j++)); - const n2 = charCodeToBase16(hex.charCodeAt(j++)); - array[i] = n1 * 16 + n2; + for (let ai = 0, hi = 0; ai < al; ai++, hi += 2) { + const n1 = asciiToBase16(hex.charCodeAt(hi)); + const n2 = asciiToBase16(hex.charCodeAt(hi + 1)); + if (n1 === undefined || n2 === undefined) { + const char = hex[hi] + hex[hi + 1]; + throw new Error('hex string expected, got non-hex character "' + char + '" at index ' + hi); + } + array[ai] = n1 * 16 + n2; } return array; }