Skip to content

Commit

Permalink
fix: faster hex to byte implementation (#6596)
Browse files Browse the repository at this point in the history
* 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>
  • Loading branch information
3 people authored Nov 20, 2023
1 parent be86e25 commit d8b8e18
Showing 1 changed file with 40 additions and 11 deletions.
51 changes: 40 additions & 11 deletions packages/web3-validator/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -449,20 +449,49 @@ export function uint8ArrayToHexString(uint8Array: Uint8Array): string {
return hexString;
}

// for optimized technique for hex to bytes conversion
const charCodeMap = {
zero: 48,
nine: 57,
A: 65,
F: 70,
a: 97,
f: 102,
} as const

function charCodeToBase16(char: number) {
if (char >= charCodeMap.zero && char <= charCodeMap.nine)
return char - charCodeMap.zero
if (char >= charCodeMap.A && char <= charCodeMap.F)
return char - (charCodeMap.A - 10)
if (char >= charCodeMap.a && char <= charCodeMap.f)
return char - (charCodeMap.a - 10)
return undefined
}

export function hexToUint8Array(hex: string): Uint8Array {
let value;
if (hex.toLowerCase().startsWith('0x')) {
value = hex.slice(2);
} else {
value = hex;
let offset = 0;
if (hex.startsWith('0') && (hex[1] === 'x' || hex[1] === 'X')) {
offset = 2;
}
if (value.length % 2 !== 0) {
if (hex.length % 2 !== 0) {
throw new InvalidBytesError(`hex string has odd length: ${hex}`);
}
const bytes = new Uint8Array(Math.ceil(value.length / 2));
for (let i = 0; i < bytes.length; i += 1) {
const byte = parseInt(value.substring(i * 2, i * 2 + 2), 16);
bytes[i] = byte;
const length = (hex.length - offset) / 2;
const bytes = new Uint8Array(length);
for (let index = 0, j = offset; index < length; index+=1) {
// eslint-disable-next-line no-plusplus
const nibbleLeft = charCodeToBase16(hex.charCodeAt(j++))
// eslint-disable-next-line no-plusplus
const nibbleRight = charCodeToBase16(hex.charCodeAt(j++))
if (nibbleLeft === undefined || nibbleRight === undefined) {
throw new InvalidBytesError(
`Invalid byte sequence ("${hex[j - 2]}${
hex[j - 1]
}" in "${hex}").`,
)
}
bytes[index] = nibbleLeft * 16 + nibbleRight
}
return bytes;
return bytes
}

0 comments on commit d8b8e18

Please sign in to comment.