@ckb-ccc/core
Version:
Core of CCC - CKBer's Codebase
205 lines (204 loc) • 5.74 kB
JavaScript
import { bytesConcat, bytesFrom } from "../bytes/index.js";
import { hexFrom } from "../hex/index.js";
/**
* Get the min among all numbers.
* @public
*
* @param numbers - numbers.
* @returns The min numbers among them.
*
* @example
* ```typescript
* numMin(1, 2, 3); // Outputs 1n
* ```
*/
export function numMin(a, ...numbers) {
let min = numFrom(a);
numbers.forEach((nLike) => {
const n = numFrom(nLike);
if (n < min) {
min = n;
}
});
return min;
}
/**
* Get the max among all numbers.
* @public
*
* @param numbers - numbers.
* @returns The max numbers among them.
*
* @example
* ```typescript
* numMax(1, 2, 3); // Outputs 3n
* ```
*/
export function numMax(a, ...numbers) {
let max = numFrom(a);
numbers.forEach((nLike) => {
const n = numFrom(nLike);
if (n > max) {
max = n;
}
});
return max;
}
/**
* Converts a NumLike value to a Num (bigint).
* @public
*
* @param val - The value to convert, which can be a string, number, bigint, or HexLike.
* @returns A Num (bigint) representing the value.
*
* @example
* ```typescript
* const num = numFrom("12345"); // Outputs 12345n
* const numFromHex = numFrom("0x3039"); // Outputs 12345n
* ```
*/
export function numFrom(val) {
if (typeof val === "bigint") {
return val;
}
if (val === "0x") {
return BigInt(0);
}
if (typeof val === "string" || typeof val === "number") {
return BigInt(val);
}
const hex = hexFrom(val);
return BigInt(hex);
}
/**
* Converts a NumLike value to a hexadecimal string.
* @public
*
* @param val - The value to convert, which can be a string, number, bigint, or HexLike.
* @returns A Hex string representing the numeric value.
*
* @example
* ```typescript
* const hex = numToHex(12345); // Outputs "0x3039"
* ```
*/
export function numToHex(val) {
return `0x${numFrom(val).toString(16)}`;
}
/**
* Converts a NumLike value to a byte array in little-endian order.
* @public
*
* @param val - The value to convert, which can be a string, number, bigint, or HexLike.
* @param bytes - The number of bytes to use for the representation. If not provided, the exact number of bytes needed is used.
* @returns A Uint8Array containing the byte representation of the numeric value.
*
* @example
* ```typescript
* const bytes = numToBytes(12345, 4); // Outputs Uint8Array [57, 48, 0, 0]
* ```
*/
export function numToBytes(val, bytes) {
return numLeToBytes(val, bytes);
}
/**
* Converts a NumLike value to a byte array in little-endian order.
* @public
*
* @param val - The value to convert, which can be a string, number, bigint, or HexLike.
* @param bytes - The number of bytes to use for the representation. If not provided, the exact number of bytes needed is used.
* @returns A Uint8Array containing the byte representation of the numeric value.
*
* @example
* ```typescript
* const bytes = numLeToBytes(12345, 4); // Outputs Uint8Array [57, 48, 0, 0]
* ```
*/
export function numLeToBytes(val, bytes) {
return numBeToBytes(val, bytes).reverse();
}
/**
* Converts a NumLike value to a byte array in big-endian order.
* @public
*
* @param val - The value to convert, which can be a string, number, bigint, or HexLike.
* @param bytes - The number of bytes to use for the representation. If not provided, the exact number of bytes needed is used.
* @returns A Uint8Array containing the byte representation of the numeric value.
*
* @example
* ```typescript
* const bytes = numBeToBytes(12345, 4); // Outputs Uint8Array [0, 0, 48, 57]
* ```
*/
export function numBeToBytes(val, bytes) {
let num = numFrom(val);
if (num < numFrom(0)) {
if (bytes == null) {
throw Error("negative number can not be serialized without knowing bytes length");
}
// 0x100............00 - abs(num)
// | . bytes * 8 .|
// 2's complement for negative number
num = (numFrom(1) << (numFrom(8) * numFrom(bytes))) + num;
if (num < 0) {
throw Error("negative number underflow");
}
}
const rawBytes = bytesFrom(num.toString(16));
if (bytes == null) {
return rawBytes;
}
if (rawBytes.length > bytes) {
throw Error("number overflow");
}
return bytesConcat("00".repeat(bytes - rawBytes.length), rawBytes);
}
/**
* Converts a byte array to a Num (bigint) assuming little-endian order.
* @public
*
* @param val - The byte array to convert.
* @returns A Num (bigint) representing the numeric value.
*
* @example
* ```typescript
* const num = numFromBytes(new Uint8Array([57, 48, 0, 0])); // Outputs 12345n
* ```
*/
export function numFromBytes(val) {
return numLeFromBytes(val);
}
/**
* Converts a byte array to a Num (bigint) assuming little-endian order.
* @public
*
* @param val - The byte array to convert.
* @returns A Num (bigint) representing the numeric value.
*
* @example
* ```typescript
* const num = numLeFromBytes(new Uint8Array([57, 48, 0, 0])); // Outputs 12345n
* ```
*/
export function numLeFromBytes(val) {
// reverse() modifies the original array
// so we use the map to copy it to avoid this
return numBeFromBytes(bytesFrom(val)
.map((v) => v)
.reverse());
}
/**
* Converts a byte array to a Num (bigint) assuming big-endian order.
* @public
*
* @param val - The byte array to convert.
* @returns A Num (bigint) representing the numeric value.
*
* @example
* ```typescript
* const num = numBeFromBytes(new Uint8Array([0, 0, 48, 57])); // Outputs 12345n
* ```
*/
export function numBeFromBytes(val) {
return numFrom(bytesFrom(val));
}