Setting the file. One moment.
Geo · Clickhouse Js Node Rowbinary · ClickHouse/agent-skills · Skills Docs
ContentsBack to the top of the page src/writers/ geo.ts
TypeScript · 125 lines · 5 KB
10 */
11 export function writePoint ( sink : Sink , [ x , y ] : Point ) : void {
12 const o = reserve (sink, 16 );
13 sink.view. setFloat64 (o, x, true );
14 sink.view. setFloat64 (o + 8 , y, true );
15 }
16
17 /**
18 * Write a `Ring`: `Array(Point)` — a LEB128 point count, then each point. The
19 * inverse of `readRing`; a SINGLE `reserve(16 * length)` covers the whole point
20 * block (one bounds check per ring, not per point), then the coordinates are
21 * written into it inline, mirroring the reader.
22 */
23 export function writeRing ( sink : Sink , points : readonly Point []) : void {
24 writeUVarint (sink, points. length );
25 let p = reserve (sink, points. length * 16 );
26 for ( let i = 0 ; i < points. length ; i ++ ) {
27 const [ x , y ] = points[i] ! ;
28 sink.view. setFloat64 (p, x, true );
29 sink.view. setFloat64 (p + 8 , y, true );
30 p += 16 ;
31 }
32 }
33
34 /** Write a `LineString`: `Array(Point)` (identical wire to a `Ring`). Inverse of `readLineString`. */
35 export function writeLineString ( sink : Sink , points : readonly Point []) : void {
36 writeUVarint (sink, points. length );
37 let p = reserve (sink, points. length * 16 );
38 for ( let i = 0 ; i < points. length ; i ++ ) {
39 const [ x , y ] = points[i] ! ;
40 sink.view. setFloat64 (p, x, true );
41 sink.view. setFloat64 (p + 8 , y, true );
42 p += 16 ;
43 }
44 }
45
46 /** Write a `Polygon`: `Array(Ring)` — outer ring first, then holes. Inverse of `readPolygon`. */
47 export function writePolygon ( sink : Sink , rings : readonly Point [][]) : void {
48 writeUVarint (sink, rings. length );
49 for ( let i = 0 ; i < rings. length ; i ++ ) writeRing (sink, rings[i] ! );
50 }
51
52 /** Write a `MultiLineString`: `Array(LineString)`. Inverse of `readMultiLineString`. */
53 export function writeMultiLineString (
54 sink : Sink ,
55 lines : readonly Point [][],
56 ) : void {
57 writeUVarint (sink, lines. length );
58 for ( let i = 0 ; i < lines. length ; i ++ ) writeLineString (sink, lines[i] ! );
59 }
60
61 /** Write a `MultiPolygon`: `Array(Polygon)`. Inverse of `readMultiPolygon`. */
62 export function writeMultiPolygon (
63 sink : Sink ,
64 polygons : readonly Point [][][],
65 ) : void {
66 writeUVarint (sink, polygons. length );
67 for ( let i = 0 ; i < polygons. length ; i ++ ) writePolygon (sink, polygons[i] ! );
68 }
69
70 /**
71 * A tagged `Geometry` value for { @link writeGeometry } : the alternative's
72 * `discriminant` paired with its value, or `null` for NULL. Like
73 * `readVariant`/`writeVariant`, `readGeometry` returns only the value — and the
74 * geo value shapes overlap (LineString and Ring are both `Point[]`,
75 * MultiLineString and Polygon both `Point[][]`) — so encode must be told which geo
76 * type it is via the discriminant.
77 *
78 * Discriminants (sorted by type name): LineString(0), MultiLineString(1),
79 * MultiPolygon(2), Point(3), Polygon(4), Ring(5); `0xFF` = NULL.
80 */
81 export type GeometryValue =
82 | readonly [ discriminant : number , value : unknown ]
83 | null ;
84
85 /**
86 * Write a `Geometry`: a 1-byte discriminant then the chosen geo type's value. The
87 * inverse of `readGeometry` (a switch over the discriminant with each branch
88 * inlined). Takes a tagged { @link GeometryValue } because the value shapes are
89 * ambiguous on their own.
90 */
91 export const writeGeometry : Writer < GeometryValue > = ( sink , value ) => {
92 if (value === null ) {
93 writeUInt8 (sink, 0xff );
94 return ;
95 }
96 // The discriminant byte is written inside each case, only after the switch
97 // has accepted it — an out-of-range value throws from `default` before the
98 // sink is advanced, so it never leaves a partially-written payload behind
99 // (mirrors `writeVariant`).
100 const [ discriminant , geo ] = value;
101 switch (discriminant) {
102 case 0 :
103 writeUInt8 (sink, discriminant);
104 return writeLineString (sink, geo as Point []);
105 case 1 :
106 writeUInt8 (sink, discriminant);
107 return writeMultiLineString (sink, geo as Point [][]);
108 case 2 :
109 writeUInt8 (sink, discriminant);
110 return writeMultiPolygon (sink, geo as Point [][][]);
111 case 3 :
112 writeUInt8 (sink, discriminant);
113 return writePoint (sink, geo as Point );
114 case 4 :
115 writeUInt8 (sink, discriminant);
116 return writePolygon (sink, geo as Point [][]);
117 case 5 :
118 writeUInt8 (sink, discriminant);
119 return writeRing (sink, geo as Point []);
120 default :
121 throw new RangeError (
122 `RowBinary: unknown Geometry discriminant ${ discriminant }` ,
123 );
124 }
125 };