Setting the file. One moment.
Varint · Clickhouse Js Node Rowbinary · ClickHouse/agent-skills · Skills Docs
ContentsBack to the top of the page (opens in a new tab)
src/readers/ varint.ts
TypeScript · 70 lines · 3 KB
*
15 * Multipliers must stay as `*` (not `<<`): JS bitwise shift is 32-bit and would wrap past bit 31.
16 *
17 * SAFE TO TOGGLE — how many bytes to handle:
18 * - If you know the maximum blob/array size, keep only the steps you need and
19 * delete the rest along with the overflow guard. E.g. lengths < 2^28 fit in
20 * 4 bytes, so everything below the `* 268435456` step can go.
21 * - Keep all eight steps (the default) when lengths are untrusted.
22 * If you genuinely need lengths beyond 2^53, create a bigint version of this
23 * function with a bigint accumulator instead of removing the guard.
24 *
25 * OPTIMIZATION HINT — for a known invariant, emit a dedicated named variant
26 * rather than toggling here. E.g. a `readUVarint32` for lengths guaranteed to be
27 * 32-bit would unroll only the first five bytes and throw past 2^32 - 1.
28 */
29 export function readUVarint ( state : Cursor ) : number {
30 // Each byte reserves its space through `advance(1)` (the bounds check), but
31 // the read itself stays inlined as `state.buf[...]` rather than calling
32 // readUInt8 — this is the hottest loop in the reader.
33 let byte = state.buf[ advance (state, 1 )] ! ;
34 if (byte < 0x80 ) return byte; // 1 byte -> 2^0
35 let result = byte & 0x7f ;
36
37 byte = state.buf[ advance (state, 1 )] ! ;
38 if (byte < 0x80 ) return result + byte * 128 ; // 2^7
39 result += (byte & 0x7f ) * 128 ;
40
41 byte = state.buf[ advance (state, 1 )] ! ;
42 if (byte < 0x80 ) return result + byte * 16384 ; // 2^14
43 result += (byte & 0x7f ) * 16384 ;
44
45 byte = state.buf[ advance (state, 1 )] ! ;
46 if (byte < 0x80 ) return result + byte * 2097152 ; // 2^21
47 result += (byte & 0x7f ) * 2097152 ;
48
49 byte = state.buf[ advance (state, 1 )] ! ;
50 if (byte < 0x80 ) return result + byte * 268435456 ; // 2^28
51 result += (byte & 0x7f ) * 268435456 ;
52
53 byte = state.buf[ advance (state, 1 )] ! ;
54 if (byte < 0x80 ) return result + byte * 34359738368 ; // 2^35
55 result += (byte & 0x7f ) * 34359738368 ;
56
57 byte = state.buf[ advance (state, 1 )] ! ;
58 if (byte < 0x80 ) return result + byte * 4398046511104 ; // 2^42
59 result += (byte & 0x7f ) * 4398046511104 ;
60
61 // 8th byte: only its low 4 payload bits (bits 49..52) fit under 2^53. A larger
62 // payload, or a continuation bit signalling a 9th byte, overflows MAX_SAFE_INTEGER.
63 byte = state.buf[ advance (state, 1 )] ! ;
64 if (byte > 0x0f ) {
65 throw new RangeError (
66 "RowBinary: varint exceeds Number.MAX_SAFE_INTEGER (2^53 - 1)" ,
67 );
68 }
69 return result + byte * 562949953421312 ; // 2^49
70 }