You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
228 lines
5.6 KiB
228 lines
5.6 KiB
import { InvalidBytesBooleanError } from '../../errors/encoding.js'
|
|
import type { ErrorType } from '../../errors/utils.js'
|
|
import type { ByteArray, Hex } from '../../types/misc.js'
|
|
import { type TrimErrorType, trim } from '../data/trim.js'
|
|
|
|
import {
|
|
type AssertSizeErrorType,
|
|
assertSize,
|
|
type HexToBigIntErrorType,
|
|
type HexToNumberErrorType,
|
|
hexToBigInt,
|
|
hexToNumber,
|
|
} from './fromHex.js'
|
|
import { type BytesToHexErrorType, bytesToHex } from './toHex.js'
|
|
|
|
export type FromBytesParameters<
|
|
to extends 'string' | 'hex' | 'bigint' | 'number' | 'boolean',
|
|
> =
|
|
| to
|
|
| {
|
|
/** Size of the bytes. */
|
|
size?: number | undefined
|
|
/** Type to convert to. */
|
|
to: to
|
|
}
|
|
|
|
export type FromBytesReturnType<to> = to extends 'string'
|
|
? string
|
|
: to extends 'hex'
|
|
? Hex
|
|
: to extends 'bigint'
|
|
? bigint
|
|
: to extends 'number'
|
|
? number
|
|
: to extends 'boolean'
|
|
? boolean
|
|
: never
|
|
|
|
export type FromBytesErrorType =
|
|
| BytesToHexErrorType
|
|
| BytesToBigIntErrorType
|
|
| BytesToBoolErrorType
|
|
| BytesToNumberErrorType
|
|
| BytesToStringErrorType
|
|
| ErrorType
|
|
|
|
/**
|
|
* Decodes a byte array into a UTF-8 string, hex value, number, bigint or boolean.
|
|
*
|
|
* - Docs: https://viem.sh/docs/utilities/fromBytes
|
|
* - Example: https://viem.sh/docs/utilities/fromBytes#usage
|
|
*
|
|
* @param bytes Byte array to decode.
|
|
* @param toOrOpts Type to convert to or options.
|
|
* @returns Decoded value.
|
|
*
|
|
* @example
|
|
* import { fromBytes } from 'viem'
|
|
* const data = fromBytes(new Uint8Array([1, 164]), 'number')
|
|
* // 420
|
|
*
|
|
* @example
|
|
* import { fromBytes } from 'viem'
|
|
* const data = fromBytes(
|
|
* new Uint8Array([72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33]),
|
|
* 'string'
|
|
* )
|
|
* // 'Hello world'
|
|
*/
|
|
export function fromBytes<
|
|
to extends 'string' | 'hex' | 'bigint' | 'number' | 'boolean',
|
|
>(
|
|
bytes: ByteArray,
|
|
toOrOpts: FromBytesParameters<to>,
|
|
): FromBytesReturnType<to> {
|
|
const opts = typeof toOrOpts === 'string' ? { to: toOrOpts } : toOrOpts
|
|
const to = opts.to
|
|
|
|
if (to === 'number')
|
|
return bytesToNumber(bytes, opts) as FromBytesReturnType<to>
|
|
if (to === 'bigint')
|
|
return bytesToBigInt(bytes, opts) as FromBytesReturnType<to>
|
|
if (to === 'boolean')
|
|
return bytesToBool(bytes, opts) as FromBytesReturnType<to>
|
|
if (to === 'string')
|
|
return bytesToString(bytes, opts) as FromBytesReturnType<to>
|
|
return bytesToHex(bytes, opts) as FromBytesReturnType<to>
|
|
}
|
|
|
|
export type BytesToBigIntOpts = {
|
|
/** Whether or not the number of a signed representation. */
|
|
signed?: boolean | undefined
|
|
/** Size of the bytes. */
|
|
size?: number | undefined
|
|
}
|
|
|
|
export type BytesToBigIntErrorType =
|
|
| BytesToHexErrorType
|
|
| HexToBigIntErrorType
|
|
| ErrorType
|
|
|
|
/**
|
|
* Decodes a byte array into a bigint.
|
|
*
|
|
* - Docs: https://viem.sh/docs/utilities/fromBytes#bytestobigint
|
|
*
|
|
* @param bytes Byte array to decode.
|
|
* @param opts Options.
|
|
* @returns BigInt value.
|
|
*
|
|
* @example
|
|
* import { bytesToBigInt } from 'viem'
|
|
* const data = bytesToBigInt(new Uint8Array([1, 164]))
|
|
* // 420n
|
|
*/
|
|
export function bytesToBigInt(
|
|
bytes: ByteArray,
|
|
opts: BytesToBigIntOpts = {},
|
|
): bigint {
|
|
if (typeof opts.size !== 'undefined') assertSize(bytes, { size: opts.size })
|
|
const hex = bytesToHex(bytes, opts)
|
|
return hexToBigInt(hex, opts)
|
|
}
|
|
|
|
export type BytesToBoolOpts = {
|
|
/** Size of the bytes. */
|
|
size?: number | undefined
|
|
}
|
|
|
|
export type BytesToBoolErrorType =
|
|
| AssertSizeErrorType
|
|
| TrimErrorType
|
|
| ErrorType
|
|
|
|
/**
|
|
* Decodes a byte array into a boolean.
|
|
*
|
|
* - Docs: https://viem.sh/docs/utilities/fromBytes#bytestobool
|
|
*
|
|
* @param bytes Byte array to decode.
|
|
* @param opts Options.
|
|
* @returns Boolean value.
|
|
*
|
|
* @example
|
|
* import { bytesToBool } from 'viem'
|
|
* const data = bytesToBool(new Uint8Array([1]))
|
|
* // true
|
|
*/
|
|
export function bytesToBool(
|
|
bytes_: ByteArray,
|
|
opts: BytesToBoolOpts = {},
|
|
): boolean {
|
|
let bytes = bytes_
|
|
if (typeof opts.size !== 'undefined') {
|
|
assertSize(bytes, { size: opts.size })
|
|
bytes = trim(bytes)
|
|
}
|
|
if (bytes.length > 1 || bytes[0] > 1)
|
|
throw new InvalidBytesBooleanError(bytes)
|
|
return Boolean(bytes[0])
|
|
}
|
|
|
|
export type BytesToNumberOpts = BytesToBigIntOpts
|
|
|
|
export type BytesToNumberErrorType =
|
|
| BytesToHexErrorType
|
|
| HexToNumberErrorType
|
|
| ErrorType
|
|
|
|
/**
|
|
* Decodes a byte array into a number.
|
|
*
|
|
* - Docs: https://viem.sh/docs/utilities/fromBytes#bytestonumber
|
|
*
|
|
* @param bytes Byte array to decode.
|
|
* @param opts Options.
|
|
* @returns Number value.
|
|
*
|
|
* @example
|
|
* import { bytesToNumber } from 'viem'
|
|
* const data = bytesToNumber(new Uint8Array([1, 164]))
|
|
* // 420
|
|
*/
|
|
export function bytesToNumber(
|
|
bytes: ByteArray,
|
|
opts: BytesToNumberOpts = {},
|
|
): number {
|
|
if (typeof opts.size !== 'undefined') assertSize(bytes, { size: opts.size })
|
|
const hex = bytesToHex(bytes, opts)
|
|
return hexToNumber(hex, opts)
|
|
}
|
|
|
|
export type BytesToStringOpts = {
|
|
/** Size of the bytes. */
|
|
size?: number | undefined
|
|
}
|
|
|
|
export type BytesToStringErrorType =
|
|
| AssertSizeErrorType
|
|
| TrimErrorType
|
|
| ErrorType
|
|
|
|
/**
|
|
* Decodes a byte array into a UTF-8 string.
|
|
*
|
|
* - Docs: https://viem.sh/docs/utilities/fromBytes#bytestostring
|
|
*
|
|
* @param bytes Byte array to decode.
|
|
* @param opts Options.
|
|
* @returns String value.
|
|
*
|
|
* @example
|
|
* import { bytesToString } from 'viem'
|
|
* const data = bytesToString(new Uint8Array([72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33]))
|
|
* // 'Hello world'
|
|
*/
|
|
export function bytesToString(
|
|
bytes_: ByteArray,
|
|
opts: BytesToStringOpts = {},
|
|
): string {
|
|
let bytes = bytes_
|
|
if (typeof opts.size !== 'undefined') {
|
|
assertSize(bytes, { size: opts.size })
|
|
bytes = trim(bytes, { dir: 'right' })
|
|
}
|
|
return new TextDecoder().decode(bytes)
|
|
}
|