Skip to content

Commit 35f67ce

Browse files
minor refactor of ast nodes to reduce duplication (#6)
1 parent d30344c commit 35f67ce

2 files changed

Lines changed: 43 additions & 136 deletions

File tree

src/core/decoder/format-decoder.ts

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { BinaryReader } from './reader';
2-
import { ParsedData } from '../types/ast';
2+
import { decodeLEB128 } from './leb128';
3+
import { AstNode, ParsedData } from '../types/ast';
34
import { ClickHouseFormat } from '../types/formats';
45

56
/**
@@ -23,4 +24,33 @@ export abstract class FormatDecoder {
2324
protected generateId(): string {
2425
return `node-${this.nodeIdCounter++}`;
2526
}
27+
28+
/** Decode a LEB128 varint and return both the value and a leaf AstNode for it */
29+
protected decodeLEB128Node(label: string = 'length'): { count: number; node: AstNode } {
30+
const start = this.reader.offset;
31+
const { value: count } = decodeLEB128(this.reader);
32+
return {
33+
count,
34+
node: {
35+
id: this.generateId(),
36+
type: 'VarUInt',
37+
byteRange: { start, end: this.reader.offset },
38+
value: count,
39+
displayValue: String(count),
40+
label,
41+
},
42+
};
43+
}
44+
45+
/** Create a UInt8 discriminant leaf node (for Nullable, Variant, Geometry, etc.) */
46+
protected createDiscriminantNode(startOffset: number, value: number, label: string): AstNode {
47+
return {
48+
id: this.generateId(),
49+
type: 'UInt8',
50+
byteRange: { start: startOffset, end: startOffset + 1 },
51+
value,
52+
displayValue: String(value),
53+
label,
54+
};
55+
}
2656
}

src/core/decoder/rowbinary-decoder.ts

Lines changed: 12 additions & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -754,18 +754,7 @@ export class RowBinaryDecoder extends FormatDecoder {
754754
private decodeArray(elementType: ClickHouseType): AstNode {
755755
const startOffset = this.reader.offset;
756756

757-
// Decode array length with AST node
758-
const lengthStart = this.reader.offset;
759-
const { value: count } = decodeLEB128(this.reader);
760-
const lengthNode: AstNode = {
761-
id: this.generateId(),
762-
type: 'VarUInt',
763-
byteRange: { start: lengthStart, end: this.reader.offset },
764-
value: count,
765-
displayValue: String(count),
766-
label: 'length',
767-
};
768-
757+
const { count, node: lengthNode } = this.decodeLEB128Node();
769758
const children: AstNode[] = [lengthNode];
770759

771760
for (let i = 0; i < count; i++) {
@@ -812,17 +801,7 @@ export class RowBinaryDecoder extends FormatDecoder {
812801
private decodeMap(keyType: ClickHouseType, valueType: ClickHouseType): AstNode {
813802
const startOffset = this.reader.offset;
814803

815-
// Decode map length with AST node
816-
const lengthStart = this.reader.offset;
817-
const { value: count } = decodeLEB128(this.reader);
818-
const lengthNode: AstNode = {
819-
id: this.generateId(),
820-
type: 'VarUInt',
821-
byteRange: { start: lengthStart, end: this.reader.offset },
822-
value: count,
823-
displayValue: String(count),
824-
label: 'length',
825-
};
804+
const { count, node: lengthNode } = this.decodeLEB128Node();
826805

827806
const children: AstNode[] = [lengthNode];
828807

@@ -872,15 +851,7 @@ export class RowBinaryDecoder extends FormatDecoder {
872851
};
873852
}
874853

875-
const discriminantNode: AstNode = {
876-
id: this.generateId(),
877-
type: 'UInt8',
878-
byteRange: { start: startOffset, end: startOffset + 1 },
879-
value: isNull,
880-
displayValue: '0',
881-
label: 'is_null',
882-
};
883-
854+
const discriminantNode = this.createDiscriminantNode(startOffset, isNull, 'is_null');
884855
const child = this.decodeValue(innerType);
885856
return {
886857
id: this.generateId(),
@@ -913,16 +884,7 @@ export class RowBinaryDecoder extends FormatDecoder {
913884
}
914885

915886
const selectedType = variants[discriminant];
916-
917-
const discriminantNode: AstNode = {
918-
id: this.generateId(),
919-
type: 'UInt8',
920-
byteRange: { start: startOffset, end: startOffset + 1 },
921-
value: discriminant,
922-
displayValue: String(discriminant),
923-
label: 'discriminant',
924-
};
925-
887+
const discriminantNode = this.createDiscriminantNode(startOffset, discriminant, 'discriminant');
926888
const child = this.decodeValue(selectedType);
927889

928890
return {
@@ -1235,18 +1197,7 @@ export class RowBinaryDecoder extends FormatDecoder {
12351197
private decodeJSON(typedPaths?: Map<string, ClickHouseType>): AstNode {
12361198
const startOffset = this.reader.offset;
12371199

1238-
// Read number of paths with AST node
1239-
const pathCountStart = this.reader.offset;
1240-
const { value: pathCount } = decodeLEB128(this.reader);
1241-
const pathCountNode: AstNode = {
1242-
id: this.generateId(),
1243-
type: 'VarUInt',
1244-
byteRange: { start: pathCountStart, end: this.reader.offset },
1245-
value: pathCount,
1246-
displayValue: String(pathCount),
1247-
label: 'path_count',
1248-
};
1249-
1200+
const { count: pathCount, node: pathCountNode } = this.decodeLEB128Node('path_count');
12501201
const children: AstNode[] = [pathCountNode];
12511202

12521203
for (let i = 0; i < pathCount; i++) {
@@ -1332,18 +1283,7 @@ export class RowBinaryDecoder extends FormatDecoder {
13321283
// Ring = Array(Point)
13331284
private decodeRing(): AstNode {
13341285
const startOffset = this.reader.offset;
1335-
1336-
const lengthStart = this.reader.offset;
1337-
const { value: count } = decodeLEB128(this.reader);
1338-
const lengthNode: AstNode = {
1339-
id: this.generateId(),
1340-
type: 'VarUInt',
1341-
byteRange: { start: lengthStart, end: this.reader.offset },
1342-
value: count,
1343-
displayValue: String(count),
1344-
label: 'length',
1345-
};
1346-
1286+
const { count, node: lengthNode } = this.decodeLEB128Node();
13471287
const children: AstNode[] = [lengthNode];
13481288

13491289
for (let i = 0; i < count; i++) {
@@ -1365,18 +1305,7 @@ export class RowBinaryDecoder extends FormatDecoder {
13651305
// Polygon = Array(Ring)
13661306
private decodePolygon(): AstNode {
13671307
const startOffset = this.reader.offset;
1368-
1369-
const lengthStart = this.reader.offset;
1370-
const { value: count } = decodeLEB128(this.reader);
1371-
const lengthNode: AstNode = {
1372-
id: this.generateId(),
1373-
type: 'VarUInt',
1374-
byteRange: { start: lengthStart, end: this.reader.offset },
1375-
value: count,
1376-
displayValue: String(count),
1377-
label: 'length',
1378-
};
1379-
1308+
const { count, node: lengthNode } = this.decodeLEB128Node();
13801309
const children: AstNode[] = [lengthNode];
13811310

13821311
for (let i = 0; i < count; i++) {
@@ -1398,18 +1327,7 @@ export class RowBinaryDecoder extends FormatDecoder {
13981327
// MultiPolygon = Array(Polygon)
13991328
private decodeMultiPolygon(): AstNode {
14001329
const startOffset = this.reader.offset;
1401-
1402-
const lengthStart = this.reader.offset;
1403-
const { value: count } = decodeLEB128(this.reader);
1404-
const lengthNode: AstNode = {
1405-
id: this.generateId(),
1406-
type: 'VarUInt',
1407-
byteRange: { start: lengthStart, end: this.reader.offset },
1408-
value: count,
1409-
displayValue: String(count),
1410-
label: 'length',
1411-
};
1412-
1330+
const { count, node: lengthNode } = this.decodeLEB128Node();
14131331
const children: AstNode[] = [lengthNode];
14141332

14151333
for (let i = 0; i < count; i++) {
@@ -1431,18 +1349,7 @@ export class RowBinaryDecoder extends FormatDecoder {
14311349
// LineString = Array(Point)
14321350
private decodeLineString(): AstNode {
14331351
const startOffset = this.reader.offset;
1434-
1435-
const lengthStart = this.reader.offset;
1436-
const { value: count } = decodeLEB128(this.reader);
1437-
const lengthNode: AstNode = {
1438-
id: this.generateId(),
1439-
type: 'VarUInt',
1440-
byteRange: { start: lengthStart, end: this.reader.offset },
1441-
value: count,
1442-
displayValue: String(count),
1443-
label: 'length',
1444-
};
1445-
1352+
const { count, node: lengthNode } = this.decodeLEB128Node();
14461353
const children: AstNode[] = [lengthNode];
14471354

14481355
for (let i = 0; i < count; i++) {
@@ -1464,18 +1371,7 @@ export class RowBinaryDecoder extends FormatDecoder {
14641371
// MultiLineString = Array(LineString)
14651372
private decodeMultiLineString(): AstNode {
14661373
const startOffset = this.reader.offset;
1467-
1468-
const lengthStart = this.reader.offset;
1469-
const { value: count } = decodeLEB128(this.reader);
1470-
const lengthNode: AstNode = {
1471-
id: this.generateId(),
1472-
type: 'VarUInt',
1473-
byteRange: { start: lengthStart, end: this.reader.offset },
1474-
value: count,
1475-
displayValue: String(count),
1476-
label: 'length',
1477-
};
1478-
1374+
const { count, node: lengthNode } = this.decodeLEB128Node();
14791375
const children: AstNode[] = [lengthNode];
14801376

14811377
for (let i = 0; i < count; i++) {
@@ -1533,15 +1429,7 @@ export class RowBinaryDecoder extends FormatDecoder {
15331429
throw new Error(`Unknown Geometry discriminant: ${discriminant}`);
15341430
}
15351431

1536-
const discriminantNode: AstNode = {
1537-
id: this.generateId(),
1538-
type: 'UInt8',
1539-
byteRange: { start: startOffset, end: startOffset + 1 },
1540-
value: discriminant,
1541-
displayValue: String(discriminant),
1542-
label: 'discriminant',
1543-
};
1544-
1432+
const discriminantNode = this.createDiscriminantNode(startOffset, discriminant, 'discriminant');
15451433
return {
15461434
id: this.generateId(),
15471435
type: 'Geometry',
@@ -1581,18 +1469,7 @@ export class RowBinaryDecoder extends FormatDecoder {
15811469
private decodeQBit(elementType: ClickHouseType, dimension: number): AstNode {
15821470
const startOffset = this.reader.offset;
15831471

1584-
// Read size (should match dimension) with AST node
1585-
const lengthStart = this.reader.offset;
1586-
const { value: size } = decodeLEB128(this.reader);
1587-
const lengthNode: AstNode = {
1588-
id: this.generateId(),
1589-
type: 'VarUInt',
1590-
byteRange: { start: lengthStart, end: this.reader.offset },
1591-
value: size,
1592-
displayValue: String(size),
1593-
label: 'length',
1594-
};
1595-
1472+
const { count: size, node: lengthNode } = this.decodeLEB128Node();
15961473
const children: AstNode[] = [lengthNode];
15971474
for (let i = 0; i < size; i++) {
15981475
const child = this.decodeValue(elementType);

0 commit comments

Comments
 (0)