@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.
- package/README.md +2 -1
- package/dist/client.d.ts +2 -2
- package/dist/client.js +11 -4
- package/dist/client.js.map +1 -1
- package/dist/common/clickhouse_types.d.ts +98 -0
- package/dist/common/clickhouse_types.js +30 -0
- package/dist/common/clickhouse_types.js.map +1 -0
- package/dist/common/client.d.ts +233 -0
- package/dist/common/client.js +414 -0
- package/dist/common/client.js.map +1 -0
- package/dist/common/config.d.ts +234 -0
- package/dist/common/config.js +364 -0
- package/dist/common/config.js.map +1 -0
- package/dist/common/connection.d.ts +124 -0
- package/dist/common/connection.js +3 -0
- package/dist/common/connection.js.map +1 -0
- package/dist/common/data_formatter/format_query_params.d.ts +11 -0
- package/dist/common/data_formatter/format_query_params.js +128 -0
- package/dist/common/data_formatter/format_query_params.js.map +1 -0
- package/dist/common/data_formatter/format_query_settings.d.ts +2 -0
- package/dist/common/data_formatter/format_query_settings.js +20 -0
- package/dist/common/data_formatter/format_query_settings.js.map +1 -0
- package/dist/common/data_formatter/formatter.d.ts +41 -0
- package/dist/common/data_formatter/formatter.js +78 -0
- package/dist/common/data_formatter/formatter.js.map +1 -0
- package/dist/common/data_formatter/index.d.ts +3 -0
- package/dist/common/data_formatter/index.js +24 -0
- package/dist/common/data_formatter/index.js.map +1 -0
- package/dist/common/error/error.d.ts +20 -0
- package/dist/common/error/error.js +73 -0
- package/dist/common/error/error.js.map +1 -0
- package/dist/common/error/index.d.ts +1 -0
- package/dist/common/error/index.js +18 -0
- package/dist/common/error/index.js.map +1 -0
- package/dist/common/index.d.ts +67 -0
- package/dist/common/index.js +97 -0
- package/dist/common/index.js.map +1 -0
- package/dist/common/logger.d.ts +80 -0
- package/dist/common/logger.js +154 -0
- package/dist/common/logger.js.map +1 -0
- package/dist/common/parse/column_types.d.ts +155 -0
- package/dist/common/parse/column_types.js +594 -0
- package/dist/common/parse/column_types.js.map +1 -0
- package/dist/common/parse/index.d.ts +2 -0
- package/dist/common/parse/index.js +19 -0
- package/dist/common/parse/index.js.map +1 -0
- package/dist/common/parse/json_handling.d.ts +19 -0
- package/dist/common/parse/json_handling.js +8 -0
- package/dist/common/parse/json_handling.js.map +1 -0
- package/dist/common/result.d.ts +90 -0
- package/dist/common/result.js +3 -0
- package/dist/common/result.js.map +1 -0
- package/dist/common/settings.d.ts +2007 -0
- package/dist/common/settings.js +19 -0
- package/dist/common/settings.js.map +1 -0
- package/dist/common/tracing.d.ts +146 -0
- package/dist/common/tracing.js +76 -0
- package/dist/common/tracing.js.map +1 -0
- package/dist/common/ts_utils.d.ts +4 -0
- package/dist/common/ts_utils.js +3 -0
- package/dist/common/ts_utils.js.map +1 -0
- package/dist/common/utils/connection.d.ts +21 -0
- package/dist/common/utils/connection.js +43 -0
- package/dist/common/utils/connection.js.map +1 -0
- package/dist/common/utils/index.d.ts +5 -0
- package/dist/common/utils/index.js +22 -0
- package/dist/common/utils/index.js.map +1 -0
- package/dist/common/utils/multipart.d.ts +34 -0
- package/dist/common/utils/multipart.js +81 -0
- package/dist/common/utils/multipart.js.map +1 -0
- package/dist/common/utils/sleep.d.ts +4 -0
- package/dist/common/utils/sleep.js +12 -0
- package/dist/common/utils/sleep.js.map +1 -0
- package/dist/common/utils/stream.d.ts +15 -0
- package/dist/common/utils/stream.js +50 -0
- package/dist/common/utils/stream.js.map +1 -0
- package/dist/common/utils/url.d.ts +20 -0
- package/dist/common/utils/url.js +67 -0
- package/dist/common/utils/url.js.map +1 -0
- package/dist/common/version.d.ts +2 -0
- package/dist/common/version.js +4 -0
- package/dist/common/version.js.map +1 -0
- package/dist/config.d.ts +22 -2
- package/dist/config.js +2 -2
- package/dist/config.js.map +1 -1
- package/dist/connection/compression.d.ts +2 -2
- package/dist/connection/compression.js +4 -4
- package/dist/connection/compression.js.map +1 -1
- package/dist/connection/create_connection.d.ts +1 -1
- package/dist/connection/node_base_connection.d.ts +3 -3
- package/dist/connection/node_base_connection.js +22 -22
- package/dist/connection/node_base_connection.js.map +1 -1
- package/dist/connection/node_custom_agent_connection.js +2 -2
- package/dist/connection/node_custom_agent_connection.js.map +1 -1
- package/dist/connection/node_http_connection.js +2 -2
- package/dist/connection/node_http_connection.js.map +1 -1
- package/dist/connection/node_https_connection.d.ts +1 -1
- package/dist/connection/node_https_connection.js +3 -3
- package/dist/connection/node_https_connection.js.map +1 -1
- package/dist/connection/socket_pool.d.ts +1 -1
- package/dist/connection/socket_pool.js +30 -30
- package/dist/connection/socket_pool.js.map +1 -1
- package/dist/connection/stream.d.ts +1 -1
- package/dist/connection/stream.js +9 -9
- package/dist/connection/stream.js.map +1 -1
- package/dist/index.d.ts +9 -7
- package/dist/index.js +26 -24
- package/dist/index.js.map +1 -1
- package/dist/result_set.d.ts +1 -1
- package/dist/result_set.js +10 -10
- package/dist/result_set.js.map +1 -1
- package/dist/utils/encoder.d.ts +1 -1
- package/dist/utils/encoder.js +5 -5
- package/dist/utils/encoder.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/package.json +7 -5
- package/skills/clickhouse-js-node-rowbinary-parser/EXAMPLES.md +48 -0
- package/skills/clickhouse-js-node-rowbinary-parser/README.md +255 -0
- package/skills/clickhouse-js-node-rowbinary-parser/SKILL.md +206 -0
- package/skills/clickhouse-js-node-rowbinary-parser/case-studies/iot-rowbinary-vs-json.md +83 -0
- package/skills/clickhouse-js-node-rowbinary-parser/case-studies/ledger-rowbinary-vs-json.md +103 -0
- package/skills/clickhouse-js-node-rowbinary-parser/case-studies/logs-json-wins.md +86 -0
- package/skills/clickhouse-js-node-rowbinary-parser/case-studies/wasm-vs-js.md +172 -0
- package/skills/clickhouse-js-node-rowbinary-parser/src/aggregateFunction.ts +34 -0
- package/skills/clickhouse-js-node-rowbinary-parser/src/bool.ts +10 -0
- package/skills/clickhouse-js-node-rowbinary-parser/src/columnar.ts +125 -0
- package/skills/clickhouse-js-node-rowbinary-parser/src/compile.ts +318 -0
- package/skills/clickhouse-js-node-rowbinary-parser/src/composite.ts +181 -0
- package/skills/clickhouse-js-node-rowbinary-parser/src/core.ts +77 -0
- package/skills/clickhouse-js-node-rowbinary-parser/src/datetime.ts +113 -0
- package/skills/clickhouse-js-node-rowbinary-parser/src/decimals.ts +57 -0
- package/skills/clickhouse-js-node-rowbinary-parser/src/dynamic.ts +328 -0
- package/skills/clickhouse-js-node-rowbinary-parser/src/enums.ts +28 -0
- package/skills/clickhouse-js-node-rowbinary-parser/src/examples/carts.ts +71 -0
- package/skills/clickhouse-js-node-rowbinary-parser/src/examples/events.ts +51 -0
- package/skills/clickhouse-js-node-rowbinary-parser/src/examples/iot.ts +158 -0
- package/skills/clickhouse-js-node-rowbinary-parser/src/examples/ledger.ts +98 -0
- package/skills/clickhouse-js-node-rowbinary-parser/src/examples/logs.ts +73 -0
- package/skills/clickhouse-js-node-rowbinary-parser/src/examples/observability.ts +142 -0
- package/skills/clickhouse-js-node-rowbinary-parser/src/examples/orders.ts +65 -0
- package/skills/clickhouse-js-node-rowbinary-parser/src/examples/profiles.ts +60 -0
- package/skills/clickhouse-js-node-rowbinary-parser/src/examples/telemetry.ts +102 -0
- package/skills/clickhouse-js-node-rowbinary-parser/src/floats.ts +32 -0
- package/skills/clickhouse-js-node-rowbinary-parser/src/geo.ts +109 -0
- package/skills/clickhouse-js-node-rowbinary-parser/src/header.ts +29 -0
- package/skills/clickhouse-js-node-rowbinary-parser/src/integers.ts +95 -0
- package/skills/clickhouse-js-node-rowbinary-parser/src/interval.ts +54 -0
- package/skills/clickhouse-js-node-rowbinary-parser/src/ip.ts +93 -0
- package/skills/clickhouse-js-node-rowbinary-parser/src/json.ts +33 -0
- package/skills/clickhouse-js-node-rowbinary-parser/src/lowCardinality.ts +18 -0
- package/skills/clickhouse-js-node-rowbinary-parser/src/nested.ts +23 -0
- package/skills/clickhouse-js-node-rowbinary-parser/src/nothing.ts +29 -0
- package/skills/clickhouse-js-node-rowbinary-parser/src/reader.ts +68 -0
- package/skills/clickhouse-js-node-rowbinary-parser/src/rowBinaryWithNamesAndTypes.ts +155 -0
- package/skills/clickhouse-js-node-rowbinary-parser/src/rows.ts +58 -0
- package/skills/clickhouse-js-node-rowbinary-parser/src/simpleAggregateFunction.ts +20 -0
- package/skills/clickhouse-js-node-rowbinary-parser/src/stream.ts +276 -0
- package/skills/clickhouse-js-node-rowbinary-parser/src/strings.ts +55 -0
- package/skills/clickhouse-js-node-rowbinary-parser/src/time.ts +61 -0
- package/skills/clickhouse-js-node-rowbinary-parser/src/uuid.ts +153 -0
- 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
|
+
}
|