Setting the file. One moment.
Uuid · Clickhouse Js Node Rowbinary · ClickHouse/agent-skills · Skills Docs
ContentsBack to the top of the page src/readers/ uuid.ts
TypeScript · 153 lines · 6 KB
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 << 64 n ) | 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 ) << 64 n ) | 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 }