@maplibre/mlt 1.1.2 → 1.1.4

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 (96) hide show
  1. package/dist/decoding/decodingTestUtils.d.ts +75 -0
  2. package/dist/decoding/decodingTestUtils.js +285 -0
  3. package/dist/decoding/decodingTestUtils.js.map +1 -0
  4. package/dist/decoding/decodingUtils.d.ts +5 -8
  5. package/dist/decoding/decodingUtils.js +22 -49
  6. package/dist/decoding/decodingUtils.js.map +1 -1
  7. package/dist/decoding/decodingUtils.spec.js +85 -69
  8. package/dist/decoding/decodingUtils.spec.js.map +1 -1
  9. package/dist/decoding/fsstDecoder.spec.js +52 -35
  10. package/dist/decoding/fsstDecoder.spec.js.map +1 -1
  11. package/dist/decoding/geometryDecoder.js +41 -30
  12. package/dist/decoding/geometryDecoder.js.map +1 -1
  13. package/dist/decoding/integerDecodingUtils.d.ts +18 -31
  14. package/dist/decoding/integerDecodingUtils.js +134 -299
  15. package/dist/decoding/integerDecodingUtils.js.map +1 -1
  16. package/dist/decoding/integerDecodingUtils.spec.js +254 -148
  17. package/dist/decoding/integerDecodingUtils.spec.js.map +1 -1
  18. package/dist/decoding/integerStreamDecoder.d.ts +4 -6
  19. package/dist/decoding/integerStreamDecoder.js +104 -122
  20. package/dist/decoding/integerStreamDecoder.js.map +1 -1
  21. package/dist/decoding/integerStreamDecoder.spec.js +370 -131
  22. package/dist/decoding/integerStreamDecoder.spec.js.map +1 -1
  23. package/dist/decoding/propertyDecoder.js +13 -23
  24. package/dist/decoding/propertyDecoder.js.map +1 -1
  25. package/dist/decoding/propertyDecoder.spec.js +397 -608
  26. package/dist/decoding/propertyDecoder.spec.js.map +1 -1
  27. package/dist/decoding/stringDecoder.js +5 -9
  28. package/dist/decoding/stringDecoder.js.map +1 -1
  29. package/dist/decoding/stringDecoder.spec.js +322 -321
  30. package/dist/decoding/stringDecoder.spec.js.map +1 -1
  31. package/dist/decoding/unpackNullableUtils.d.ts +25 -0
  32. package/dist/decoding/unpackNullableUtils.js +51 -0
  33. package/dist/decoding/unpackNullableUtils.js.map +1 -0
  34. package/dist/decoding/unpackNullableUtils.spec.js +71 -0
  35. package/dist/decoding/unpackNullableUtils.spec.js.map +1 -0
  36. package/dist/encoding/embeddedTilesetMetadataEncoder.d.ts +16 -0
  37. package/dist/encoding/embeddedTilesetMetadataEncoder.js +40 -0
  38. package/dist/encoding/embeddedTilesetMetadataEncoder.js.map +1 -0
  39. package/dist/encoding/encodingUtils.d.ts +7 -0
  40. package/dist/encoding/encodingUtils.js +107 -0
  41. package/dist/encoding/encodingUtils.js.map +1 -0
  42. package/dist/encoding/fsstEncoder.d.ts +21 -0
  43. package/dist/encoding/fsstEncoder.js +78 -0
  44. package/dist/encoding/fsstEncoder.js.map +1 -0
  45. package/dist/encoding/integerEncodingUtils.d.ts +68 -0
  46. package/dist/encoding/integerEncodingUtils.js +655 -0
  47. package/dist/encoding/integerEncodingUtils.js.map +1 -0
  48. package/dist/encoding/integerStreamEncoder.d.ts +27 -0
  49. package/dist/encoding/integerStreamEncoder.js +139 -0
  50. package/dist/encoding/integerStreamEncoder.js.map +1 -0
  51. package/dist/encoding/packNullableUtils.d.ts +4 -0
  52. package/dist/encoding/packNullableUtils.js +55 -0
  53. package/dist/encoding/packNullableUtils.js.map +1 -0
  54. package/dist/encoding/propertyEncoder.d.ts +78 -0
  55. package/dist/encoding/propertyEncoder.js +335 -0
  56. package/dist/encoding/propertyEncoder.js.map +1 -0
  57. package/dist/encoding/stringEncoder.d.ts +12 -0
  58. package/dist/encoding/stringEncoder.js +182 -0
  59. package/dist/encoding/stringEncoder.js.map +1 -0
  60. package/dist/encoding/zOrderCurveEncoder.d.ts +1 -0
  61. package/dist/encoding/zOrderCurveEncoder.js +10 -0
  62. package/dist/encoding/zOrderCurveEncoder.js.map +1 -0
  63. package/dist/metadata/tileset/embeddedTilesetMetadataDecoder.d.ts +5 -1
  64. package/dist/metadata/tileset/embeddedTilesetMetadataDecoder.js +29 -41
  65. package/dist/metadata/tileset/embeddedTilesetMetadataDecoder.js.map +1 -1
  66. package/dist/metadata/tileset/embeddedTilesetMetadataDecoder.spec.d.ts +1 -0
  67. package/dist/metadata/tileset/embeddedTilesetMetadataDecoder.spec.js +142 -0
  68. package/dist/metadata/tileset/embeddedTilesetMetadataDecoder.spec.js.map +1 -0
  69. package/dist/mltDecoder.js +1 -2
  70. package/dist/mltDecoder.js.map +1 -1
  71. package/dist/vector/dictionary/stringDictionaryVector.d.ts +1 -1
  72. package/dist/vector/dictionary/stringDictionaryVector.js.map +1 -1
  73. package/dist/vector/flat/stringFlatVector.d.ts +1 -1
  74. package/dist/vector/flat/stringFlatVector.js.map +1 -1
  75. package/dist/vector/fsst-dictionary/stringFsstDictionaryVector.d.ts +1 -1
  76. package/dist/vector/fsst-dictionary/stringFsstDictionaryVector.js.map +1 -1
  77. package/dist/vector/fsst-dictionary/stringFsstDictionaryVector.spec.js +2 -2
  78. package/dist/vector/fsst-dictionary/stringFsstDictionaryVector.spec.js.map +1 -1
  79. package/dist/vector/geometry/constGpuVector.d.ts +2 -2
  80. package/dist/vector/geometry/constGpuVector.js.map +1 -1
  81. package/dist/vector/geometry/flatGpuVector.d.ts +2 -2
  82. package/dist/vector/geometry/flatGpuVector.js.map +1 -1
  83. package/dist/vector/geometry/gpuVector.d.ts +2 -2
  84. package/dist/vector/geometry/gpuVector.js.map +1 -1
  85. package/dist/vector/geometry/topologyVector.d.ts +4 -4
  86. package/dist/vector/geometry/topologyVector.js +0 -1
  87. package/dist/vector/geometry/topologyVector.js.map +1 -1
  88. package/dist/vector/geometry/zOrderCurve.spec.js +17 -11
  89. package/dist/vector/geometry/zOrderCurve.spec.js.map +1 -1
  90. package/dist/vector/variableSizeVector.d.ts +2 -2
  91. package/dist/vector/variableSizeVector.js +0 -1
  92. package/dist/vector/variableSizeVector.js.map +1 -1
  93. package/package.json +6 -8
  94. package/dist/decoding/geometryDecoder.spec.js +0 -5
  95. package/dist/decoding/geometryDecoder.spec.js.map +0 -1
  96. /package/dist/decoding/{geometryDecoder.spec.d.ts → unpackNullableUtils.spec.d.ts} +0 -0
@@ -1,645 +1,434 @@
1
- import { afterEach, describe, expect, it, vi } from "vitest";
2
- import * as StreamMetadataDecoder from "../metadata/tile/streamMetadataDecoder";
3
- import * as IntegerStreamDecoder from "./integerStreamDecoder";
1
+ import { describe, it, expect } from "vitest";
4
2
  import { decodePropertyColumn } from "./propertyDecoder";
5
- import { ScalarType } from "../metadata/tile/scalarType";
6
3
  import IntWrapper from "./intWrapper";
4
+ import { ScalarType } from "../metadata/tileset/tilesetMetadata";
7
5
  import { IntFlatVector } from "../vector/flat/intFlatVector";
8
6
  import { LongFlatVector } from "../vector/flat/longFlatVector";
7
+ import { FloatFlatVector } from "../vector/flat/floatFlatVector";
8
+ import { DoubleFlatVector } from "../vector/flat/doubleFlatVector";
9
+ import { BooleanFlatVector } from "../vector/flat/booleanFlatVector";
9
10
  import { IntSequenceVector } from "../vector/sequence/intSequenceVector";
10
11
  import { LongSequenceVector } from "../vector/sequence/longSequenceVector";
11
12
  import { IntConstVector } from "../vector/constant/intConstVector";
12
13
  import { LongConstVector } from "../vector/constant/longConstVector";
13
- import { VectorType } from "../vector/vectorType";
14
- import * as StringDecoder from "./stringDecoder";
15
- import * as decodingUtils from "./decodingUtils";
16
- import { BooleanFlatVector } from "../vector/flat/booleanFlatVector";
17
- import { FloatFlatVector } from "../vector/flat/floatFlatVector";
18
- import { DoubleFlatVector } from "../vector/flat/doubleFlatVector";
19
- // Constants for test data
20
- const TEST_DATA = {
21
- BYTE_LENGTH: 12,
22
- NUM_VALUES: 3,
23
- NULLABILITY_BYTE_LENGTH: 1,
24
- BUFFER_SIZE: 100,
25
- };
26
- // Helper: Create column with specific configuration
27
- function createColumn(scalarType, nullable = false) {
14
+ import { StringDictionaryVector } from "../vector/dictionary/stringDictionaryVector";
15
+ import { createColumnMetadataForStruct, encodeSharedDictionary, encodeStructField } from "./decodingTestUtils";
16
+ import { concatenateBuffers } from "../encoding/encodingUtils";
17
+ import { encodeInt32NoneColumn, encodeInt32DeltaColumn, encodeInt32RleColumn, encodeInt32DeltaRleColumn, encodeUint32Column, encodeInt64NoneColumn, encodeInt64DeltaColumn, encodeInt64RleColumn, encodeInt64DeltaRleColumn, encodeInt64NullableColumn, encodeUint64Column, encodeUint64NullableColumn, encodeFloatColumn, encodeFloatNullableColumn, encodeDoubleColumn, encodeDoubleNullableColumn, encodeBooleanColumn, encodeBooleanNullableColumn, encodeInt32NullableColumn, } from "../encoding/propertyEncoder";
18
+ function createColumnMetadata(name, scalarType, nullable = false) {
28
19
  return {
29
- name: "age",
30
- nullable,
31
- columnScope: null,
20
+ name: name,
21
+ nullable: nullable,
32
22
  type: "scalarType",
33
23
  scalarType: {
34
- longID: false,
35
24
  physicalType: scalarType,
36
- logicalType: null,
37
25
  type: "physicalType",
38
26
  },
39
- complexType: null,
40
- };
41
- }
42
- // Helper: Setup stream metadata mock
43
- function mockStreamMetadata(byteLength = TEST_DATA.BYTE_LENGTH, numValues = TEST_DATA.NUM_VALUES) {
44
- return {
45
- byteLength,
46
- numValues,
47
- logicalLevelTechnique1: 0,
48
- logicalLevelTechnique2: 0,
49
- physicalLevelTechnique: 0,
50
- };
51
- }
52
- // Helper: Setup RLE stream metadata for sequence encoding
53
- function mockRleStreamMetadata(byteLength = TEST_DATA.BYTE_LENGTH, numValues = TEST_DATA.NUM_VALUES, numRleValues = 2) {
54
- return {
55
- byteLength,
56
- numValues,
57
- numRleValues,
58
- logicalLevelTechnique1: 0,
59
- logicalLevelTechnique2: 0,
60
- physicalLevelTechnique: 0,
61
27
  };
62
28
  }
63
- // Helper: Mock integer decoders (INT_32 or INT_64)
64
- function mockIntegerDecoder(scalarType) {
65
- vi.spyOn(IntegerStreamDecoder, "getVectorType").mockReturnValue(VectorType.FLAT);
66
- if (scalarType === ScalarType.INT_64 || scalarType === ScalarType.UINT_64) {
67
- vi.spyOn(IntegerStreamDecoder, "decodeLongStream").mockReturnValue(new BigInt64Array([100n, 200n, 300n]));
68
- }
69
- else {
70
- vi.spyOn(IntegerStreamDecoder, "decodeIntStream").mockReturnValue(new Int32Array([100, 200, 300]));
71
- }
72
- }
73
- // Helper: Mock integer sequence decoders
74
- function mockIntegerSequenceDecoder(scalarType) {
75
- vi.spyOn(IntegerStreamDecoder, "getVectorType").mockReturnValue(VectorType.SEQUENCE);
76
- if (scalarType === ScalarType.INT_64 || scalarType === ScalarType.UINT_64) {
77
- vi.spyOn(IntegerStreamDecoder, "decodeSequenceLongStream").mockReturnValue([10n, 20n]);
78
- }
79
- else {
80
- vi.spyOn(IntegerStreamDecoder, "decodeSequenceIntStream").mockReturnValue([10, 20]);
81
- }
82
- }
83
- // Helper: Mock integer const decoders
84
- function mockIntegerConstDecoder(scalarType) {
85
- vi.spyOn(IntegerStreamDecoder, "getVectorType").mockReturnValue(VectorType.CONST);
86
- if (scalarType === ScalarType.INT_64 || scalarType === ScalarType.UINT_64) {
87
- vi.spyOn(IntegerStreamDecoder, "decodeConstLongStream").mockReturnValue(42n);
88
- }
89
- else {
90
- vi.spyOn(IntegerStreamDecoder, "decodeConstIntStream").mockReturnValue(42);
91
- }
92
- }
93
- // Helper: Mock float decoders (FLOAT or DOUBLE)
94
- function mockFloatDecoder(scalarType) {
95
- if (scalarType === ScalarType.FLOAT) {
96
- vi.spyOn(decodingUtils, "decodeFloatsLE").mockReturnValue(new Float32Array([100.5, 200.5, 300.5]));
97
- }
98
- else if (scalarType === ScalarType.DOUBLE) {
99
- vi.spyOn(decodingUtils, "decodeDoublesLE").mockReturnValue(new Float64Array([100.5, 200.5, 300.5]));
100
- }
101
- }
102
- // Helper: Mock nullable float decoders
103
- function mockNullableFloatDecoder(scalarType) {
104
- if (scalarType === ScalarType.FLOAT) {
105
- vi.spyOn(decodingUtils, "decodeNullableFloatsLE").mockReturnValue(new Float32Array([100.5, 200.5, 300.5]));
106
- }
107
- else if (scalarType === ScalarType.DOUBLE) {
108
- vi.spyOn(decodingUtils, "decodeNullableDoublesLE").mockReturnValue(new Float64Array([100.5, 200.5, 300.5]));
109
- }
110
- }
111
- // Helper: Mock nullable integer decoders
112
- function mockNullableIntegerDecoder(scalarType) {
113
- vi.spyOn(IntegerStreamDecoder, "getVectorType").mockReturnValue(VectorType.FLAT);
114
- if (scalarType === ScalarType.INT_64 || scalarType === ScalarType.UINT_64) {
115
- vi.spyOn(IntegerStreamDecoder, "decodeNullableLongStream").mockReturnValue(new BigInt64Array([100n, 200n, 300n]));
116
- }
117
- else {
118
- vi.spyOn(IntegerStreamDecoder, "decodeNullableIntStream").mockReturnValue(new Int32Array([100, 200, 300]));
119
- }
120
- }
121
- // Helper: Setup nullable column with separate nullability stream
122
- function setupNullableStreamMocks() {
123
- const metadataSpy = vi.spyOn(StreamMetadataDecoder, "decodeStreamMetadata");
124
- // First call: nullability stream
125
- metadataSpy.mockReturnValueOnce({
126
- byteLength: TEST_DATA.NULLABILITY_BYTE_LENGTH,
127
- numValues: TEST_DATA.NUM_VALUES,
128
- logicalLevelTechnique1: 0,
129
- logicalLevelTechnique2: 0,
130
- physicalLevelTechnique: 0,
29
+ describe("decodePropertyColumn - INT_32", () => {
30
+ it("should decode INT_32 column with NONE encoding (signed)", () => {
31
+ const expectedValues = new Int32Array([2, -4, 6]);
32
+ const columnMetadata = createColumnMetadata("testColumn", ScalarType.INT_32, false);
33
+ const encodedData = encodeInt32NoneColumn(expectedValues);
34
+ const offset = new IntWrapper(0);
35
+ const result = decodePropertyColumn(encodedData, offset, columnMetadata, 1, expectedValues.length);
36
+ expect(result).toBeInstanceOf(IntFlatVector);
37
+ const resultVec = result;
38
+ for (let i = 0; i < expectedValues.length; i++) {
39
+ expect(resultVec.getValue(i)).toBe(expectedValues[i]);
40
+ }
131
41
  });
132
- // Subsequent calls: data stream
133
- metadataSpy.mockReturnValue(mockStreamMetadata());
134
- // Mock the nullability bitmap decoding
135
- vi.spyOn(decodingUtils, "decodeBooleanRle").mockReturnValue(new Uint8Array([0b00000111]));
136
- }
137
- describe("decodePropertyColumn", () => {
138
- afterEach(() => vi.restoreAllMocks());
139
- describe("Number Columns - Non-Nullable - Signed Types", () => {
140
- const numberTypes = [
141
- {
142
- scalarType: ScalarType.INT_32,
143
- vectorClass: IntFlatVector,
144
- mockFn: mockIntegerDecoder,
145
- testName: "INT_32",
146
- },
147
- {
148
- scalarType: ScalarType.INT_64,
149
- vectorClass: LongFlatVector,
150
- mockFn: mockIntegerDecoder,
151
- testName: "INT_64",
152
- },
153
- ];
154
- it.each(numberTypes)("should decode $testName column", ({ scalarType, vectorClass, mockFn }) => {
155
- // Arrange
156
- vi.spyOn(StreamMetadataDecoder, "decodeStreamMetadata").mockReturnValue(mockStreamMetadata());
157
- mockFn(scalarType);
158
- const column = createColumn(scalarType, false);
159
- const data = new Uint8Array(TEST_DATA.BUFFER_SIZE);
160
- const offset = new IntWrapper(0);
161
- // Act
162
- const result = decodePropertyColumn(data, offset, column, 1, TEST_DATA.NUM_VALUES);
163
- // Assert
164
- expect(result).toBeInstanceOf(vectorClass);
165
- expect(result._name).toBe("age");
166
- expect(result.dataBuffer).toHaveLength(TEST_DATA.NUM_VALUES);
167
- });
42
+ it("should decode INT_32 column with DELTA encoding", () => {
43
+ const expectedValues = new Int32Array([2, 4, 6]);
44
+ const columnMetadata = createColumnMetadata("testColumn", ScalarType.INT_32, false);
45
+ const encodedData = encodeInt32DeltaColumn(expectedValues);
46
+ const offset = new IntWrapper(0);
47
+ const result = decodePropertyColumn(encodedData, offset, columnMetadata, 1, expectedValues.length);
48
+ expect(result).toBeInstanceOf(IntFlatVector);
49
+ const resultVec = result;
50
+ for (let i = 0; i < expectedValues.length; i++) {
51
+ expect(resultVec.getValue(i)).toBe(expectedValues[i]);
52
+ }
168
53
  });
169
- describe("Number Columns - Non-Nullable - Unsigned Types", () => {
170
- const numberTypes = [
171
- {
172
- scalarType: ScalarType.UINT_32,
173
- vectorClass: IntFlatVector,
174
- mockFn: mockIntegerDecoder,
175
- testName: "UINT_32",
176
- },
177
- {
178
- scalarType: ScalarType.UINT_64,
179
- vectorClass: LongFlatVector,
180
- mockFn: mockIntegerDecoder,
181
- testName: "UINT_64",
182
- },
183
- ];
184
- it.each(numberTypes)("should decode $testName column", ({ scalarType, vectorClass, mockFn }) => {
185
- // Arrange
186
- vi.spyOn(StreamMetadataDecoder, "decodeStreamMetadata").mockReturnValue(mockStreamMetadata());
187
- mockFn(scalarType);
188
- const column = createColumn(scalarType, false);
189
- const data = new Uint8Array(TEST_DATA.BUFFER_SIZE);
190
- const offset = new IntWrapper(0);
191
- // Act
192
- const result = decodePropertyColumn(data, offset, column, 1, TEST_DATA.NUM_VALUES);
193
- // Assert
194
- expect(result).toBeInstanceOf(vectorClass);
195
- expect(result._name).toBe("age");
196
- expect(result.dataBuffer).toHaveLength(TEST_DATA.NUM_VALUES);
197
- });
54
+ it("should decode INT_32 column with RLE encoding", () => {
55
+ const expectedValues = new Int32Array([100, 100, 100, -50, -50]);
56
+ const columnMetadata = createColumnMetadata("testColumn", ScalarType.INT_32, false);
57
+ const encodedData = encodeInt32RleColumn([
58
+ [3, 100],
59
+ [2, -50],
60
+ ]);
61
+ const offset = new IntWrapper(0);
62
+ const result = decodePropertyColumn(encodedData, offset, columnMetadata, 1, expectedValues.length);
63
+ expect(result).toBeInstanceOf(IntFlatVector);
64
+ const resultVec = result;
65
+ for (let i = 0; i < expectedValues.length; i++) {
66
+ expect(resultVec.getValue(i)).toBe(expectedValues[i]);
67
+ }
198
68
  });
199
- describe("Number Columns - Nullable - Signed Types", () => {
200
- const numberTypes = [
201
- { scalarType: ScalarType.INT_32, mockFn: mockNullableIntegerDecoder, testName: "INT_32" },
202
- { scalarType: ScalarType.INT_64, mockFn: mockNullableIntegerDecoder, testName: "INT_64" },
203
- ];
204
- it.each(numberTypes)("should decode nullable $testName column with null mask", ({ scalarType, mockFn }) => {
205
- // Arrange
206
- setupNullableStreamMocks();
207
- mockFn(scalarType);
208
- const column = createColumn(scalarType, true);
209
- const data = new Uint8Array(TEST_DATA.BUFFER_SIZE);
210
- const offset = new IntWrapper(0);
211
- // Act
212
- const result = decodePropertyColumn(data, offset, column, 2, TEST_DATA.NUM_VALUES);
213
- // Assert
214
- expect(result).toBeDefined();
215
- expect(result._name).toBe("age");
216
- });
69
+ it("should decode INT_32 column with DELTA+RLE encoding", () => {
70
+ const expectedValues = new Int32Array([10, 12, 14, 15, 16]);
71
+ const columnMetadata = createColumnMetadata("testColumn", ScalarType.INT_32, false);
72
+ const encodedData = encodeInt32DeltaRleColumn([
73
+ [1, 10],
74
+ [2, 2],
75
+ [2, 1],
76
+ ]);
77
+ const offset = new IntWrapper(0);
78
+ const result = decodePropertyColumn(encodedData, offset, columnMetadata, 1, expectedValues.length);
79
+ expect(result).toBeInstanceOf(IntFlatVector);
80
+ const resultVec = result;
81
+ for (let i = 0; i < expectedValues.length; i++) {
82
+ expect(resultVec.getValue(i)).toBe(expectedValues[i]);
83
+ }
217
84
  });
218
- describe("Number Columns - Nullable - Unsigned Types", () => {
219
- const numberTypes = [
220
- { scalarType: ScalarType.UINT_32, mockFn: mockNullableIntegerDecoder, testName: "UINT_32" },
221
- { scalarType: ScalarType.UINT_64, mockFn: mockNullableIntegerDecoder, testName: "UINT_64" },
222
- ];
223
- it.each(numberTypes)("should decode nullable $testName column with null mask", ({ scalarType, mockFn }) => {
224
- // Arrange
225
- setupNullableStreamMocks();
226
- mockFn(scalarType);
227
- const column = createColumn(scalarType, true);
228
- const data = new Uint8Array(TEST_DATA.BUFFER_SIZE);
229
- const offset = new IntWrapper(0);
230
- // Act
231
- const result = decodePropertyColumn(data, offset, column, 2, TEST_DATA.NUM_VALUES);
232
- // Assert
233
- expect(result).toBeDefined();
234
- expect(result._name).toBe("age");
235
- });
85
+ it("should decode nullable INT_32 column with null values", () => {
86
+ const expectedValues = [2, null, -4, null, 6];
87
+ const columnMetadata = createColumnMetadata("testColumn", ScalarType.INT_32, true);
88
+ const encodedData = encodeInt32NullableColumn(expectedValues);
89
+ const offset = new IntWrapper(0);
90
+ const result = decodePropertyColumn(encodedData, offset, columnMetadata, 2, expectedValues.length);
91
+ expect(result).toBeInstanceOf(IntFlatVector);
92
+ const resultVec = result;
93
+ for (let i = 0; i < expectedValues.length; i++) {
94
+ expect(resultVec.getValue(i)).toBe(expectedValues[i]);
95
+ }
236
96
  });
237
- describe("Integer Vector Encoding Types - SEQUENCE", () => {
238
- const numberTypes = [
239
- {
240
- scalarType: ScalarType.INT_32,
241
- vectorClass: IntSequenceVector,
242
- mockFn: mockIntegerSequenceDecoder,
243
- testName: "INT_32",
244
- },
245
- {
246
- scalarType: ScalarType.INT_64,
247
- vectorClass: LongSequenceVector,
248
- mockFn: mockIntegerSequenceDecoder,
249
- testName: "INT_64",
250
- },
251
- ];
252
- it.each(numberTypes)("should decode $testName with SEQUENCE encoding", ({ scalarType, vectorClass, mockFn }) => {
253
- // Arrange
254
- vi.spyOn(StreamMetadataDecoder, "decodeStreamMetadata").mockReturnValue(mockRleStreamMetadata());
255
- mockFn(scalarType);
256
- const column = createColumn(scalarType, false);
257
- const data = new Uint8Array(TEST_DATA.BUFFER_SIZE);
258
- const offset = new IntWrapper(0);
259
- // Act
260
- const result = decodePropertyColumn(data, offset, column, 1, TEST_DATA.NUM_VALUES);
261
- // Assert
262
- expect(result).toBeInstanceOf(vectorClass);
263
- expect(result._name).toBe("age");
264
- });
97
+ it("should decode INT_32 SEQUENCE vector", () => {
98
+ const numValues = 5;
99
+ const value = 10;
100
+ const columnMetadata = createColumnMetadata("testColumn", ScalarType.INT_32, false);
101
+ const encodedData = encodeInt32DeltaRleColumn([[numValues, value]]);
102
+ const offset = new IntWrapper(0);
103
+ const result = decodePropertyColumn(encodedData, offset, columnMetadata, 1, numValues);
104
+ expect(result).toBeInstanceOf(IntSequenceVector);
105
+ const seqVec = result;
106
+ expect(seqVec.getValue(0)).toBe(value);
107
+ expect(seqVec.getValue(1)).toBe(value + value);
108
+ expect(seqVec.getValue(2)).toBe(value + value * 2);
265
109
  });
266
- describe("Integer Vector Encoding Types - CONST", () => {
267
- const numberTypes = [
268
- {
269
- scalarType: ScalarType.INT_32,
270
- vectorClass: IntConstVector,
271
- mockFn: mockIntegerConstDecoder,
272
- testName: "INT_32",
273
- },
274
- {
275
- scalarType: ScalarType.INT_64,
276
- vectorClass: LongConstVector,
277
- mockFn: mockIntegerConstDecoder,
278
- testName: "INT_64",
279
- },
280
- ];
281
- it.each(numberTypes)("should decode $testName with CONST encoding", ({ scalarType, vectorClass, mockFn }) => {
282
- // Arrange
283
- vi.spyOn(StreamMetadataDecoder, "decodeStreamMetadata").mockReturnValue(mockStreamMetadata());
284
- mockFn(scalarType);
285
- const column = createColumn(scalarType, false);
286
- const data = new Uint8Array(TEST_DATA.BUFFER_SIZE);
287
- const offset = new IntWrapper(0);
288
- // Act
289
- const result = decodePropertyColumn(data, offset, column, 1, TEST_DATA.NUM_VALUES);
290
- // Assert
291
- expect(result).toBeInstanceOf(vectorClass);
292
- expect(result._name).toBe("age");
293
- });
110
+ it("should decode INT_32 CONST vector", () => {
111
+ const numValues = 5;
112
+ const constValue = 42;
113
+ const columnMetadata = createColumnMetadata("testColumn", ScalarType.INT_32, false);
114
+ const encodedData = encodeInt32RleColumn([[numValues, constValue]]);
115
+ const offset = new IntWrapper(0);
116
+ const result = decodePropertyColumn(encodedData, offset, columnMetadata, 1, numValues);
117
+ expect(result).toBeInstanceOf(IntConstVector);
118
+ const constVec = result;
119
+ expect(constVec.getValue(0)).toBe(constValue);
120
+ expect(constVec.getValue(4)).toBe(constValue);
294
121
  });
295
- describe("Float Columns - Non-Nullable", () => {
296
- const numberTypes = [
297
- {
298
- scalarType: ScalarType.FLOAT,
299
- vectorClass: FloatFlatVector,
300
- mockFn: mockFloatDecoder,
301
- testName: "FLOAT",
302
- },
303
- {
304
- scalarType: ScalarType.DOUBLE,
305
- vectorClass: DoubleFlatVector,
306
- mockFn: mockFloatDecoder,
307
- testName: "DOUBLE",
308
- },
309
- ];
310
- it.each(numberTypes)("should decode $testName column", ({ scalarType, vectorClass, mockFn }) => {
311
- // Arrange
312
- vi.spyOn(StreamMetadataDecoder, "decodeStreamMetadata").mockReturnValue(mockStreamMetadata());
313
- mockFn(scalarType);
314
- const column = createColumn(scalarType, false);
315
- const data = new Uint8Array(TEST_DATA.BUFFER_SIZE);
316
- const offset = new IntWrapper(0);
317
- // Act
318
- const result = decodePropertyColumn(data, offset, column, 1, TEST_DATA.NUM_VALUES);
319
- // Assert
320
- expect(result).toBeInstanceOf(vectorClass);
321
- expect(result._name).toBe("age");
322
- expect(result.dataBuffer).toHaveLength(TEST_DATA.NUM_VALUES);
323
- });
122
+ });
123
+ describe("decodePropertyColumn - UINT_32", () => {
124
+ it("should decode UINT_32 column with NONE encoding (unsigned)", () => {
125
+ const expectedValues = new Uint32Array([2, 4, 6, 100]);
126
+ const columnMetadata = createColumnMetadata("testColumn", ScalarType.UINT_32, false);
127
+ const encodedData = encodeUint32Column(expectedValues);
128
+ const offset = new IntWrapper(0);
129
+ const result = decodePropertyColumn(encodedData, offset, columnMetadata, 1, expectedValues.length);
130
+ expect(result).toBeInstanceOf(IntFlatVector);
131
+ const resultVec = result;
132
+ for (let i = 0; i < expectedValues.length; i++) {
133
+ expect(resultVec.getValue(i)).toBe(expectedValues[i]);
134
+ }
324
135
  });
325
- describe("Float Columns - Nullable", () => {
326
- const numberTypes = [
327
- {
328
- scalarType: ScalarType.FLOAT,
329
- vectorClass: FloatFlatVector,
330
- mockFn: mockNullableFloatDecoder,
331
- testName: "FLOAT",
332
- },
333
- {
334
- scalarType: ScalarType.DOUBLE,
335
- vectorClass: DoubleFlatVector,
336
- mockFn: mockNullableFloatDecoder,
337
- testName: "DOUBLE",
338
- },
339
- ];
340
- it.each(numberTypes)("should decode nullable $testName column with null mask", ({ scalarType, vectorClass, mockFn }) => {
341
- // Arrange
342
- setupNullableStreamMocks();
343
- mockFn(scalarType);
344
- const column = createColumn(scalarType, true);
345
- const data = new Uint8Array(TEST_DATA.BUFFER_SIZE);
346
- const offset = new IntWrapper(0);
347
- // Act
348
- const result = decodePropertyColumn(data, offset, column, 2, TEST_DATA.NUM_VALUES);
349
- // Assert
350
- expect(result).toBeInstanceOf(vectorClass);
351
- expect(result._name).toBe("age");
352
- });
136
+ });
137
+ describe("decodePropertyColumn - INT_64", () => {
138
+ it("should decode INT_64 column with NONE encoding (signed)", () => {
139
+ const expectedValues = new BigInt64Array([2n, -4n, 6n]);
140
+ const columnMetadata = createColumnMetadata("testColumn", ScalarType.INT_64, false);
141
+ const encodedData = encodeInt64NoneColumn(expectedValues);
142
+ const offset = new IntWrapper(0);
143
+ const result = decodePropertyColumn(encodedData, offset, columnMetadata, 1, expectedValues.length);
144
+ expect(result).toBeInstanceOf(LongFlatVector);
145
+ const resultVec = result;
146
+ for (let i = 0; i < expectedValues.length; i++) {
147
+ expect(resultVec.getValue(i)).toBe(expectedValues[i]);
148
+ }
353
149
  });
354
- describe("Boolean Columns", () => {
355
- it("should decode non-nullable BOOLEAN column", () => {
356
- // Arrange
357
- vi.spyOn(StreamMetadataDecoder, "decodeStreamMetadata").mockReturnValue(mockStreamMetadata());
358
- vi.spyOn(decodingUtils, "decodeBooleanRle").mockReturnValue(new Uint8Array([0b00000111]));
359
- const column = createColumn(ScalarType.BOOLEAN, false);
360
- const data = new Uint8Array(TEST_DATA.BUFFER_SIZE);
361
- const offset = new IntWrapper(0);
362
- // Act
363
- const result = decodePropertyColumn(data, offset, column, 1, TEST_DATA.NUM_VALUES);
364
- // Assert
365
- expect(result).toBeInstanceOf(BooleanFlatVector);
366
- expect(result._name).toBe("age");
367
- });
368
- it("should decode nullable BOOLEAN column with null mask", () => {
369
- // Arrange
370
- setupNullableStreamMocks();
371
- vi.spyOn(decodingUtils, "decodeNullableBooleanRle").mockReturnValue(new Uint8Array([0b00000111]));
372
- const column = createColumn(ScalarType.BOOLEAN, true);
373
- const data = new Uint8Array(TEST_DATA.BUFFER_SIZE);
374
- const offset = new IntWrapper(0);
375
- // Act
376
- const result = decodePropertyColumn(data, offset, column, 2, TEST_DATA.NUM_VALUES);
377
- // Assert
378
- expect(result).toBeInstanceOf(BooleanFlatVector);
379
- expect(result._name).toBe("age");
380
- });
150
+ it("should decode INT_64 column with DELTA encoding", () => {
151
+ const expectedValues = new BigInt64Array([2n, 4n, 6n]);
152
+ const columnMetadata = createColumnMetadata("testColumn", ScalarType.INT_64, false);
153
+ const encodedData = encodeInt64DeltaColumn(expectedValues);
154
+ const offset = new IntWrapper(0);
155
+ const result = decodePropertyColumn(encodedData, offset, columnMetadata, 1, expectedValues.length);
156
+ expect(result).toBeInstanceOf(LongFlatVector);
157
+ const resultVec = result;
158
+ for (let i = 0; i < expectedValues.length; i++) {
159
+ expect(resultVec.getValue(i)).toBe(expectedValues[i]);
160
+ }
381
161
  });
382
- describe("String Columns - Nullable", () => {
383
- const streamConfigs = [
384
- { totalStreams: 2, description: "single data stream" },
385
- { totalStreams: 4, description: "multiple data streams" },
386
- ];
387
- it.each(streamConfigs)("should decode nullable STRING with $description", ({ totalStreams }) => {
388
- // Arrange
389
- setupNullableStreamMocks();
390
- const mockStringVector = { name: "age" };
391
- const stringDecodeSpy = vi.spyOn(StringDecoder, "decodeString").mockReturnValue(mockStringVector);
392
- const column = createColumn(ScalarType.STRING, true);
393
- const data = new Uint8Array(TEST_DATA.BUFFER_SIZE);
394
- const offset = new IntWrapper(0);
395
- // Act
396
- const result = decodePropertyColumn(data, offset, column, totalStreams, TEST_DATA.NUM_VALUES);
397
- // Assert
398
- expect(result.name).toBe(mockStringVector.name);
399
- });
162
+ it("should decode INT_64 column with RLE encoding", () => {
163
+ const expectedValues = new BigInt64Array([100n, 100n, 100n, -50n, -50n]);
164
+ const columnMetadata = createColumnMetadata("testColumn", ScalarType.INT_64, false);
165
+ const encodedData = encodeInt64RleColumn([
166
+ [3, 100n],
167
+ [2, -50n],
168
+ ]);
169
+ const offset = new IntWrapper(0);
170
+ const result = decodePropertyColumn(encodedData, offset, columnMetadata, 1, expectedValues.length);
171
+ expect(result).toBeInstanceOf(LongFlatVector);
172
+ const resultVec = result;
173
+ for (let i = 0; i < expectedValues.length; i++) {
174
+ expect(resultVec.getValue(i)).toBe(expectedValues[i]);
175
+ }
400
176
  });
401
- describe("Column Filtering", () => {
402
- it("should return null when column NOT in propertyColumnNames filter", () => {
403
- // Arrange
404
- vi.spyOn(StreamMetadataDecoder, "decodeStreamMetadata").mockReturnValue(mockStreamMetadata());
405
- const skipColumnSpy = vi.spyOn(decodingUtils, "skipColumn");
406
- const column = createColumn(ScalarType.STRING);
407
- const filterList = new Set(["name", "value"]);
408
- const data = new Uint8Array(TEST_DATA.BUFFER_SIZE);
409
- const offset = new IntWrapper(0);
410
- // Act
411
- const result = decodePropertyColumn(data, offset, column, 1, TEST_DATA.NUM_VALUES, filterList);
412
- // Assert
413
- expect(result).toBeNull();
414
- expect(skipColumnSpy).toHaveBeenCalledWith(1, data, offset);
415
- });
416
- it("should decode column when it IS in propertyColumnNames filter", () => {
417
- // Arrange
418
- vi.spyOn(StreamMetadataDecoder, "decodeStreamMetadata").mockReturnValue(mockStreamMetadata());
419
- vi.spyOn(decodingUtils, "decodeBooleanRle").mockReturnValue(new Uint8Array([0b00000111]));
420
- const column = createColumn(ScalarType.BOOLEAN);
421
- const filterList = new Set(["age", "name"]);
422
- const data = new Uint8Array(TEST_DATA.BUFFER_SIZE);
423
- const offset = new IntWrapper(0);
424
- // Act
425
- const result = decodePropertyColumn(data, offset, column, 1, TEST_DATA.NUM_VALUES, filterList);
426
- // Assert
427
- expect(result).toBeInstanceOf(BooleanFlatVector);
428
- });
429
- it("should ignore filter when propertyColumnNames is undefined", () => {
430
- // Arrange
431
- vi.spyOn(StreamMetadataDecoder, "decodeStreamMetadata").mockReturnValue(mockStreamMetadata());
432
- vi.spyOn(decodingUtils, "decodeBooleanRle").mockReturnValue(new Uint8Array([0b00000111]));
433
- const column = createColumn(ScalarType.BOOLEAN);
434
- const data = new Uint8Array(TEST_DATA.BUFFER_SIZE);
435
- const offset = new IntWrapper(0);
436
- // Act
437
- const result = decodePropertyColumn(data, offset, column, 1, TEST_DATA.NUM_VALUES, undefined);
438
- // Assert
439
- expect(result).toBeInstanceOf(BooleanFlatVector);
440
- });
441
- it("should handle empty filter set", () => {
442
- // Arrange
443
- vi.spyOn(StreamMetadataDecoder, "decodeStreamMetadata").mockReturnValue(mockStreamMetadata());
444
- const skipColumnSpy = vi.spyOn(decodingUtils, "skipColumn");
445
- const column = createColumn(ScalarType.BOOLEAN);
446
- const filterList = new Set();
447
- const data = new Uint8Array(TEST_DATA.BUFFER_SIZE);
448
- const offset = new IntWrapper(0);
449
- // Act
450
- const result = decodePropertyColumn(data, offset, column, 1, TEST_DATA.NUM_VALUES, filterList);
451
- // Assert
452
- expect(result).toBeNull();
453
- expect(skipColumnSpy).toHaveBeenCalled();
454
- });
177
+ it("should decode INT_64 column with DELTA+RLE encoding", () => {
178
+ const expectedValues = new BigInt64Array([10n, 12n, 14n, 15n, 16n]);
179
+ const columnMetadata = createColumnMetadata("testColumn", ScalarType.INT_64, false);
180
+ const encodedData = encodeInt64DeltaRleColumn([
181
+ [1, 10n],
182
+ [2, 2n],
183
+ [2, 1n],
184
+ ]);
185
+ const offset = new IntWrapper(0);
186
+ const result = decodePropertyColumn(encodedData, offset, columnMetadata, 1, expectedValues.length);
187
+ expect(result).toBeInstanceOf(LongFlatVector);
188
+ const resultVec = result;
189
+ for (let i = 0; i < expectedValues.length; i++) {
190
+ expect(resultVec.getValue(i)).toBe(expectedValues[i]);
191
+ }
192
+ });
193
+ it("should decode nullable INT_64 column with null values", () => {
194
+ const expectedValues = [2n, null, -4n, null, 6n];
195
+ const columnMetadata = createColumnMetadata("testColumn", ScalarType.INT_64, true);
196
+ const encodedData = encodeInt64NullableColumn(expectedValues);
197
+ const offset = new IntWrapper(0);
198
+ const result = decodePropertyColumn(encodedData, offset, columnMetadata, 2, expectedValues.length);
199
+ expect(result).toBeInstanceOf(LongFlatVector);
200
+ const resultVec = result;
201
+ for (let i = 0; i < expectedValues.length; i++) {
202
+ expect(resultVec.getValue(i)).toBe(expectedValues[i]);
203
+ }
204
+ });
205
+ it("should decode INT_64 SEQUENCE vector", () => {
206
+ const numValues = 5;
207
+ const value = 10n;
208
+ const columnMetadata = createColumnMetadata("testColumn", ScalarType.INT_64, false);
209
+ const encodedData = encodeInt64DeltaRleColumn([[numValues, value]]);
210
+ const offset = new IntWrapper(0);
211
+ const result = decodePropertyColumn(encodedData, offset, columnMetadata, 1, numValues);
212
+ expect(result).toBeInstanceOf(LongSequenceVector);
213
+ const seqVec = result;
214
+ expect(seqVec.getValue(0)).toBe(value);
215
+ expect(seqVec.getValue(1)).toBe(value + value);
216
+ expect(seqVec.getValue(2)).toBe(value + value * 2n);
217
+ });
218
+ it("should decode INT_64 CONST vector", () => {
219
+ const numValues = 5;
220
+ const constValue = 42n;
221
+ const columnMetadata = createColumnMetadata("testColumn", ScalarType.INT_64, false);
222
+ const encodedData = encodeInt64RleColumn([[numValues, constValue]]);
223
+ const offset = new IntWrapper(0);
224
+ const result = decodePropertyColumn(encodedData, offset, columnMetadata, 1, numValues);
225
+ expect(result).toBeInstanceOf(LongConstVector);
226
+ const constVec = result;
227
+ expect(constVec.getValue(0)).toBe(constValue);
228
+ expect(constVec.getValue(4)).toBe(constValue);
229
+ });
230
+ });
231
+ describe("decodePropertyColumn - UINT_64", () => {
232
+ it("should decode UINT_64 column with NONE encoding (unsigned)", () => {
233
+ const expectedValues = new BigUint64Array([2n, 4n, 6n, 100n]);
234
+ const columnMetadata = createColumnMetadata("testColumn", ScalarType.UINT_64, false);
235
+ const encodedData = encodeUint64Column(expectedValues);
236
+ const offset = new IntWrapper(0);
237
+ const result = decodePropertyColumn(encodedData, offset, columnMetadata, 1, expectedValues.length);
238
+ expect(result).toBeInstanceOf(LongFlatVector);
239
+ const resultVec = result;
240
+ for (let i = 0; i < expectedValues.length; i++) {
241
+ expect(resultVec.getValue(i)).toBe(expectedValues[i]);
242
+ }
243
+ });
244
+ it("should decode nullable UINT_64 column with null values", () => {
245
+ const expectedValues = [2n, null, 4n, null, 6n];
246
+ const columnMetadata = createColumnMetadata("testColumn", ScalarType.UINT_64, true);
247
+ const encodedData = encodeUint64NullableColumn(expectedValues);
248
+ const offset = new IntWrapper(0);
249
+ const result = decodePropertyColumn(encodedData, offset, columnMetadata, 2, expectedValues.length);
250
+ expect(result).toBeInstanceOf(LongFlatVector);
251
+ const resultVec = result;
252
+ for (let i = 0; i < expectedValues.length; i++) {
253
+ expect(resultVec.getValue(i)).toBe(expectedValues[i]);
254
+ }
255
+ });
256
+ });
257
+ describe("decodePropertyColumn - FLOAT", () => {
258
+ it("should decode non-nullable FLOAT column", () => {
259
+ const expectedValues = new Float32Array([1.5, 2.7, -3.14, 4.2]);
260
+ const columnMetadata = createColumnMetadata("testColumn", ScalarType.FLOAT, false);
261
+ const encodedData = encodeFloatColumn(expectedValues);
262
+ const offset = new IntWrapper(0);
263
+ const result = decodePropertyColumn(encodedData, offset, columnMetadata, 1, expectedValues.length);
264
+ expect(result).toBeInstanceOf(FloatFlatVector);
265
+ const resultVec = result;
266
+ expect(resultVec.size).toBe(expectedValues.length);
267
+ for (let i = 0; i < expectedValues.length; i++) {
268
+ expect(resultVec.getValue(i)).toBeCloseTo(expectedValues[i], 5);
269
+ }
270
+ });
271
+ it("should decode nullable FLOAT column with null values", () => {
272
+ const expectedValues = [1.5, null, 2.7, null, 3.14];
273
+ const columnMetadata = createColumnMetadata("testColumn", ScalarType.FLOAT, true);
274
+ const encodedData = encodeFloatNullableColumn(expectedValues);
275
+ const offset = new IntWrapper(0);
276
+ const result = decodePropertyColumn(encodedData, offset, columnMetadata, 2, expectedValues.length);
277
+ expect(result).toBeInstanceOf(FloatFlatVector);
278
+ const resultVec = result;
279
+ expect(resultVec.size).toBe(expectedValues.length);
280
+ expect(resultVec.getValue(0)).toBeCloseTo(1.5, 5);
281
+ expect(resultVec.getValue(1)).toBe(null); // null value
282
+ expect(resultVec.getValue(2)).toBeCloseTo(2.7, 5);
283
+ expect(resultVec.getValue(3)).toBe(null); // null value
284
+ expect(resultVec.getValue(4)).toBeCloseTo(3.14, 5);
285
+ });
286
+ it("should handle offset correctly after decoding FLOAT column", () => {
287
+ const expectedValues = new Float32Array([1.0, 2.0, 3.0]);
288
+ const columnMetadata = createColumnMetadata("testColumn", ScalarType.FLOAT, false);
289
+ const encodedData = encodeFloatColumn(expectedValues);
290
+ const offset = new IntWrapper(0);
291
+ decodePropertyColumn(encodedData, offset, columnMetadata, 1, expectedValues.length);
292
+ // Verify offset was advanced correctly
293
+ expect(offset.get()).toBe(encodedData.length);
294
+ });
295
+ });
296
+ describe("decodePropertyColumn - BOOLEAN", () => {
297
+ it("should decode non-nullable BOOLEAN column with RLE", () => {
298
+ const booleanValues = [true, false, true, true, false, false, false, true];
299
+ const columnMetadata = createColumnMetadata("testColumn", ScalarType.BOOLEAN, false);
300
+ const encodedData = encodeBooleanColumn(booleanValues);
301
+ const offset = new IntWrapper(0);
302
+ const result = decodePropertyColumn(encodedData, offset, columnMetadata, 1, booleanValues.length);
303
+ expect(result).toBeInstanceOf(BooleanFlatVector);
304
+ const boolVec = result;
305
+ for (let i = 0; i < booleanValues.length; i++) {
306
+ expect(boolVec.getValue(i)).toBe(booleanValues[i]);
307
+ }
308
+ });
309
+ it("should decode nullable BOOLEAN column with RLE and present stream", () => {
310
+ const expectedValues = [true, null, false, null, true];
311
+ const columnMetadata = createColumnMetadata("testColumn", ScalarType.BOOLEAN, true);
312
+ const encodedData = encodeBooleanNullableColumn(expectedValues);
313
+ const offset = new IntWrapper(0);
314
+ const result = decodePropertyColumn(encodedData, offset, columnMetadata, 2, expectedValues.length);
315
+ expect(result).toBeInstanceOf(BooleanFlatVector);
316
+ const boolVec = result;
317
+ expect(boolVec.getValue(0)).toBe(true);
318
+ expect(boolVec.getValue(1)).toBe(null);
319
+ expect(boolVec.getValue(2)).toBe(false);
320
+ expect(boolVec.getValue(3)).toBe(null);
321
+ expect(boolVec.getValue(4)).toBe(true);
322
+ });
323
+ });
324
+ describe("decodePropertyColumn - DOUBLE", () => {
325
+ it("should decode non-nullable DOUBLE column", () => {
326
+ const expectedValues = new Float32Array([1.2345, 5.4321, 1.33742]);
327
+ const columnMetadata = createColumnMetadata("testColumn", ScalarType.DOUBLE, false);
328
+ const encodedData = encodeDoubleColumn(expectedValues);
329
+ const offset = new IntWrapper(0);
330
+ const result = decodePropertyColumn(encodedData, offset, columnMetadata, 1, expectedValues.length);
331
+ expect(result).toBeInstanceOf(DoubleFlatVector);
332
+ const resultVec = result;
333
+ expect(resultVec.size).toBe(expectedValues.length);
334
+ for (let i = 0; i < expectedValues.length; i++) {
335
+ expect(resultVec.getValue(i)).toBeCloseTo(expectedValues[i], 5);
336
+ }
337
+ });
338
+ it("should decode nullable DOUBLE column with null values", () => {
339
+ const expectedValues = [1.5, null, 2.7, null, 3.14159];
340
+ const columnMetadata = createColumnMetadata("testColumn", ScalarType.DOUBLE, true);
341
+ const encodedData = encodeDoubleNullableColumn(expectedValues);
342
+ const offset = new IntWrapper(0);
343
+ const result = decodePropertyColumn(encodedData, offset, columnMetadata, 2, expectedValues.length);
344
+ expect(result).toBeInstanceOf(DoubleFlatVector);
345
+ const resultVec = result;
346
+ expect(resultVec.size).toBe(expectedValues.length);
347
+ expect(resultVec.getValue(0)).toBeCloseTo(1.5, 5);
348
+ expect(resultVec.getValue(1)).toBe(null); // null value
349
+ expect(resultVec.getValue(2)).toBeCloseTo(2.7, 5);
350
+ expect(resultVec.getValue(3)).toBe(null); // null value
351
+ expect(resultVec.getValue(4)).toBeCloseTo(3.14159, 5);
352
+ });
353
+ it("should handle offset correctly after decoding DOUBLE column", () => {
354
+ const expectedValues = new Float32Array([1.33742, 1.2345, 5.4321]);
355
+ const columnMetadata = createColumnMetadata("testColumn", ScalarType.DOUBLE, false);
356
+ const encodedData = encodeDoubleColumn(expectedValues);
357
+ const offset = new IntWrapper(0);
358
+ decodePropertyColumn(encodedData, offset, columnMetadata, 1, expectedValues.length);
359
+ // Verify offset was advanced correctly
360
+ expect(offset.get()).toBe(encodedData.length);
455
361
  });
456
- describe("Edge Cases", () => {
457
- it("should handle single value column", () => {
458
- // Arrange
459
- vi.spyOn(StreamMetadataDecoder, "decodeStreamMetadata").mockReturnValue(mockStreamMetadata(12, 1));
460
- vi.spyOn(IntegerStreamDecoder, "getVectorType").mockReturnValue(VectorType.FLAT);
461
- vi.spyOn(IntegerStreamDecoder, "decodeIntStream").mockReturnValue(new Int32Array([42]));
462
- const column = createColumn(ScalarType.INT_32);
463
- const data = new Uint8Array(TEST_DATA.BUFFER_SIZE);
362
+ });
363
+ describe("decodePropertyColumn - STRING", () => {
364
+ describe("basic functionality", () => {
365
+ it("should decode single field with shared dictionary", () => {
366
+ const dictionaryStrings = ["apple", "banana", "peach", "date"];
367
+ const { lengthStream, dataStream } = encodeSharedDictionary(dictionaryStrings);
368
+ const fieldStreams = encodeStructField([0, 1, 2, 3], [true, true, true, true]);
369
+ const completeData = concatenateBuffers(lengthStream, dataStream, fieldStreams);
370
+ const columnMetadata = createColumnMetadataForStruct("address", [{ name: "street" }]);
464
371
  const offset = new IntWrapper(0);
465
- // Act
466
- const result = decodePropertyColumn(data, offset, column, 1, 1);
467
- // Assert
468
- expect(result).toBeInstanceOf(IntFlatVector);
469
- expect(result.dataBuffer).toHaveLength(1);
470
- });
471
- it("should handle large column with many values", () => {
472
- // Arrange
473
- const largeNumValues = 100000;
474
- vi.spyOn(StreamMetadataDecoder, "decodeStreamMetadata").mockReturnValue(mockStreamMetadata(400000, largeNumValues));
475
- vi.spyOn(IntegerStreamDecoder, "getVectorType").mockReturnValue(VectorType.FLAT);
476
- const largeArray = new Int32Array(largeNumValues);
477
- for (let i = 0; i < largeNumValues; i++) {
478
- largeArray[i] = i;
372
+ const result = decodePropertyColumn(completeData, offset, columnMetadata, 1, dictionaryStrings.length);
373
+ expect(result).toHaveLength(1);
374
+ expect(result[0]).toBeInstanceOf(StringDictionaryVector);
375
+ expect(result[0].name).toBe("address:street");
376
+ for (let i = 0; i < dictionaryStrings.length; i++) {
377
+ expect(result[0].getValue(i)).toBe(dictionaryStrings[i]);
479
378
  }
480
- vi.spyOn(IntegerStreamDecoder, "decodeIntStream").mockReturnValue(largeArray);
481
- const column = createColumn(ScalarType.INT_32);
482
- const data = new Uint8Array(TEST_DATA.BUFFER_SIZE);
483
- const offset = new IntWrapper(0);
484
- // Act
485
- const result = decodePropertyColumn(data, offset, column, 1, largeNumValues);
486
- // Assert
487
- expect(result).toBeInstanceOf(IntFlatVector);
488
- expect(result.dataBuffer).toHaveLength(largeNumValues);
489
- });
490
- it("should handle zero numValues gracefully", () => {
491
- // Arrange
492
- vi.spyOn(StreamMetadataDecoder, "decodeStreamMetadata").mockReturnValue({
493
- ...mockStreamMetadata(),
494
- numValues: 0,
495
- });
496
- vi.spyOn(IntegerStreamDecoder, "getVectorType").mockReturnValue(VectorType.FLAT);
497
- vi.spyOn(IntegerStreamDecoder, "decodeIntStream").mockReturnValue(new Int32Array(0));
498
- const column = createColumn(ScalarType.INT_32);
499
- const data = new Uint8Array(TEST_DATA.BUFFER_SIZE);
500
- const offset = new IntWrapper(0);
501
- // Act
502
- const result = decodePropertyColumn(data, offset, column, 1, 0);
503
- // Assert
504
- expect(result).toBeInstanceOf(IntFlatVector);
505
- expect(result.dataBuffer).toHaveLength(0);
506
- });
507
- it("should handle multiple sequential columns with offset advancement", () => {
508
- // Arrange
509
- vi.spyOn(StreamMetadataDecoder, "decodeStreamMetadata").mockReturnValue(mockStreamMetadata(12, 3));
510
- vi.spyOn(IntegerStreamDecoder, "getVectorType").mockReturnValue(VectorType.FLAT);
511
- vi.spyOn(IntegerStreamDecoder, "decodeIntStream").mockReturnValue(new Int32Array([100, 200, 300]));
512
- const column1 = createColumn(ScalarType.INT_32);
513
- const column2 = createColumn(ScalarType.INT_32);
514
- const data = new Uint8Array(TEST_DATA.BUFFER_SIZE);
515
- const offset = new IntWrapper(0);
516
- // Act
517
- const result1 = decodePropertyColumn(data, offset, column1, 1, TEST_DATA.NUM_VALUES);
518
- const offsetAfterFirst = offset.get();
519
- const result2 = decodePropertyColumn(data, offset, column2, 1, TEST_DATA.NUM_VALUES);
520
- const offsetAfterSecond = offset.get();
521
- // Assert
522
- expect(result1).toBeInstanceOf(IntFlatVector);
523
- expect(result2).toBeInstanceOf(IntFlatVector);
524
- expect(offsetAfterSecond).toEqual(offsetAfterFirst);
525
- });
526
- it("should handle non-scalar column type returning null", () => {
527
- // Arrange
528
- const column = {
529
- name: "complex",
530
- nullable: false,
531
- columnScope: null,
532
- type: "complexType",
533
- complexType: { type: "arrayType" },
534
- scalarType: null,
535
- };
536
- const data = new Uint8Array(TEST_DATA.BUFFER_SIZE);
537
- const offset = new IntWrapper(0);
538
- // Act
539
- const result = decodePropertyColumn(data, offset, column, 2, TEST_DATA.NUM_VALUES);
540
- // Assert
541
- expect(result).toBeNull();
542
379
  });
543
380
  });
544
- describe("Offset Management", () => {
545
- it("should handle offset at non-zero starting position", () => {
546
- // Arrange
547
- vi.spyOn(StreamMetadataDecoder, "decodeStreamMetadata").mockReturnValue(mockStreamMetadata());
548
- vi.spyOn(IntegerStreamDecoder, "getVectorType").mockReturnValue(VectorType.FLAT);
549
- vi.spyOn(IntegerStreamDecoder, "decodeIntStream").mockReturnValue(new Int32Array([100, 200, 300]));
550
- const column = createColumn(ScalarType.INT_32);
551
- const data = new Uint8Array(TEST_DATA.BUFFER_SIZE);
552
- const startOffset = 50;
553
- const offset = new IntWrapper(startOffset);
554
- // Act
555
- const result = decodePropertyColumn(data, offset, column, 1, TEST_DATA.NUM_VALUES);
556
- // Assert
557
- expect(result).toBeInstanceOf(IntFlatVector);
558
- expect(offset.get()).toEqual(startOffset);
559
- });
560
- it("should correctly skip columns with filterList and advance offset", () => {
561
- // Arrange
562
- vi.spyOn(StreamMetadataDecoder, "decodeStreamMetadata").mockReturnValue(mockStreamMetadata());
563
- const skipColumnSpy = vi
564
- .spyOn(decodingUtils, "skipColumn")
565
- .mockImplementation((numStreams, data, offset) => {
566
- offset.add(12 * numStreams); // Simulate skipping
567
- });
568
- const column = createColumn(ScalarType.INT_32);
569
- const filterList = new Set(["other_column"]);
570
- const data = new Uint8Array(TEST_DATA.BUFFER_SIZE);
571
- const offset = new IntWrapper(0);
572
- const startOffset = offset.get();
573
- // Act
574
- const result = decodePropertyColumn(data, offset, column, 3, TEST_DATA.NUM_VALUES, filterList);
575
- // Assert
576
- expect(result).toBeNull();
577
- expect(offset.get()).toBeGreaterThan(startOffset);
578
- expect(skipColumnSpy).toHaveBeenCalledWith(3, data, offset);
579
- });
381
+ });
382
+ describe("decodePropertyColumn - Edge Cases", () => {
383
+ it("should filter columns with propertyColumnNames set", () => {
384
+ const expectedValues = new Int32Array([1, 2, 3]);
385
+ const columnMetadata = createColumnMetadata("includedColumn", ScalarType.INT_32, false);
386
+ const encodedData = encodeInt32NoneColumn(expectedValues);
387
+ const propertyColumnNames = new Set(["includedColumn"]);
388
+ const offset = new IntWrapper(0);
389
+ const result = decodePropertyColumn(encodedData, offset, columnMetadata, 1, expectedValues.length, propertyColumnNames);
390
+ expect(result).toBeInstanceOf(IntFlatVector);
391
+ const resultVec = result;
392
+ for (let i = 0; i < expectedValues.length; i++) {
393
+ expect(resultVec.getValue(i)).toBe(expectedValues[i]);
394
+ }
580
395
  });
581
- describe("Type Consistency Checks", () => {
582
- it("should preserve column metadata in returned vector", () => {
583
- // Arrange
584
- vi.spyOn(StreamMetadataDecoder, "decodeStreamMetadata").mockReturnValue(mockStreamMetadata());
585
- vi.spyOn(IntegerStreamDecoder, "getVectorType").mockReturnValue(VectorType.FLAT);
586
- vi.spyOn(IntegerStreamDecoder, "decodeIntStream").mockReturnValue(new Int32Array([10, 20, 30]));
587
- const column = createColumn(ScalarType.INT_32);
588
- const data = new Uint8Array(TEST_DATA.BUFFER_SIZE);
589
- const offset = new IntWrapper(0);
590
- // Act
591
- const result = decodePropertyColumn(data, offset, column, 1, TEST_DATA.NUM_VALUES);
592
- // Assert
593
- expect(result._name).toBe(column.name);
594
- });
595
- it("should handle all signed and unsigned type combinations", () => {
596
- // Arrange
597
- const types = [ScalarType.INT_32, ScalarType.UINT_32, ScalarType.INT_64, ScalarType.UINT_64];
598
- types.forEach((scalarType) => {
599
- vi.spyOn(StreamMetadataDecoder, "decodeStreamMetadata").mockReturnValue(mockStreamMetadata());
600
- mockIntegerDecoder(scalarType);
601
- const column = createColumn(scalarType, false);
602
- const data = new Uint8Array(TEST_DATA.BUFFER_SIZE);
603
- const offset = new IntWrapper(0);
604
- // Act
605
- const result = decodePropertyColumn(data, offset, column, 1, TEST_DATA.NUM_VALUES);
606
- // Assert
607
- expect(result).toBeDefined();
608
- expect(result._name).toBe("age");
609
- vi.restoreAllMocks();
610
- });
611
- });
396
+ it("should skip column when not in propertyColumnNames filter", () => {
397
+ const expectedValues = new Int32Array([1, 2, 3]);
398
+ const columnMetadata = createColumnMetadata("excludedColumn", ScalarType.INT_32, false);
399
+ const encodedData = encodeInt32NoneColumn(expectedValues);
400
+ const propertyColumnNames = new Set(["someOtherColumn"]);
401
+ const offset = new IntWrapper(0);
402
+ const result = decodePropertyColumn(encodedData, offset, columnMetadata, 1, expectedValues.length, propertyColumnNames);
403
+ // Should return null and advance the offset past the skipped data
404
+ expect(result).toBe(null);
405
+ expect(offset.get()).toBe(encodedData.length);
612
406
  });
613
- describe("Error Scenarios", () => {
614
- it("should handle invalid scalar type gracefully", () => {
615
- // Arrange
616
- vi.spyOn(StreamMetadataDecoder, "decodeStreamMetadata").mockReturnValue(mockStreamMetadata());
617
- const column = createColumn(999); // Invalid type
618
- const data = new Uint8Array(TEST_DATA.BUFFER_SIZE);
619
- const offset = new IntWrapper(0);
620
- // Act & Assert
621
- expect(() => {
622
- decodePropertyColumn(data, offset, column, 1, TEST_DATA.NUM_VALUES);
623
- }).toThrow();
624
- });
625
- it("should handle mismatched numStreams for string type", () => {
626
- // Arrange
627
- vi.spyOn(StreamMetadataDecoder, "decodeStreamMetadata").mockReturnValue(mockStreamMetadata());
628
- const column = {
629
- name: "stringCol",
630
- nullable: false,
631
- columnScope: null,
632
- type: "stringType",
633
- scalarType: null,
634
- complexType: null,
635
- };
636
- const data = new Uint8Array(TEST_DATA.BUFFER_SIZE);
637
- const offset = new IntWrapper(0);
638
- // Act
639
- const result = decodePropertyColumn(data, offset, column, 2, TEST_DATA.NUM_VALUES);
640
- // Assert
641
- expect(result).toBeNull();
642
- });
407
+ it("should return null for empty columns (numStreams === 0)", () => {
408
+ const columnMetadata = createColumnMetadata("emptyColumn", ScalarType.INT_32, false);
409
+ const offset = new IntWrapper(0);
410
+ const data = new Uint8Array(0);
411
+ const result = decodePropertyColumn(data, offset, columnMetadata, 0, 0);
412
+ expect(result).toBeNull();
413
+ });
414
+ it("should return null for complex type with numStreams != 1", () => {
415
+ // Create a struct/complex type column
416
+ const columnMetadata = createColumnMetadataForStruct("structColumn", [
417
+ { name: "field1", type: ScalarType.INT_32 },
418
+ { name: "field2", type: ScalarType.STRING },
419
+ ]);
420
+ const offset = new IntWrapper(0);
421
+ const data = new Uint8Array(10);
422
+ const result = decodePropertyColumn(data, offset, columnMetadata, 2, 5);
423
+ expect(result).toBeNull();
424
+ });
425
+ it("should throw error for unsupported data type", () => {
426
+ const columnMetadata = createColumnMetadata("unsupportedColumn", ScalarType.INT_8, false);
427
+ const encodedData = encodeInt32NoneColumn(new Int32Array([1, 2, 3]));
428
+ const offset = new IntWrapper(0);
429
+ expect(() => {
430
+ decodePropertyColumn(encodedData, offset, columnMetadata, 1, 3);
431
+ }).toThrow();
643
432
  });
644
433
  });
645
434
  //# sourceMappingURL=propertyDecoder.spec.js.map