11/**
2- * LEB128 (Little Endian Base 128) encoding/decoding for unsigned 32-bit integers.
3- *
4- * This is a variable-length integer encoding where each byte stores 7 bits of data
5- * and uses bit 7 as a continuation flag (1 = more bytes follow, 0 = last byte).
6- *
7- * Benefits:
8- * - Small values use fewer bytes (e.g., 0-127 use only 1 byte)
9- * - Works in all JavaScript runtimes (uses only Uint8Array)
10- * - No dependencies on Node.js Buffer or other runtime-specific APIs
2+ * LEB128 (Little Endian Base 128) encoding for unsigned 32-bit integers.
3+ * Variable-length encoding: each byte stores 7 bits of data, bit 7 is continuation flag.
114 */
125
136const MAX_UINT32 = 0xffffffff ;
147const CONTINUATION_BIT = 0x80 ;
158const DATA_BITS_MASK = 0x7f ;
169const DATA_BITS_PER_BYTE = 7 ;
17- const MAX_BYTES_FOR_UINT32 = 5 ; // ceil(32 / 7) = 5
10+ const MAX_BYTES_FOR_UINT32 = 5 ;
1811
1912/**
2013 * Encodes an unsigned 32-bit integer into LEB128 format.
2114 *
22- * @param value - The unsigned 32-bit integer to encode (0 to 4,294,967,295)
23- * @returns Uint8Array containing the encoded bytes (1-5 bytes)
24- * @throws Error if value is invalid
25- *
26- * @example
27- * encodeUInt32(0) // Uint8Array[0x00] (1 byte)
28- * encodeUInt32(127) // Uint8Array[0x7F] (1 byte)
29- * encodeUInt32(128) // Uint8Array[0x80, 0x01] (2 bytes)
30- * encodeUInt32(300) // Uint8Array[0xAC, 0x02] (2 bytes)
15+ * @param value - Unsigned 32-bit integer (0 to 4,294,967,295)
16+ * @returns Encoded bytes (1-5 bytes depending on value)
3117 */
3218export function encodeUInt32 ( value : number ) : Uint8Array {
3319 validateUInt32 ( value ) ;
3420
35- // Handle zero directly (most common small value)
3621 if ( value === 0 ) {
3722 return new Uint8Array ( [ 0 ] ) ;
3823 }
@@ -56,16 +41,9 @@ export function encodeUInt32(value: number): Uint8Array {
5641/**
5742 * Decodes an unsigned 32-bit integer from LEB128 format.
5843 *
59- * @param data - Uint8Array containing LEB128 encoded data
60- * @param offset - Starting position in the buffer (defaults to 0)
61- * @returns Object with decoded value and the index after the last byte read
62- * @throws Error if decoding fails
63- *
64- * @example
65- * decodeUInt32(new Uint8Array([0x00])) // { value: 0, nextIndex: 1 }
66- * decodeUInt32(new Uint8Array([0x7F])) // { value: 127, nextIndex: 1 }
67- * decodeUInt32(new Uint8Array([0x80, 0x01])) // { value: 128, nextIndex: 2 }
68- * decodeUInt32(new Uint8Array([0xAC, 0x02])) // { value: 300, nextIndex: 2 }
44+ * @param data - Buffer containing LEB128 encoded data
45+ * @param offset - Starting position in buffer (default: 0)
46+ * @returns Decoded value and index after last byte read
6947 */
7048export function decodeUInt32 (
7149 data : Uint8Array ,
@@ -82,15 +60,13 @@ export function decodeUInt32(
8260 const byte = data [ index ++ ] ;
8361 bytesRead ++ ;
8462
85- // Check for overflow before processing
8663 if ( bytesRead > MAX_BYTES_FOR_UINT32 ) {
8764 throw new Error ( 'LEB128 sequence exceeds maximum length for uint32' ) ;
8865 }
8966
9067 result |= ( byte & DATA_BITS_MASK ) << shift ;
9168
9269 if ( ! hasContinuationBit ( byte ) ) {
93- // Convert to unsigned 32-bit integer
9470 return { value : result >>> 0 , nextIndex : index } ;
9571 }
9672
@@ -100,9 +76,6 @@ export function decodeUInt32(
10076 throw new Error ( 'Truncated LEB128 encoding' ) ;
10177}
10278
103- /**
104- * Validates that a value is a valid unsigned 32-bit integer.
105- */
10679function validateUInt32 ( value : number ) : void {
10780 if ( ! Number . isFinite ( value ) ) {
10881 throw new Error ( 'Value must be a finite number' ) ;
@@ -118,18 +91,14 @@ function validateUInt32(value: number): void {
11891 }
11992}
12093
121- /**
122- * Validates that an offset is within bounds.
123- */
12494function validateOffset ( data : Uint8Array , offset : number ) : void {
12595 if ( offset < 0 || offset >= data . length ) {
126- throw new Error ( `Offset ${ offset } is out of bounds (buffer length: ${ data . length } )` ) ;
96+ throw new Error (
97+ `Offset ${ offset } is out of bounds (buffer length: ${ data . length } )` ,
98+ ) ;
12799 }
128100}
129101
130- /**
131- * Checks if a byte has the continuation bit set.
132- */
133102function hasContinuationBit ( byte : number ) : boolean {
134103 return ( byte & CONTINUATION_BIT ) !== 0 ;
135- }
104+ }
0 commit comments