Skip to content
This repository was archived by the owner on Mar 5, 2025. It is now read-only.

Commit d8b8e18

Browse files
mpetrunicMuhammad-AltabbaAlex
authored
fix: faster hex to byte implementation (#6596)
* faster hex to byte implementation Signed-off-by: Marin Petrunic <marin.petrunic@gmail.com> * Apply suggestions from code review Co-authored-by: Muhammad Altabba <24407834+Muhammad-Altabba@users.noreply.github.com> * fix tiny linting issue --------- Signed-off-by: Marin Petrunic <marin.petrunic@gmail.com> Co-authored-by: Muhammad Altabba <24407834+Muhammad-Altabba@users.noreply.github.com> Co-authored-by: Alex <alex.luu@mail.utoronto.ca>
1 parent be86e25 commit d8b8e18

File tree

1 file changed

+40
-11
lines changed

1 file changed

+40
-11
lines changed

packages/web3-validator/src/utils.ts

Lines changed: 40 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -449,20 +449,49 @@ export function uint8ArrayToHexString(uint8Array: Uint8Array): string {
449449
return hexString;
450450
}
451451

452+
// for optimized technique for hex to bytes conversion
453+
const charCodeMap = {
454+
zero: 48,
455+
nine: 57,
456+
A: 65,
457+
F: 70,
458+
a: 97,
459+
f: 102,
460+
} as const
461+
462+
function charCodeToBase16(char: number) {
463+
if (char >= charCodeMap.zero && char <= charCodeMap.nine)
464+
return char - charCodeMap.zero
465+
if (char >= charCodeMap.A && char <= charCodeMap.F)
466+
return char - (charCodeMap.A - 10)
467+
if (char >= charCodeMap.a && char <= charCodeMap.f)
468+
return char - (charCodeMap.a - 10)
469+
return undefined
470+
}
471+
452472
export function hexToUint8Array(hex: string): Uint8Array {
453-
let value;
454-
if (hex.toLowerCase().startsWith('0x')) {
455-
value = hex.slice(2);
456-
} else {
457-
value = hex;
473+
let offset = 0;
474+
if (hex.startsWith('0') && (hex[1] === 'x' || hex[1] === 'X')) {
475+
offset = 2;
458476
}
459-
if (value.length % 2 !== 0) {
477+
if (hex.length % 2 !== 0) {
460478
throw new InvalidBytesError(`hex string has odd length: ${hex}`);
461479
}
462-
const bytes = new Uint8Array(Math.ceil(value.length / 2));
463-
for (let i = 0; i < bytes.length; i += 1) {
464-
const byte = parseInt(value.substring(i * 2, i * 2 + 2), 16);
465-
bytes[i] = byte;
480+
const length = (hex.length - offset) / 2;
481+
const bytes = new Uint8Array(length);
482+
for (let index = 0, j = offset; index < length; index+=1) {
483+
// eslint-disable-next-line no-plusplus
484+
const nibbleLeft = charCodeToBase16(hex.charCodeAt(j++))
485+
// eslint-disable-next-line no-plusplus
486+
const nibbleRight = charCodeToBase16(hex.charCodeAt(j++))
487+
if (nibbleLeft === undefined || nibbleRight === undefined) {
488+
throw new InvalidBytesError(
489+
`Invalid byte sequence ("${hex[j - 2]}${
490+
hex[j - 1]
491+
}" in "${hex}").`,
492+
)
493+
}
494+
bytes[index] = nibbleLeft * 16 + nibbleRight
466495
}
467-
return bytes;
496+
return bytes
468497
}

0 commit comments

Comments
 (0)