1- import { cachedTextDecoder } from "../text-decoder.js" ;
2- import { cachedTextEncoder } from "../text-encoder.js" ;
3- // slightly tweaked re-exports from viem for the moment
4- import { assertSize } from "./helpers/assert-size.js" ;
5- import { charCodeToBase16 } from "./helpers/charcode-to-base-16.js" ;
1+ import { Hex as ox__Hex } from "ox" ;
62import type { Hex } from "./helpers/is-hex.js" ;
73
84export { type Hex , isHex , type IsHexOptions } from "./helpers/is-hex.js" ;
95
10- type TrimOptions = {
11- dir ?: "left" | "right" ;
12- } ;
13- type TrimReturnType < TValue extends Uint8Array | Hex > = TValue extends Hex
14- ? Hex
15- : Uint8Array ;
16-
17- function trim < TValue extends Uint8Array | Hex > (
18- hexOrBytes : TValue ,
19- options : TrimOptions = { } ,
20- ) : TrimReturnType < TValue > {
21- const dir = options . dir || "left" ;
22- // biome-ignore lint/suspicious/noExplicitAny: TODO: fix any
23- let data : any =
24- typeof hexOrBytes === "string" ? hexOrBytes . replace ( "0x" , "" ) : hexOrBytes ;
25-
26- let sliceLength = 0 ;
27- for ( let i = 0 ; i < data . length - 1 ; i ++ ) {
28- if ( data [ dir === "left" ? i : data . length - i - 1 ] . toString ( ) === "0" ) {
29- sliceLength ++ ;
30- } else {
31- break ;
32- }
33- }
34- data =
35- dir === "left"
36- ? data . slice ( sliceLength )
37- : data . slice ( 0 , data . length - sliceLength ) ;
38-
39- if ( typeof hexOrBytes === "string" ) {
40- if ( data . length === 1 && dir === "right" ) {
41- data = `${ data } 0` ;
42- }
43- return `0x${
44- data . length % 2 === 1 ? `0${ data } ` : data
45- } ` as TrimReturnType < TValue > ;
46- }
47- return data as TrimReturnType < TValue > ;
48- }
49-
506type PadOptions = {
517 dir ?: "left" | "right" ;
528 size ?: number | null ;
@@ -71,25 +27,17 @@ export function padHex(hex_: Hex, options: PadOptions = {}) {
7127 if ( size === null ) {
7228 return hex_ ;
7329 }
74- const hex = hex_ . replace ( "0x" , "" ) ;
75- if ( hex . length > size * 2 ) {
76- throw new Error ( `Size overflow: ${ Math . ceil ( hex . length / 2 ) } > ${ size } ` ) ;
30+ if ( dir === "left" ) {
31+ return ox__Hex . padLeft ( hex_ , size ) ;
7732 }
78-
79- return `0x${ hex [ dir === "right" ? "padEnd" : "padStart" ] (
80- size * 2 ,
81- "0" ,
82- ) } ` as Hex ;
33+ return ox__Hex . padRight ( hex_ , size ) ;
8334}
8435
8536//--------------------------------------------------------------------------
8637// FROM HEX
8738//--------------------------------------------------------------------------
8839
89- export type HexToStringOpts = {
90- /** Size (in bytes) of the hex value. */
91- size ?: number ;
92- } ;
40+ export type HexToStringOpts = ox__Hex . toString . Options ;
9341
9442/**
9543 * Converts a hexadecimal string to a UTF-8 string.
@@ -105,20 +53,10 @@ export type HexToStringOpts = {
10553 * @utils
10654 */
10755export function hexToString ( hex : Hex , opts : HexToStringOpts = { } ) : string {
108- let bytes = hexToUint8Array ( hex ) ;
109- if ( opts . size ) {
110- assertSize ( bytes , { size : opts . size } ) ;
111- bytes = trim ( bytes , { dir : "right" } ) ;
112- }
113- return cachedTextDecoder ( ) . decode ( bytes ) ;
56+ return ox__Hex . toString ( hex , opts ) ;
11457}
11558
116- export type HexToBigIntOpts = {
117- /** Whether or not the number of a signed representation. */
118- signed ?: boolean ;
119- /** Size (in bytes) of the hex value. */
120- size ?: number ;
121- } ;
59+ export type HexToBigIntOpts = ox__Hex . toBigInt . Options ;
12260
12361/**
12462 * Converts a hexadecimal string to a BigInt.
@@ -134,24 +72,7 @@ export type HexToBigIntOpts = {
13472 * @utils
13573 */
13674export function hexToBigInt ( hex : Hex , opts : HexToBigIntOpts = { } ) : bigint {
137- const { signed } = opts ;
138-
139- if ( opts . size ) {
140- assertSize ( hex , { size : opts . size } ) ;
141- }
142-
143- const value = BigInt ( hex ) ;
144- if ( ! signed ) {
145- return value ;
146- }
147-
148- const size = ( hex . length - 2 ) / 2 ;
149- const max = ( 1n << ( BigInt ( size ) * 8n - 1n ) ) - 1n ;
150- if ( value <= max ) {
151- return value ;
152- }
153-
154- return value - BigInt ( `0x${ "f" . padStart ( size * 2 , "f" ) } ` ) - 1n ;
75+ return ox__Hex . toBigInt ( hex , opts ) ;
15576}
15677
15778export type HexToNumberOpts = HexToBigIntOpts ;
@@ -169,13 +90,10 @@ export type HexToNumberOpts = HexToBigIntOpts;
16990 * @utils
17091 */
17192export function hexToNumber ( hex : Hex , opts : HexToNumberOpts = { } ) : number {
172- return Number ( hexToBigInt ( hex , opts ) ) ;
93+ return ox__Hex . toNumber ( hex , opts ) ;
17394}
17495
175- export type HexToBoolOpts = {
176- /** Size (in bytes) of the hex value. */
177- size ?: number ;
178- } ;
96+ export type HexToBoolOpts = ox__Hex . toBoolean . Options ;
17997
18098/**
18199 * Converts a hexadecimal string to a boolean value.
@@ -192,24 +110,10 @@ export type HexToBoolOpts = {
192110 * @utils
193111 */
194112export function hexToBool ( hex : Hex , opts : HexToBoolOpts = { } ) : boolean {
195- if ( opts . size ) {
196- assertSize ( hex , { size : opts . size } ) ;
197- // biome-ignore lint/style/noParameterAssign: for perf
198- hex = trim ( hex ) ;
199- }
200- if ( trim ( hex ) === "0x00" ) {
201- return false ;
202- }
203- if ( trim ( hex ) === "0x01" ) {
204- return true ;
205- }
206- throw new Error ( `Invalid hex boolean: ${ hex } ` ) ;
113+ return ox__Hex . toBoolean ( hex , opts ) ;
207114}
208115
209- export type HexToUint8ArrayOpts = {
210- /** Size of the output bytes. */
211- size ?: number ;
212- } ;
116+ export type HexToUint8ArrayOpts = ox__Hex . toBytes . Options ;
213117
214118/**
215119 * Converts a hexadecimal string to a Uint8Array.
@@ -228,28 +132,7 @@ export function hexToUint8Array(
228132 hex : Hex ,
229133 opts : HexToUint8ArrayOpts = { } ,
230134) : Uint8Array {
231- if ( opts . size ) {
232- assertSize ( hex , { size : opts . size } ) ;
233- // biome-ignore lint/style/noParameterAssign: for perf
234- hex = padHex ( hex , { dir : "right" , size : opts . size } ) ;
235- }
236-
237- let hexString = hex . slice ( 2 ) as string ;
238- if ( hexString . length % 2 ) {
239- hexString = `0${ hexString } ` ;
240- }
241-
242- const length = hexString . length / 2 ;
243- const bytes = new Uint8Array ( length ) ;
244- for ( let index = 0 , j = 0 ; index < length ; index ++ ) {
245- const nibbleLeft = charCodeToBase16 ( hexString . charCodeAt ( j ++ ) ) ;
246- const nibbleRight = charCodeToBase16 ( hexString . charCodeAt ( j ++ ) ) ;
247- if ( nibbleLeft === undefined || nibbleRight === undefined ) {
248- throw new Error ( `Invalid hex character: ${ hexString } ` ) ;
249- }
250- bytes [ index ] = nibbleLeft * 16 + nibbleRight ;
251- }
252- return bytes ;
135+ return ox__Hex . toBytes ( hex , opts ) ;
253136}
254137
255138export type FromHexParameters <
@@ -311,13 +194,7 @@ export function fromHex<
311194// TO HEX
312195//--------------------------------------------------------------------------
313196
314- const hexes = /* @__PURE__ */ ( ( ) =>
315- Array . from ( { length : 256 } , ( _v , i ) => i . toString ( 16 ) . padStart ( 2 , "0" ) ) ) ( ) ;
316-
317- export type BoolToHexOpts = {
318- /** The size (in bytes) of the output hex value. */
319- size ?: number ;
320- } ;
197+ export type BoolToHexOpts = ox__Hex . fromBoolean . Options ;
321198
322199/**
323200 * Converts a boolean value to a hexadecimal string representation.
@@ -333,18 +210,10 @@ export type BoolToHexOpts = {
333210 * @utils
334211 */
335212export function boolToHex ( value : boolean , opts : BoolToHexOpts = { } ) : Hex {
336- const hex = `0x${ Number ( value ) } ` as const ;
337- if ( typeof opts . size === "number" ) {
338- assertSize ( hex , { size : opts . size } ) ;
339- return padHex ( hex , { size : opts . size } ) ;
340- }
341- return hex ;
213+ return ox__Hex . fromBoolean ( value , opts ) ;
342214}
343215
344- export type Uint8ArrayToHexOpts = {
345- /** The size (in bytes) of the output hex value. */
346- size ?: number ;
347- } ;
216+ export type Uint8ArrayToHexOpts = ox__Hex . fromBoolean . Options ;
348217
349218/**
350219 * Converts an array of bytes to a hexadecimal string.
@@ -363,32 +232,10 @@ export function uint8ArrayToHex(
363232 value : Uint8Array ,
364233 opts : Uint8ArrayToHexOpts = { } ,
365234) : Hex {
366- let string = "" ;
367- for ( let i = 0 ; i < value . length ; i ++ ) {
368- // biome-ignore lint/style/noNonNullAssertion: we know this is defined
369- string += hexes [ value [ i ] ! ] ;
370- }
371- const hex = `0x${ string } ` as const ;
372-
373- if ( typeof opts . size === "number" ) {
374- assertSize ( hex , { size : opts . size } ) ;
375- return padHex ( hex , { dir : "right" , size : opts . size } ) ;
376- }
377- return hex ;
235+ return ox__Hex . fromBytes ( value , opts ) ;
378236}
379237
380- export type NumberToHexOpts =
381- | {
382- /** Whether or not the number of a signed representation. */
383- signed ?: boolean ;
384- /** The size (in bytes) of the output hex value. */
385- size : number ;
386- }
387- | {
388- signed ?: never ;
389- /** The size (in bytes) of the output hex value. */
390- size ?: number ;
391- } ;
238+ export type NumberToHexOpts = ox__Hex . fromNumber . Options ;
392239
393240/**
394241 * Converts a number or bigint to a hexadecimal string.
@@ -408,47 +255,10 @@ export function numberToHex(
408255 value_ : number | bigint ,
409256 opts : NumberToHexOpts = { } ,
410257) : Hex {
411- const { signed, size } = opts ;
412-
413- const value = BigInt ( value_ ) ;
414-
415- let maxValue : bigint | number | undefined ;
416- if ( size ) {
417- if ( signed ) {
418- maxValue = ( 1n << ( BigInt ( size ) * 8n - 1n ) ) - 1n ;
419- } else {
420- maxValue = 2n ** ( BigInt ( size ) * 8n ) - 1n ;
421- }
422- } else if ( typeof value_ === "number" ) {
423- maxValue = BigInt ( Number . MAX_SAFE_INTEGER ) ;
424- }
425-
426- const minValue = typeof maxValue === "bigint" && signed ? - maxValue - 1n : 0 ;
427-
428- if ( ( maxValue && value > maxValue ) || value < minValue ) {
429- const suffix = typeof value_ === "bigint" ? "n" : "" ;
430- throw new Error (
431- `Number "${ value_ } ${ suffix } " is not in safe ${
432- size ? `${ size * 8 } -bit ${ signed ? "signed" : "unsigned" } ` : ""
433- } integer range ${
434- maxValue ? `(${ minValue } to ${ maxValue } )` : `(above ${ minValue } )`
435- } `,
436- ) ;
437- }
438-
439- const hex = `0x${ (
440- signed && value < 0 ? ( 1n << BigInt ( size * 8 ) ) + BigInt ( value ) : value
441- ) . toString ( 16 ) } ` as Hex ;
442- if ( size ) {
443- return padHex ( hex , { size } ) as Hex ;
444- }
445- return hex ;
258+ return ox__Hex . fromNumber ( value_ , opts ) ;
446259}
447260
448- export type StringToHexOpts = {
449- /** The size (in bytes) of the output hex value. */
450- size ?: number ;
451- } ;
261+ export type StringToHexOpts = ox__Hex . fromString . Options ;
452262
453263/**
454264 * Converts a string to its hexadecimal representation.
@@ -464,11 +274,10 @@ export type StringToHexOpts = {
464274 * @utils
465275 */
466276export function stringToHex ( value_ : string , opts : StringToHexOpts = { } ) : Hex {
467- const value = cachedTextEncoder ( ) . encode ( value_ ) ;
468- return uint8ArrayToHex ( value , opts ) ;
277+ return ox__Hex . fromString ( value_ , opts ) ;
469278}
470279
471- export type ToHexParameters = {
280+ type ToHexParameters = {
472281 /** The size (in bytes) of the output hex value. */
473282 size ?: number ;
474283} ;
0 commit comments