Skip to content

Commit ad6b427

Browse files
phroiHanssen0
authored andcommitted
feat(core): Add bytesLen and bytesLenUnsafe utilities (ckb-devrel#353)
1 parent ebe0d35 commit ad6b427

2 files changed

Lines changed: 62 additions & 1 deletion

File tree

.changeset/eighty-terms-cry.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@ckb-ccc/core": minor
3+
---
4+
5+
Add `bytesLen` and `bytesLenUnsafe` utilities

packages/core/src/hex/index.ts

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export type HexLike = BytesLike;
1818
* A valid hexadecimal string:
1919
* - Has at least two characters.
2020
* - Starts with "0x".
21-
* - Has an even length.
21+
* - Has an even length (odd-length hex is considered non-standard).
2222
* - Contains only characters representing digits (0-9) or lowercase letters (a-f) after the "0x" prefix.
2323
*
2424
* @param v - The value to validate as a hexadecimal (ccc.Hex) string.
@@ -58,3 +58,59 @@ export function hexFrom(hex: HexLike): Hex {
5858

5959
return `0x${bytesTo(bytesFrom(hex), "hex")}`;
6060
}
61+
62+
/**
63+
* Return the number of bytes occupied by `hexLike`.
64+
*
65+
* This function efficiently calculates the byte length of hex-like values.
66+
* For valid Hex strings, it uses a fast-path helper. For other types, it
67+
* converts to bytes first.
68+
*
69+
* @param hexLike - Hex-like value (Hex string, Uint8Array, ArrayBuffer, or iterable of numbers).
70+
* @returns Byte length of `hexLike`.
71+
*
72+
* @example
73+
* ```typescript
74+
* bytesLen("0x48656c6c6f") // 5
75+
* bytesLen(new Uint8Array([1, 2, 3])) // 3
76+
* bytesLen(new ArrayBuffer(4)) // 4
77+
* bytesLen([1, 2]) // 2
78+
* ```
79+
*
80+
* @throws May throw if `hexLike` contains invalid byte values when passed to `bytesFrom`.
81+
* @see bytesLenUnsafe - Fast version for already-validated Hex strings
82+
*
83+
* @note Prefer direct `.length`/`.byteLength` access on Uint8Array/ArrayBuffer when you already have bytes.
84+
* Use `bytesLen()` only when you need length without performing additional operations.
85+
* @see bytesFrom - Convert values to Bytes (Uint8Array)
86+
*/
87+
export function bytesLen(hexLike: HexLike): number {
88+
if (isHex(hexLike)) {
89+
return bytesLenUnsafe(hexLike);
90+
}
91+
92+
return bytesFrom(hexLike).length;
93+
}
94+
95+
/**
96+
* Fast byte length for Hex strings.
97+
*
98+
* This function efficiently calculates the byte length of Hex values:
99+
* - Skips isHex validation (caller must ensure input is valid Hex)
100+
* - Handles odd-digit hex by rounding up, matching bytesFrom's padding behavior.
101+
*
102+
* @param hex - A valid Hex string (with "0x" prefix).
103+
* @returns Byte length of the hex string.
104+
*
105+
* @example
106+
* ```typescript
107+
* bytesLenUnsafe("0x48656c6c6f") // 5
108+
* bytesLenUnsafe("0x123") // 2 (odd digits round up via padding)
109+
* ```
110+
*
111+
* @see bytesLen - Validated version for untrusted input
112+
*/
113+
export function bytesLenUnsafe(hex: Hex): number {
114+
// Equivalent to Math.ceil((hex.length - 2) / 2), rounds up for odd-digit hex.
115+
return (hex.length - 1) >> 1;
116+
}

0 commit comments

Comments
 (0)