Skip to content

Commit c5054eb

Browse files
util: optimize hexToBytes (#3203)
* util: optimize hexToBytes * util: also ensure unprefixedHexToBytes (so also toBytes for bigint) uses the optimizer --------- Co-authored-by: acolytec3 <[email protected]>
1 parent 4f908ca commit c5054eb

File tree

1 file changed

+30
-12
lines changed

1 file changed

+30
-12
lines changed

packages/util/src/bytes.ts

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
import { getRandomBytesSync } from 'ethereum-cryptography/random.js'
22
// eslint-disable-next-line no-restricted-imports
3-
import {
4-
bytesToHex as _bytesToUnprefixedHex,
5-
hexToBytes as _unprefixedHexToBytes,
6-
} from 'ethereum-cryptography/utils.js'
3+
import { bytesToHex as _bytesToUnprefixedHex } from 'ethereum-cryptography/utils.js'
74

85
import { assertIsArray, assertIsBytes, assertIsHexString } from './helpers.js'
96
import { isHexPrefixed, isHexString, padToEven, stripHexPrefix } from './internal.js'
@@ -17,6 +14,34 @@ const BIGINT_0 = BigInt(0)
1714
*/
1815
export const bytesToUnprefixedHex = _bytesToUnprefixedHex
1916

17+
// hexToBytes cache
18+
const hexToBytesMapFirstKey: { [key: string]: number } = {}
19+
const hexToBytesMapSecondKey: { [key: string]: number } = {}
20+
21+
for (let i = 0; i < 16; i++) {
22+
const vSecondKey = i
23+
const vFirstKey = i * 16
24+
const key = i.toString(16).toLowerCase()
25+
hexToBytesMapSecondKey[key] = vSecondKey
26+
hexToBytesMapSecondKey[key.toUpperCase()] = vSecondKey
27+
hexToBytesMapFirstKey[key] = vFirstKey
28+
hexToBytesMapFirstKey[key.toUpperCase()] = vFirstKey
29+
}
30+
31+
/**
32+
* NOTE: only use this function if the string is even, and only consists of hex characters
33+
* If this is not the case, this function could return weird results
34+
* @deprecated
35+
*/
36+
function _unprefixedHexToBytes(hex: string): Uint8Array {
37+
const byteLen = hex.length
38+
const bytes = new Uint8Array(byteLen / 2)
39+
for (let i = 0; i < byteLen; i += 2) {
40+
bytes[i / 2] = hexToBytesMapFirstKey[hex[i]] + hexToBytesMapSecondKey[hex[i + 1]]
41+
}
42+
return bytes
43+
}
44+
2045
/**
2146
* @deprecated
2247
*/
@@ -96,14 +121,7 @@ export const hexToBytes = (hex: string): Uint8Array => {
96121
if (hex.length % 2 !== 0) {
97122
hex = padToEven(hex)
98123
}
99-
100-
const byteLen = hex.length
101-
const bytes = new Uint8Array(byteLen / 2)
102-
for (let i = 0; i < byteLen; i += 2) {
103-
const byte = parseInt(hex.slice(i, i + 2), 16)
104-
bytes[i / 2] = byte
105-
}
106-
return bytes
124+
return _unprefixedHexToBytes(hex)
107125
}
108126

109127
/******************************************/

0 commit comments

Comments
 (0)