@clickhouse/client 1.22.0 → 1.23.0-head.287977a.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (163) hide show
  1. package/README.md +2 -1
  2. package/dist/client.d.ts +2 -2
  3. package/dist/client.js +11 -4
  4. package/dist/client.js.map +1 -1
  5. package/dist/common/clickhouse_types.d.ts +98 -0
  6. package/dist/common/clickhouse_types.js +30 -0
  7. package/dist/common/clickhouse_types.js.map +1 -0
  8. package/dist/common/client.d.ts +233 -0
  9. package/dist/common/client.js +414 -0
  10. package/dist/common/client.js.map +1 -0
  11. package/dist/common/config.d.ts +234 -0
  12. package/dist/common/config.js +364 -0
  13. package/dist/common/config.js.map +1 -0
  14. package/dist/common/connection.d.ts +124 -0
  15. package/dist/common/connection.js +3 -0
  16. package/dist/common/connection.js.map +1 -0
  17. package/dist/common/data_formatter/format_query_params.d.ts +11 -0
  18. package/dist/common/data_formatter/format_query_params.js +128 -0
  19. package/dist/common/data_formatter/format_query_params.js.map +1 -0
  20. package/dist/common/data_formatter/format_query_settings.d.ts +2 -0
  21. package/dist/common/data_formatter/format_query_settings.js +20 -0
  22. package/dist/common/data_formatter/format_query_settings.js.map +1 -0
  23. package/dist/common/data_formatter/formatter.d.ts +41 -0
  24. package/dist/common/data_formatter/formatter.js +78 -0
  25. package/dist/common/data_formatter/formatter.js.map +1 -0
  26. package/dist/common/data_formatter/index.d.ts +3 -0
  27. package/dist/common/data_formatter/index.js +24 -0
  28. package/dist/common/data_formatter/index.js.map +1 -0
  29. package/dist/common/error/error.d.ts +20 -0
  30. package/dist/common/error/error.js +73 -0
  31. package/dist/common/error/error.js.map +1 -0
  32. package/dist/common/error/index.d.ts +1 -0
  33. package/dist/common/error/index.js +18 -0
  34. package/dist/common/error/index.js.map +1 -0
  35. package/dist/common/index.d.ts +67 -0
  36. package/dist/common/index.js +97 -0
  37. package/dist/common/index.js.map +1 -0
  38. package/dist/common/logger.d.ts +80 -0
  39. package/dist/common/logger.js +154 -0
  40. package/dist/common/logger.js.map +1 -0
  41. package/dist/common/parse/column_types.d.ts +155 -0
  42. package/dist/common/parse/column_types.js +594 -0
  43. package/dist/common/parse/column_types.js.map +1 -0
  44. package/dist/common/parse/index.d.ts +2 -0
  45. package/dist/common/parse/index.js +19 -0
  46. package/dist/common/parse/index.js.map +1 -0
  47. package/dist/common/parse/json_handling.d.ts +19 -0
  48. package/dist/common/parse/json_handling.js +8 -0
  49. package/dist/common/parse/json_handling.js.map +1 -0
  50. package/dist/common/result.d.ts +90 -0
  51. package/dist/common/result.js +3 -0
  52. package/dist/common/result.js.map +1 -0
  53. package/dist/common/settings.d.ts +2007 -0
  54. package/dist/common/settings.js +19 -0
  55. package/dist/common/settings.js.map +1 -0
  56. package/dist/common/tracing.d.ts +146 -0
  57. package/dist/common/tracing.js +76 -0
  58. package/dist/common/tracing.js.map +1 -0
  59. package/dist/common/ts_utils.d.ts +4 -0
  60. package/dist/common/ts_utils.js +3 -0
  61. package/dist/common/ts_utils.js.map +1 -0
  62. package/dist/common/utils/connection.d.ts +21 -0
  63. package/dist/common/utils/connection.js +43 -0
  64. package/dist/common/utils/connection.js.map +1 -0
  65. package/dist/common/utils/index.d.ts +5 -0
  66. package/dist/common/utils/index.js +22 -0
  67. package/dist/common/utils/index.js.map +1 -0
  68. package/dist/common/utils/multipart.d.ts +34 -0
  69. package/dist/common/utils/multipart.js +81 -0
  70. package/dist/common/utils/multipart.js.map +1 -0
  71. package/dist/common/utils/sleep.d.ts +4 -0
  72. package/dist/common/utils/sleep.js +12 -0
  73. package/dist/common/utils/sleep.js.map +1 -0
  74. package/dist/common/utils/stream.d.ts +15 -0
  75. package/dist/common/utils/stream.js +50 -0
  76. package/dist/common/utils/stream.js.map +1 -0
  77. package/dist/common/utils/url.d.ts +20 -0
  78. package/dist/common/utils/url.js +67 -0
  79. package/dist/common/utils/url.js.map +1 -0
  80. package/dist/common/version.d.ts +2 -0
  81. package/dist/common/version.js +4 -0
  82. package/dist/common/version.js.map +1 -0
  83. package/dist/config.d.ts +22 -2
  84. package/dist/config.js +2 -2
  85. package/dist/config.js.map +1 -1
  86. package/dist/connection/compression.d.ts +2 -2
  87. package/dist/connection/compression.js +4 -4
  88. package/dist/connection/compression.js.map +1 -1
  89. package/dist/connection/create_connection.d.ts +1 -1
  90. package/dist/connection/node_base_connection.d.ts +3 -3
  91. package/dist/connection/node_base_connection.js +22 -22
  92. package/dist/connection/node_base_connection.js.map +1 -1
  93. package/dist/connection/node_custom_agent_connection.js +2 -2
  94. package/dist/connection/node_custom_agent_connection.js.map +1 -1
  95. package/dist/connection/node_http_connection.js +2 -2
  96. package/dist/connection/node_http_connection.js.map +1 -1
  97. package/dist/connection/node_https_connection.d.ts +1 -1
  98. package/dist/connection/node_https_connection.js +3 -3
  99. package/dist/connection/node_https_connection.js.map +1 -1
  100. package/dist/connection/socket_pool.d.ts +1 -1
  101. package/dist/connection/socket_pool.js +30 -30
  102. package/dist/connection/socket_pool.js.map +1 -1
  103. package/dist/connection/stream.d.ts +1 -1
  104. package/dist/connection/stream.js +9 -9
  105. package/dist/connection/stream.js.map +1 -1
  106. package/dist/index.d.ts +9 -7
  107. package/dist/index.js +26 -24
  108. package/dist/index.js.map +1 -1
  109. package/dist/result_set.d.ts +1 -1
  110. package/dist/result_set.js +10 -10
  111. package/dist/result_set.js.map +1 -1
  112. package/dist/utils/encoder.d.ts +1 -1
  113. package/dist/utils/encoder.js +5 -5
  114. package/dist/utils/encoder.js.map +1 -1
  115. package/dist/version.d.ts +1 -1
  116. package/dist/version.js +1 -1
  117. package/dist/version.js.map +1 -1
  118. package/package.json +7 -5
  119. package/skills/clickhouse-js-node-rowbinary-parser/EXAMPLES.md +48 -0
  120. package/skills/clickhouse-js-node-rowbinary-parser/README.md +255 -0
  121. package/skills/clickhouse-js-node-rowbinary-parser/SKILL.md +206 -0
  122. package/skills/clickhouse-js-node-rowbinary-parser/case-studies/iot-rowbinary-vs-json.md +83 -0
  123. package/skills/clickhouse-js-node-rowbinary-parser/case-studies/ledger-rowbinary-vs-json.md +103 -0
  124. package/skills/clickhouse-js-node-rowbinary-parser/case-studies/logs-json-wins.md +86 -0
  125. package/skills/clickhouse-js-node-rowbinary-parser/case-studies/wasm-vs-js.md +172 -0
  126. package/skills/clickhouse-js-node-rowbinary-parser/src/aggregateFunction.ts +34 -0
  127. package/skills/clickhouse-js-node-rowbinary-parser/src/bool.ts +10 -0
  128. package/skills/clickhouse-js-node-rowbinary-parser/src/columnar.ts +125 -0
  129. package/skills/clickhouse-js-node-rowbinary-parser/src/compile.ts +318 -0
  130. package/skills/clickhouse-js-node-rowbinary-parser/src/composite.ts +181 -0
  131. package/skills/clickhouse-js-node-rowbinary-parser/src/core.ts +77 -0
  132. package/skills/clickhouse-js-node-rowbinary-parser/src/datetime.ts +113 -0
  133. package/skills/clickhouse-js-node-rowbinary-parser/src/decimals.ts +57 -0
  134. package/skills/clickhouse-js-node-rowbinary-parser/src/dynamic.ts +328 -0
  135. package/skills/clickhouse-js-node-rowbinary-parser/src/enums.ts +28 -0
  136. package/skills/clickhouse-js-node-rowbinary-parser/src/examples/carts.ts +71 -0
  137. package/skills/clickhouse-js-node-rowbinary-parser/src/examples/events.ts +51 -0
  138. package/skills/clickhouse-js-node-rowbinary-parser/src/examples/iot.ts +158 -0
  139. package/skills/clickhouse-js-node-rowbinary-parser/src/examples/ledger.ts +98 -0
  140. package/skills/clickhouse-js-node-rowbinary-parser/src/examples/logs.ts +73 -0
  141. package/skills/clickhouse-js-node-rowbinary-parser/src/examples/observability.ts +142 -0
  142. package/skills/clickhouse-js-node-rowbinary-parser/src/examples/orders.ts +65 -0
  143. package/skills/clickhouse-js-node-rowbinary-parser/src/examples/profiles.ts +60 -0
  144. package/skills/clickhouse-js-node-rowbinary-parser/src/examples/telemetry.ts +102 -0
  145. package/skills/clickhouse-js-node-rowbinary-parser/src/floats.ts +32 -0
  146. package/skills/clickhouse-js-node-rowbinary-parser/src/geo.ts +109 -0
  147. package/skills/clickhouse-js-node-rowbinary-parser/src/header.ts +29 -0
  148. package/skills/clickhouse-js-node-rowbinary-parser/src/integers.ts +95 -0
  149. package/skills/clickhouse-js-node-rowbinary-parser/src/interval.ts +54 -0
  150. package/skills/clickhouse-js-node-rowbinary-parser/src/ip.ts +93 -0
  151. package/skills/clickhouse-js-node-rowbinary-parser/src/json.ts +33 -0
  152. package/skills/clickhouse-js-node-rowbinary-parser/src/lowCardinality.ts +18 -0
  153. package/skills/clickhouse-js-node-rowbinary-parser/src/nested.ts +23 -0
  154. package/skills/clickhouse-js-node-rowbinary-parser/src/nothing.ts +29 -0
  155. package/skills/clickhouse-js-node-rowbinary-parser/src/reader.ts +68 -0
  156. package/skills/clickhouse-js-node-rowbinary-parser/src/rowBinaryWithNamesAndTypes.ts +155 -0
  157. package/skills/clickhouse-js-node-rowbinary-parser/src/rows.ts +58 -0
  158. package/skills/clickhouse-js-node-rowbinary-parser/src/simpleAggregateFunction.ts +20 -0
  159. package/skills/clickhouse-js-node-rowbinary-parser/src/stream.ts +276 -0
  160. package/skills/clickhouse-js-node-rowbinary-parser/src/strings.ts +55 -0
  161. package/skills/clickhouse-js-node-rowbinary-parser/src/time.ts +61 -0
  162. package/skills/clickhouse-js-node-rowbinary-parser/src/uuid.ts +153 -0
  163. package/skills/clickhouse-js-node-rowbinary-parser/src/varint.ts +70 -0
@@ -0,0 +1,61 @@
1
+ import { type Reader, Cursor } from "./core.js";
2
+ import { readInt32, readInt64 } from "./integers.js";
3
+
4
+ /** Semantic alias for `number` marking a seconds value (see {@link readTime}). */
5
+ export type Seconds = number;
6
+
7
+ /**
8
+ * A signed sub-second duration kept lossless as its raw parts: the value is
9
+ * `ticks / 10 ** precision` seconds. Used by `Time64` (a time-of-day duration,
10
+ * which has no natural JS type), carrying the precision so nothing is lost.
11
+ */
12
+ export type ScaledTicks = readonly [ticks: bigint, precision: number];
13
+
14
+ /**
15
+ * Read a `Time`: 4-byte signed `Int32` seconds-of-day (range ±999:59:59).
16
+ * Returns the raw seconds; pass it to {@link formatTime}.
17
+ */
18
+ export function readTime(state: Cursor): Seconds {
19
+ return readInt32(state);
20
+ }
21
+
22
+ /**
23
+ * Read a `Time64(P)`: 8-byte signed `Int64` count of `10^-P`-second ticks.
24
+ * Curried: `readTime64(P)` returns the reader. Returns `[ticks, precision]` (a
25
+ * {@link ScaledTicks}); pass it to {@link formatTime64}.
26
+ */
27
+ export function readTime64(precision: number): Reader<ScaledTicks> {
28
+ return (state) => [readInt64(state), precision];
29
+ }
30
+
31
+ /**
32
+ * Format a `Time` value (signed seconds-of-day) as "[-]HH:MM:SS". The hour
33
+ * field can exceed two digits (the range is ±999:59:59).
34
+ */
35
+ export function formatTime(seconds: Seconds): string {
36
+ const sign = seconds < 0 ? "-" : "";
37
+ const s = Math.abs(seconds);
38
+ const hh = Math.floor(s / 3600);
39
+ const mm = Math.floor((s % 3600) / 60);
40
+ const ss = s % 60;
41
+ return `${sign}${String(hh).padStart(2, "0")}:${String(mm).padStart(2, "0")}:${String(ss).padStart(2, "0")}`;
42
+ }
43
+
44
+ /**
45
+ * Format a `Time64` [ticks, precision] (signed sub-second time-of-day) as
46
+ * "[-]HH:MM:SS[.fff]".
47
+ */
48
+ export function formatTime64([ticks, precision]: ScaledTicks): string {
49
+ const sign = ticks < 0n ? "-" : "";
50
+ const t = ticks < 0n ? -ticks : ticks;
51
+ const scale = 10n ** BigInt(precision);
52
+ const totalSec = Number(t / scale);
53
+ const frac = t % scale;
54
+ const hh = Math.floor(totalSec / 3600);
55
+ const mm = Math.floor((totalSec % 3600) / 60);
56
+ const ss = totalSec % 60;
57
+ const base = `${sign}${String(hh).padStart(2, "0")}:${String(mm).padStart(2, "0")}:${String(ss).padStart(2, "0")}`;
58
+ return precision > 0
59
+ ? `${base}.${frac.toString().padStart(precision, "0")}`
60
+ : base;
61
+ }
@@ -0,0 +1,153 @@
1
+ import { Cursor, advance } from "./core.js";
2
+
3
+ /**
4
+ * `UUID_HEX16[b]` packs the two lowercase ASCII hex chars of byte `b`, low char
5
+ * in the low byte. Drives the lookup-table UUID formatter {@link formatUUIDTable}.
6
+ */
7
+ const UUID_HEX16 = new Uint16Array(256);
8
+ for (let b = 0; b < 256; b++) {
9
+ const hex = b.toString(16).padStart(2, "0");
10
+ UUID_HEX16[b] = hex.charCodeAt(0) | (hex.charCodeAt(1) << 8);
11
+ }
12
+
13
+ /**
14
+ * Reusable 36-byte scratch for {@link formatUUIDTable}. The four `-` separators
15
+ * are written once and never touched again; each call overwrites only the 32
16
+ * hex slots, then copies the bytes out as a string.
17
+ */
18
+ const UUID_OUT = Buffer.alloc(36);
19
+ UUID_OUT[8] = UUID_OUT[13] = UUID_OUT[18] = UUID_OUT[23] = 0x2d; // '-'
20
+
21
+ /**
22
+ * Read a `UUID`: 16 raw bytes (two little-endian `UInt64` halves on the wire).
23
+ * Returns a zero-copy view; pass it to {@link formatUUID} for the canonical
24
+ * `xxxxxxxx-...` string.
25
+ *
26
+ * The view shares memory with the response buffer, so keeping it alive pins the
27
+ * whole chunk; copy with `Buffer.from(...)` if it must outlive the row.
28
+ *
29
+ * FAST ALTERNATIVE: if you stringify every UUID, use {@link formatUUIDTable}
30
+ * (lookup table, no BigInt, ~1.6x faster).
31
+ */
32
+ export function readUUID(state: Cursor): Buffer {
33
+ const start = advance(state, 16);
34
+ return state.buf.subarray(start, start + 16);
35
+ }
36
+
37
+ /**
38
+ * Read a `UUID` as a single 128-bit `bigint` (`hi << 64 | lo`) — useful for
39
+ * numeric storage, comparison, or de-duplication without a string.
40
+ *
41
+ * Reads the halves with `DataView.getBigUint64` rather than
42
+ * `Buffer.readBigUInt64LE`: V8 inlines the DataView accessors, measurably faster
43
+ * for 8-byte reads. For the canonical string, use {@link readUUID} + {@link formatUUID}.
44
+ */
45
+ export function readUUIDBigInt(state: Cursor): bigint {
46
+ const start = advance(state, 16);
47
+ const hi = state.view.getBigUint64(start, true);
48
+ const lo = state.view.getBigUint64(start + 8, true);
49
+ return (hi << 64n) | lo;
50
+ }
51
+
52
+ /**
53
+ * Read a `UUID` as its two raw little-endian `UInt64` halves, `[hi, lo]` — the
54
+ * faithful wire split with no combining work. Cheaper than {@link readUUIDBigInt}
55
+ * (skips `hi << 64 | lo`) and a compact two-value key for comparison/dedup. For
56
+ * the canonical string, use {@link readUUID} + {@link formatUUID}.
57
+ */
58
+ export function readUUIDHiLo(state: Cursor): [hi: bigint, lo: bigint] {
59
+ const start = advance(state, 16);
60
+ const hi = state.view.getBigUint64(start, true);
61
+ const lo = state.view.getBigUint64(start + 8, true);
62
+ return [hi, lo];
63
+ }
64
+
65
+ /**
66
+ * Format a `UUID` (raw 16 bytes from {@link readUUID}) as the canonical
67
+ * `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx` string.
68
+ *
69
+ * THE TRAP: ClickHouse stores a UUID as two little-endian `UInt64` halves (high
70
+ * then low), so each half is byte-reversed vs the text form. Reading each half
71
+ * with `readBigUInt64LE` undoes that; concatenating high then low gives the 32
72
+ * canonical hex digits. (Hexing the 16 bytes in wire order scrambles the value.)
73
+ * Kept aside from the read so the hot path can skip stringifying when raw bytes
74
+ * suffice.
75
+ *
76
+ * FAST ALTERNATIVE: to format every value, {@link formatUUIDTable} does the same
77
+ * via a byte->hex lookup table with no BigInt (~1.6x faster).
78
+ */
79
+ export function formatUUID(b: Buffer): string {
80
+ const hex = ((b.readBigUInt64LE(0) << 64n) | b.readBigUInt64LE(8))
81
+ .toString(16)
82
+ .padStart(32, "0");
83
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
84
+ }
85
+
86
+ /**
87
+ * Fast {@link formatUUID}: same canonical string via a byte -> two-hex-char
88
+ * lookup table (`UUID_HEX16`) written into a reused 36-byte buffer (`UUID_OUT`,
89
+ * dashes preset), no BigInt, no slicing. ~1.6x faster (see `readUUID.bench.ts`).
90
+ * Takes the raw 16 bytes from {@link readUUID}.
91
+ *
92
+ * Same byte-reversal as formatUUID: emit the high half in reverse (`b[7]..b[0]`)
93
+ * then the low half (`b[15]..b[8]`).
94
+ *
95
+ * SAFE TO TOGGLE — opt-in fast formatter, not the default. `UUID_OUT` is shared
96
+ * scratch, so NOT reentrant; safe for synchronous formatting because the bytes
97
+ * are copied into the returned string before the next call (don't alias
98
+ * `UUID_OUT`). Worth it only when you stringify every UUID.
99
+ */
100
+ export function formatUUIDTable(b: Buffer): string {
101
+ let p: number;
102
+ // High half: bytes b[7]..b[0] -> hex positions 0..7 (chars 0..15).
103
+ p = UUID_HEX16[b[7]!]!;
104
+ UUID_OUT[0] = p & 0xff;
105
+ UUID_OUT[1] = p >>> 8;
106
+ p = UUID_HEX16[b[6]!]!;
107
+ UUID_OUT[2] = p & 0xff;
108
+ UUID_OUT[3] = p >>> 8;
109
+ p = UUID_HEX16[b[5]!]!;
110
+ UUID_OUT[4] = p & 0xff;
111
+ UUID_OUT[5] = p >>> 8;
112
+ p = UUID_HEX16[b[4]!]!;
113
+ UUID_OUT[6] = p & 0xff;
114
+ UUID_OUT[7] = p >>> 8;
115
+ p = UUID_HEX16[b[3]!]!;
116
+ UUID_OUT[9] = p & 0xff;
117
+ UUID_OUT[10] = p >>> 8;
118
+ p = UUID_HEX16[b[2]!]!;
119
+ UUID_OUT[11] = p & 0xff;
120
+ UUID_OUT[12] = p >>> 8;
121
+ p = UUID_HEX16[b[1]!]!;
122
+ UUID_OUT[14] = p & 0xff;
123
+ UUID_OUT[15] = p >>> 8;
124
+ p = UUID_HEX16[b[0]!]!;
125
+ UUID_OUT[16] = p & 0xff;
126
+ UUID_OUT[17] = p >>> 8;
127
+ // Low half: bytes b[15]..b[8] -> hex positions 8..15 (chars 19..35).
128
+ p = UUID_HEX16[b[15]!]!;
129
+ UUID_OUT[19] = p & 0xff;
130
+ UUID_OUT[20] = p >>> 8;
131
+ p = UUID_HEX16[b[14]!]!;
132
+ UUID_OUT[21] = p & 0xff;
133
+ UUID_OUT[22] = p >>> 8;
134
+ p = UUID_HEX16[b[13]!]!;
135
+ UUID_OUT[24] = p & 0xff;
136
+ UUID_OUT[25] = p >>> 8;
137
+ p = UUID_HEX16[b[12]!]!;
138
+ UUID_OUT[26] = p & 0xff;
139
+ UUID_OUT[27] = p >>> 8;
140
+ p = UUID_HEX16[b[11]!]!;
141
+ UUID_OUT[28] = p & 0xff;
142
+ UUID_OUT[29] = p >>> 8;
143
+ p = UUID_HEX16[b[10]!]!;
144
+ UUID_OUT[30] = p & 0xff;
145
+ UUID_OUT[31] = p >>> 8;
146
+ p = UUID_HEX16[b[9]!]!;
147
+ UUID_OUT[32] = p & 0xff;
148
+ UUID_OUT[33] = p >>> 8;
149
+ p = UUID_HEX16[b[8]!]!;
150
+ UUID_OUT[34] = p & 0xff;
151
+ UUID_OUT[35] = p >>> 8;
152
+ return UUID_OUT.toString("latin1");
153
+ }
@@ -0,0 +1,70 @@
1
+ import { Cursor, advance } from "./core.js";
2
+
3
+ /**
4
+ * Read a LEB128 unsigned varint (used for string/array lengths).
5
+ *
6
+ * Returns a JS `number`, so it is NOT bigint-friendly: only values up to
7
+ * `Number.MAX_SAFE_INTEGER` (2^53 - 1) are representable exactly. A varint
8
+ * larger than that throws rather than silently losing precision. RowBinary
9
+ * lengths never approach this in practice.
10
+ *
11
+ * The loop is unrolled: each byte carries 7 bits, so its place value is the
12
+ * constant 2^(7*k). The overwhelmingly common 1–2 byte case costs one or two
13
+ * reads and a compare.
14
+ *
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
+ }