@loaders.gl/parquet 5.0.0-alpha.2 → 5.0.0-alpha.3
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/LICENSE +1 -1
- package/dist/bundled.d.ts +1 -1
- package/dist/bundled.d.ts.map +1 -1
- package/dist/bundled.js.map +1 -1
- package/dist/delta-format.d.ts +9 -0
- package/dist/delta-format.d.ts.map +1 -0
- package/dist/delta-format.js +12 -0
- package/dist/delta-format.js.map +1 -0
- package/dist/delta-source-loader-types.d.ts +27 -0
- package/dist/delta-source-loader-types.d.ts.map +1 -0
- package/dist/delta-source-loader-types.js +28 -0
- package/dist/delta-source-loader-types.js.map +1 -0
- package/dist/delta-source.d.ts +48 -0
- package/dist/delta-source.d.ts.map +1 -0
- package/dist/delta-source.js +222 -0
- package/dist/delta-source.js.map +1 -0
- package/dist/delta-types.d.ts +38 -0
- package/dist/delta-types.d.ts.map +1 -0
- package/dist/delta-types.js +5 -0
- package/dist/delta-types.js.map +1 -0
- package/dist/geoparquet-loader.js +1 -1
- package/dist/iceberg-rest-catalog.d.ts +49 -0
- package/dist/iceberg-rest-catalog.d.ts.map +1 -0
- package/dist/iceberg-rest-catalog.js +78 -0
- package/dist/iceberg-rest-catalog.js.map +1 -0
- package/dist/iceberg-table-source.d.ts +63 -0
- package/dist/iceberg-table-source.d.ts.map +1 -0
- package/dist/iceberg-table-source.js +797 -0
- package/dist/iceberg-table-source.js.map +1 -0
- package/dist/iceberg-types.d.ts +150 -0
- package/dist/iceberg-types.d.ts.map +1 -0
- package/dist/iceberg-types.js +5 -0
- package/dist/iceberg-types.js.map +1 -0
- package/dist/index.cjs +15005 -3143
- package/dist/index.cjs.map +3 -3
- package/dist/index.d.ts +7 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/arrow/convert-schema-from-parquet.d.ts +3 -1
- package/dist/lib/arrow/convert-schema-from-parquet.d.ts.map +1 -1
- package/dist/lib/arrow/convert-schema-from-parquet.js +94 -19
- package/dist/lib/arrow/convert-schema-from-parquet.js.map +1 -1
- package/dist/lib/arrow/create-nested-arrow-vector.js +89 -0
- package/dist/lib/arrow/create-nested-arrow-vector.js.map +1 -1
- package/dist/lib/constants.js +1 -1
- package/dist/lib/encoders/encode-table-to-parquet-js.d.ts.map +1 -1
- package/dist/lib/encoders/encode-table-to-parquet-js.js +202 -7
- package/dist/lib/encoders/encode-table-to-parquet-js.js.map +1 -1
- package/dist/lib/geo/geoparquet-covering.d.ts +19 -0
- package/dist/lib/geo/geoparquet-covering.d.ts.map +1 -0
- package/dist/lib/geo/geoparquet-covering.js +137 -0
- package/dist/lib/geo/geoparquet-covering.js.map +1 -0
- package/dist/lib/geo/geospatial-metadata.d.ts.map +1 -1
- package/dist/lib/geo/geospatial-metadata.js +39 -13
- package/dist/lib/geo/geospatial-metadata.js.map +1 -1
- package/dist/lib/parquet-bloom-filter-planner.d.ts +16 -0
- package/dist/lib/parquet-bloom-filter-planner.d.ts.map +1 -0
- package/dist/lib/parquet-bloom-filter-planner.js +57 -0
- package/dist/lib/parquet-bloom-filter-planner.js.map +1 -0
- package/dist/lib/parquet-bloom-filter.d.ts +30 -0
- package/dist/lib/parquet-bloom-filter.d.ts.map +1 -0
- package/dist/lib/parquet-bloom-filter.js +289 -0
- package/dist/lib/parquet-bloom-filter.js.map +1 -0
- package/dist/lib/parquet-encryption.d.ts +80 -0
- package/dist/lib/parquet-encryption.d.ts.map +1 -0
- package/dist/lib/parquet-encryption.js +190 -0
- package/dist/lib/parquet-encryption.js.map +1 -0
- package/dist/lib/parquet-page-index.d.ts +34 -5
- package/dist/lib/parquet-page-index.d.ts.map +1 -1
- package/dist/lib/parquet-page-index.js +114 -28
- package/dist/lib/parquet-page-index.js.map +1 -1
- package/dist/lib/parquet-predicate.d.ts +5 -1
- package/dist/lib/parquet-predicate.d.ts.map +1 -1
- package/dist/lib/parquet-predicate.js +42 -14
- package/dist/lib/parquet-predicate.js.map +1 -1
- package/dist/lib/parquet-source-worker-decoder.d.ts +4 -1
- package/dist/lib/parquet-source-worker-decoder.d.ts.map +1 -1
- package/dist/lib/parquet-source-worker-decoder.js +83 -17
- package/dist/lib/parquet-source-worker-decoder.js.map +1 -1
- package/dist/lib/parquet-source-worker-types.d.ts +24 -0
- package/dist/lib/parquet-source-worker-types.d.ts.map +1 -1
- package/dist/lib/parsers/get-parquet-schema.d.ts.map +1 -1
- package/dist/lib/parsers/get-parquet-schema.js +3 -1
- package/dist/lib/parsers/get-parquet-schema.js.map +1 -1
- package/dist/lib/parsers/parse-parquet-to-arrow-js.d.ts.map +1 -1
- package/dist/lib/parsers/parse-parquet-to-arrow-js.js +327 -18
- package/dist/lib/parsers/parse-parquet-to-arrow-js.js.map +1 -1
- package/dist/lib/parsers/parse-parquet-to-arrow.d.ts.map +1 -1
- package/dist/lib/parsers/parse-parquet-to-arrow.js +5 -5
- package/dist/lib/parsers/parse-parquet-to-arrow.js.map +1 -1
- package/dist/lib/parsers/parse-parquet-to-columns.d.ts.map +1 -1
- package/dist/lib/parsers/parse-parquet-to-columns.js +3 -1
- package/dist/lib/parsers/parse-parquet-to-columns.js.map +1 -1
- package/dist/lib/parsers/parse-parquet-to-json.d.ts.map +1 -1
- package/dist/lib/parsers/parse-parquet-to-json.js +18 -2
- package/dist/lib/parsers/parse-parquet-to-json.js.map +1 -1
- package/dist/lib/slice-parquet-batch.d.ts +9 -0
- package/dist/lib/slice-parquet-batch.d.ts.map +1 -0
- package/dist/lib/slice-parquet-batch.js +28 -0
- package/dist/lib/slice-parquet-batch.js.map +1 -0
- package/dist/lib/sources/parquet-range-file.d.ts +1 -1
- package/dist/lib/sources/parquet-range-file.d.ts.map +1 -1
- package/dist/lib/sources/parquet-range-file.js +28 -22
- package/dist/lib/sources/parquet-range-file.js.map +1 -1
- package/dist/lib/utils/normalize-parquet-options.d.ts.map +1 -1
- package/dist/lib/utils/normalize-parquet-options.js +15 -1
- package/dist/lib/utils/normalize-parquet-options.js.map +1 -1
- package/dist/parquet-dataset-source.cjs +15766 -4896
- package/dist/parquet-dataset-source.cjs.map +3 -3
- package/dist/parquet-dataset-source.d.ts +31 -4
- package/dist/parquet-dataset-source.d.ts.map +1 -1
- package/dist/parquet-dataset-source.js +296 -74
- package/dist/parquet-dataset-source.js.map +1 -1
- package/dist/parquet-js-loader-types.d.ts +2 -0
- package/dist/parquet-js-loader-types.d.ts.map +1 -1
- package/dist/parquet-js-loader-types.js +2 -1
- package/dist/parquet-js-loader-types.js.map +1 -1
- package/dist/parquet-js-loader.d.ts +1 -0
- package/dist/parquet-js-loader.d.ts.map +1 -1
- package/dist/parquet-js-loader.js +2 -1
- package/dist/parquet-js-loader.js.map +1 -1
- package/dist/parquet-js-writer.d.ts +23 -2
- package/dist/parquet-js-writer.d.ts.map +1 -1
- package/dist/parquet-js-writer.js +1 -1
- package/dist/parquet-js-writer.js.map +1 -1
- package/dist/parquet-loader-base.js +1 -1
- package/dist/parquet-loader-options.d.ts +11 -0
- package/dist/parquet-loader-options.d.ts.map +1 -1
- package/dist/parquet-loader-options.js.map +1 -1
- package/dist/parquet-source-capabilities.d.ts +8 -1
- package/dist/parquet-source-capabilities.d.ts.map +1 -1
- package/dist/parquet-source-capabilities.js +10 -0
- package/dist/parquet-source-capabilities.js.map +1 -1
- package/dist/parquet-source-loader-types.d.ts +10 -0
- package/dist/parquet-source-loader-types.d.ts.map +1 -1
- package/dist/parquet-source-loader-types.js +11 -1
- package/dist/parquet-source-loader-types.js.map +1 -1
- package/dist/parquet-source-loader.cjs +14911 -4316
- package/dist/parquet-source-loader.cjs.map +3 -3
- package/dist/parquet-source-loader.d.ts +42 -4
- package/dist/parquet-source-loader.d.ts.map +1 -1
- package/dist/parquet-source-loader.js +585 -38
- package/dist/parquet-source-loader.js.map +1 -1
- package/dist/parquet-source-types.d.ts +180 -30
- package/dist/parquet-source-types.d.ts.map +1 -1
- package/dist/parquet-source-worker.js +7055 -6989
- package/dist/parquet-source-worker.js.map +4 -4
- package/dist/parquet-worker-node.cjs +8505 -1041
- package/dist/parquet-worker-node.cjs.map +4 -4
- package/dist/parquet-worker-url.js +5 -1
- package/dist/parquet-worker-url.js.map +1 -1
- package/dist/parquet-worker.js +289 -218
- package/dist/parquet-worker.js.map +4 -4
- package/dist/parquetjs/codecs/declare.d.ts +15 -0
- package/dist/parquetjs/codecs/declare.d.ts.map +1 -1
- package/dist/parquetjs/codecs/declare.js +10 -0
- package/dist/parquetjs/codecs/declare.js.map +1 -1
- package/dist/parquetjs/codecs/delta.d.ts.map +1 -1
- package/dist/parquetjs/codecs/delta.js +356 -7
- package/dist/parquetjs/codecs/delta.js.map +1 -1
- package/dist/parquetjs/codecs/index.d.ts.map +1 -1
- package/dist/parquetjs/codecs/index.js +4 -0
- package/dist/parquetjs/codecs/index.js.map +1 -1
- package/dist/parquetjs/codecs/plain.d.ts +1 -1
- package/dist/parquetjs/codecs/plain.d.ts.map +1 -1
- package/dist/parquetjs/codecs/plain.js +153 -12
- package/dist/parquetjs/codecs/plain.js.map +1 -1
- package/dist/parquetjs/codecs/rle.d.ts +4 -0
- package/dist/parquetjs/codecs/rle.d.ts.map +1 -1
- package/dist/parquetjs/codecs/rle.js +406 -3
- package/dist/parquetjs/codecs/rle.js.map +1 -1
- package/dist/parquetjs/compression.d.ts +9 -0
- package/dist/parquetjs/compression.d.ts.map +1 -1
- package/dist/parquetjs/compression.js +86 -67
- package/dist/parquetjs/compression.js.map +1 -1
- package/dist/parquetjs/encoder/dictionary-planner.d.ts.map +1 -1
- package/dist/parquetjs/encoder/dictionary-planner.js +5 -2
- package/dist/parquetjs/encoder/dictionary-planner.js.map +1 -1
- package/dist/parquetjs/encoder/parquet-encoder.d.ts +43 -1
- package/dist/parquetjs/encoder/parquet-encoder.d.ts.map +1 -1
- package/dist/parquetjs/encoder/parquet-encoder.js +691 -34
- package/dist/parquetjs/encoder/parquet-encoder.js.map +1 -1
- package/dist/parquetjs/parquet-thrift/BoundingBox.d.ts +29 -0
- package/dist/parquetjs/parquet-thrift/BoundingBox.d.ts.map +1 -0
- package/dist/parquetjs/parquet-thrift/BoundingBox.js +85 -0
- package/dist/parquetjs/parquet-thrift/BoundingBox.js.map +1 -0
- package/dist/parquetjs/parquet-thrift/ColumnChunk.d.ts +5 -0
- package/dist/parquetjs/parquet-thrift/ColumnChunk.d.ts.map +1 -1
- package/dist/parquetjs/parquet-thrift/ColumnChunk.js +35 -0
- package/dist/parquetjs/parquet-thrift/ColumnChunk.js.map +1 -1
- package/dist/parquetjs/parquet-thrift/ColumnCryptoMetaData.d.ts +35 -0
- package/dist/parquetjs/parquet-thrift/ColumnCryptoMetaData.d.ts.map +1 -0
- package/dist/parquetjs/parquet-thrift/ColumnCryptoMetaData.js +135 -0
- package/dist/parquetjs/parquet-thrift/ColumnCryptoMetaData.js.map +1 -0
- package/dist/parquetjs/parquet-thrift/ColumnMetaData.d.ts +10 -0
- package/dist/parquetjs/parquet-thrift/ColumnMetaData.d.ts.map +1 -1
- package/dist/parquetjs/parquet-thrift/ColumnMetaData.js +73 -0
- package/dist/parquetjs/parquet-thrift/ColumnMetaData.js.map +1 -1
- package/dist/parquetjs/parquet-thrift/EncryptionAlgorithm.d.ts +22 -0
- package/dist/parquetjs/parquet-thrift/EncryptionAlgorithm.d.ts.map +1 -0
- package/dist/parquetjs/parquet-thrift/EncryptionAlgorithm.js +111 -0
- package/dist/parquetjs/parquet-thrift/EncryptionAlgorithm.js.map +1 -0
- package/dist/parquetjs/parquet-thrift/FileCryptoMetaData.d.ts +16 -0
- package/dist/parquetjs/parquet-thrift/FileCryptoMetaData.d.ts.map +1 -0
- package/dist/parquetjs/parquet-thrift/FileCryptoMetaData.js +57 -0
- package/dist/parquetjs/parquet-thrift/FileCryptoMetaData.js.map +1 -0
- package/dist/parquetjs/parquet-thrift/FileMetaData.d.ts +5 -0
- package/dist/parquetjs/parquet-thrift/FileMetaData.d.ts.map +1 -1
- package/dist/parquetjs/parquet-thrift/FileMetaData.js +35 -0
- package/dist/parquetjs/parquet-thrift/FileMetaData.js.map +1 -1
- package/dist/parquetjs/parquet-thrift/GeospatialStatistics.d.ts +18 -0
- package/dist/parquetjs/parquet-thrift/GeospatialStatistics.d.ts.map +1 -0
- package/dist/parquetjs/parquet-thrift/GeospatialStatistics.js +62 -0
- package/dist/parquetjs/parquet-thrift/GeospatialStatistics.js.map +1 -0
- package/dist/parquetjs/parquet-thrift/SizeStatistics.d.ts +26 -0
- package/dist/parquetjs/parquet-thrift/SizeStatistics.d.ts.map +1 -0
- package/dist/parquetjs/parquet-thrift/SizeStatistics.js +85 -0
- package/dist/parquetjs/parquet-thrift/SizeStatistics.js.map +1 -0
- package/dist/parquetjs/parquet-thrift/index.d.ts +6 -0
- package/dist/parquetjs/parquet-thrift/index.d.ts.map +1 -1
- package/dist/parquetjs/parquet-thrift/index.js +6 -0
- package/dist/parquetjs/parquet-thrift/index.js.map +1 -1
- package/dist/parquetjs/parser/decoders.d.ts +10 -1
- package/dist/parquetjs/parser/decoders.d.ts.map +1 -1
- package/dist/parquetjs/parser/decoders.js +318 -14
- package/dist/parquetjs/parser/decoders.js.map +1 -1
- package/dist/parquetjs/parser/parquet-reader.d.ts +78 -12
- package/dist/parquetjs/parser/parquet-reader.d.ts.map +1 -1
- package/dist/parquetjs/parser/parquet-reader.js +605 -66
- package/dist/parquetjs/parser/parquet-reader.js.map +1 -1
- package/dist/parquetjs/schema/declare.d.ts +22 -3
- package/dist/parquetjs/schema/declare.d.ts.map +1 -1
- package/dist/parquetjs/schema/declare.js.map +1 -1
- package/dist/parquetjs/schema/schema.d.ts.map +1 -1
- package/dist/parquetjs/schema/schema.js +10 -0
- package/dist/parquetjs/schema/schema.js.map +1 -1
- package/dist/parquetjs/schema/shred.d.ts.map +1 -1
- package/dist/parquetjs/schema/shred.js +219 -11
- package/dist/parquetjs/schema/shred.js.map +1 -1
- package/dist/parquetjs/schema/types.js +19 -21
- package/dist/parquetjs/schema/types.js.map +1 -1
- package/dist/parquetjs/schema/variant.d.ts +3 -0
- package/dist/parquetjs/schema/variant.d.ts.map +1 -0
- package/dist/parquetjs/schema/variant.js +248 -0
- package/dist/parquetjs/schema/variant.js.map +1 -0
- package/dist/parquetjs/utils/crc32.d.ts +3 -0
- package/dist/parquetjs/utils/crc32.d.ts.map +1 -0
- package/dist/parquetjs/utils/crc32.js +15 -0
- package/dist/parquetjs/utils/crc32.js.map +1 -0
- package/dist/parquetjs/utils/read-utils.d.ts +11 -1
- package/dist/parquetjs/utils/read-utils.d.ts.map +1 -1
- package/dist/parquetjs/utils/read-utils.js +21 -1
- package/dist/parquetjs/utils/read-utils.js.map +1 -1
- package/dist/unbundled.d.ts +2 -1
- package/dist/unbundled.d.ts.map +1 -1
- package/dist/unbundled.js +1 -0
- package/dist/unbundled.js.map +1 -1
- package/package.json +36 -11
- package/src/bundled.ts +3 -0
- package/src/delta-format.ts +12 -0
- package/src/delta-source-loader-types.ts +40 -0
- package/src/delta-source.ts +305 -0
- package/src/delta-types.ts +40 -0
- package/src/iceberg-rest-catalog.ts +122 -0
- package/src/iceberg-table-source.ts +1037 -0
- package/src/iceberg-types.ts +165 -0
- package/src/index.ts +50 -1
- package/src/lib/arrow/convert-schema-from-parquet.ts +113 -19
- package/src/lib/arrow/create-nested-arrow-vector.ts +116 -0
- package/src/lib/encoders/encode-table-to-parquet-js.ts +268 -7
- package/src/lib/geo/geoparquet-covering.ts +201 -0
- package/src/lib/geo/geospatial-metadata.ts +42 -15
- package/src/lib/parquet-bloom-filter-planner.ts +86 -0
- package/src/lib/parquet-bloom-filter.ts +345 -0
- package/src/lib/parquet-encryption.ts +344 -0
- package/src/lib/parquet-page-index.ts +180 -34
- package/src/lib/parquet-predicate.ts +52 -16
- package/src/lib/parquet-source-worker-decoder.ts +116 -20
- package/src/lib/parquet-source-worker-types.ts +25 -0
- package/src/lib/parsers/get-parquet-schema.ts +3 -1
- package/src/lib/parsers/parse-parquet-to-arrow-js.ts +397 -17
- package/src/lib/parsers/parse-parquet-to-arrow.ts +4 -5
- package/src/lib/parsers/parse-parquet-to-columns.ts +3 -1
- package/src/lib/parsers/parse-parquet-to-json.ts +18 -2
- package/src/lib/slice-parquet-batch.ts +32 -0
- package/src/lib/sources/parquet-range-file.ts +35 -29
- package/src/lib/utils/normalize-parquet-options.ts +17 -1
- package/src/parquet-dataset-source.ts +397 -85
- package/src/parquet-js-loader-types.ts +1 -0
- package/src/parquet-js-loader.ts +2 -1
- package/src/parquet-js-writer.ts +30 -0
- package/src/parquet-loader-options.ts +11 -0
- package/src/parquet-source-capabilities.ts +18 -1
- package/src/parquet-source-loader-types.ts +10 -0
- package/src/parquet-source-loader.ts +929 -52
- package/src/parquet-source-types.ts +197 -28
- package/src/parquet-worker-url.ts +6 -1
- package/src/parquetjs/codecs/declare.ts +27 -0
- package/src/parquetjs/codecs/delta.ts +466 -6
- package/src/parquetjs/codecs/index.ts +4 -0
- package/src/parquetjs/codecs/plain.ts +177 -11
- package/src/parquetjs/codecs/rle.ts +573 -3
- package/src/parquetjs/compression.ts +102 -76
- package/src/parquetjs/encoder/dictionary-planner.ts +7 -2
- package/src/parquetjs/encoder/parquet-encoder.ts +1016 -38
- package/src/parquetjs/parquet-thrift/BoundingBox.ts +108 -0
- package/src/parquetjs/parquet-thrift/ColumnChunk.ts +35 -0
- package/src/parquetjs/parquet-thrift/ColumnCryptoMetaData.ts +139 -0
- package/src/parquetjs/parquet-thrift/ColumnMetaData.ts +73 -0
- package/src/parquetjs/parquet-thrift/EncryptionAlgorithm.ts +127 -0
- package/src/parquetjs/parquet-thrift/FileCryptoMetaData.ts +60 -0
- package/src/parquetjs/parquet-thrift/FileMetaData.ts +35 -0
- package/src/parquetjs/parquet-thrift/GeospatialStatistics.ts +68 -0
- package/src/parquetjs/parquet-thrift/SizeStatistics.ts +98 -0
- package/src/parquetjs/parquet-thrift/index.ts +6 -0
- package/src/parquetjs/parser/decoders.ts +451 -26
- package/src/parquetjs/parser/parquet-reader.ts +935 -87
- package/src/parquetjs/schema/declare.ts +22 -2
- package/src/parquetjs/schema/schema.ts +10 -0
- package/src/parquetjs/schema/shred.ts +238 -11
- package/src/parquetjs/schema/types.ts +16 -25
- package/src/parquetjs/schema/variant.ts +313 -0
- package/src/parquetjs/utils/crc32.ts +15 -0
- package/src/parquetjs/utils/read-utils.ts +26 -1
- package/src/unbundled.ts +14 -0
|
@@ -7,6 +7,7 @@ import type {PrimitiveType} from '../schema/declare';
|
|
|
7
7
|
import {concatUint8Arrays, copyUint8Array, toUint8Array} from '../utils/binary-utils';
|
|
8
8
|
import {
|
|
9
9
|
getParquetValueOutput,
|
|
10
|
+
reserveParquetByteArrayOutput,
|
|
10
11
|
type CursorBuffer,
|
|
11
12
|
type ParquetCodecOptions,
|
|
12
13
|
type ParquetValueBuffer
|
|
@@ -15,6 +16,8 @@ import {
|
|
|
15
16
|
const DELTA_BLOCK_SIZE = 128;
|
|
16
17
|
const DELTA_MINI_BLOCK_COUNT = 4;
|
|
17
18
|
const DELTA_VALUES_PER_MINI_BLOCK = DELTA_BLOCK_SIZE / DELTA_MINI_BLOCK_COUNT;
|
|
19
|
+
const UINT32_BASE = 0x1_0000_0000;
|
|
20
|
+
const IS_LITTLE_ENDIAN = new Uint8Array(new Uint16Array([1]).buffer)[0] === 1;
|
|
18
21
|
|
|
19
22
|
/** Encodes INT32 or INT64 values using Parquet DELTA_BINARY_PACKED. */
|
|
20
23
|
export function encodeDeltaBinaryPackedValues(
|
|
@@ -264,6 +267,31 @@ function decodeDeltaBinaryPackedInt32Values(
|
|
|
264
267
|
while (outputIndex < count) {
|
|
265
268
|
const minimumDelta = readZigZagVarInt32(cursor);
|
|
266
269
|
const bitWidths = readBitWidths(cursor, miniBlockCount, 32);
|
|
270
|
+
const activeMiniBlockCount = Math.min(
|
|
271
|
+
miniBlockCount,
|
|
272
|
+
Math.ceil((count - outputIndex) / valuesPerMiniBlock)
|
|
273
|
+
);
|
|
274
|
+
// Writers commonly select one width for every mini-block in a block. Fuse that contiguous
|
|
275
|
+
// bitstream so the decoder pays call/state setup once instead of once per 32 values.
|
|
276
|
+
if (haveEqualBitWidths(bitWidths, activeMiniBlockCount)) {
|
|
277
|
+
const bitWidth = bitWidths[0];
|
|
278
|
+
const valueCount = Math.min(valuesPerMiniBlock * activeMiniBlockCount, count - outputIndex);
|
|
279
|
+
const packedByteLength = (valuesPerMiniBlock * activeMiniBlockCount * bitWidth) / 8;
|
|
280
|
+
assertReadable(cursor, packedByteLength);
|
|
281
|
+
value = decodeInt32MiniBlock(
|
|
282
|
+
cursor.buffer,
|
|
283
|
+
cursor.offset,
|
|
284
|
+
bitWidth,
|
|
285
|
+
valueCount,
|
|
286
|
+
minimumDelta,
|
|
287
|
+
value,
|
|
288
|
+
output,
|
|
289
|
+
outputOffset + outputIndex
|
|
290
|
+
);
|
|
291
|
+
outputIndex += valueCount;
|
|
292
|
+
cursor.offset += packedByteLength;
|
|
293
|
+
continue;
|
|
294
|
+
}
|
|
267
295
|
for (const bitWidth of bitWidths) {
|
|
268
296
|
const packedOffset = cursor.offset;
|
|
269
297
|
const packedByteLength = (valuesPerMiniBlock * bitWidth) / 8;
|
|
@@ -310,6 +338,26 @@ function decodeInt32MiniBlock(
|
|
|
310
338
|
return value;
|
|
311
339
|
}
|
|
312
340
|
|
|
341
|
+
if (bitWidth <= 24) {
|
|
342
|
+
// Bitwise reservoirs stay exact through 24 bits and are substantially cheaper than the
|
|
343
|
+
// division-based reservoir required for wider INT32 deltas.
|
|
344
|
+
const mask = 2 ** bitWidth - 1;
|
|
345
|
+
let packedBits = 0;
|
|
346
|
+
let packedBitCount = 0;
|
|
347
|
+
let byteOffset = packedOffset;
|
|
348
|
+
for (let index = 0; index < count; index++) {
|
|
349
|
+
while (packedBitCount < bitWidth) {
|
|
350
|
+
packedBits |= buffer[byteOffset++] << packedBitCount;
|
|
351
|
+
packedBitCount += 8;
|
|
352
|
+
}
|
|
353
|
+
value = (value + minimumDelta + (packedBits & mask)) | 0;
|
|
354
|
+
output[outputOffset + index] = value;
|
|
355
|
+
packedBits >>>= bitWidth;
|
|
356
|
+
packedBitCount -= bitWidth;
|
|
357
|
+
}
|
|
358
|
+
return value;
|
|
359
|
+
}
|
|
360
|
+
|
|
313
361
|
const divisor = 2 ** bitWidth;
|
|
314
362
|
let packedBits = 0;
|
|
315
363
|
let packedBitCount = 0;
|
|
@@ -337,6 +385,21 @@ function decodeDeltaBinaryPackedInt64Values(
|
|
|
337
385
|
options: ParquetCodecOptions
|
|
338
386
|
): ParquetValueBuffer {
|
|
339
387
|
const {output, outputOffset} = getParquetValueOutput(options, count);
|
|
388
|
+
if (options.int64AsBigInt && output instanceof BigInt64Array) {
|
|
389
|
+
// BigInt arithmetic per value is expensive in V8. Decode into the two uint32 words backing
|
|
390
|
+
// Arrow Int64 instead; modulo-64 addition preserves every signed INT64 bit pattern exactly.
|
|
391
|
+
const state = new Uint32Array(2);
|
|
392
|
+
readZigZagVarIntWords(cursor, state);
|
|
393
|
+
return decodeDeltaBinaryPackedInt64ArrowValues(
|
|
394
|
+
cursor,
|
|
395
|
+
count,
|
|
396
|
+
miniBlockCount,
|
|
397
|
+
valuesPerMiniBlock,
|
|
398
|
+
output,
|
|
399
|
+
outputOffset,
|
|
400
|
+
state
|
|
401
|
+
);
|
|
402
|
+
}
|
|
340
403
|
let value = readZigZagVarInt(cursor);
|
|
341
404
|
let outputIndex = 0;
|
|
342
405
|
writeInt64Output(output, outputOffset + outputIndex++, value, options.int64AsBigInt);
|
|
@@ -371,6 +434,254 @@ function decodeDeltaBinaryPackedInt64Values(
|
|
|
371
434
|
return output;
|
|
372
435
|
}
|
|
373
436
|
|
|
437
|
+
/** Decodes INT64 directly into Arrow storage with modulo-64 two-word arithmetic. */
|
|
438
|
+
function decodeDeltaBinaryPackedInt64ArrowValues(
|
|
439
|
+
cursor: CursorBuffer,
|
|
440
|
+
count: number,
|
|
441
|
+
miniBlockCount: number,
|
|
442
|
+
valuesPerMiniBlock: number,
|
|
443
|
+
output: BigInt64Array,
|
|
444
|
+
outputOffset: number,
|
|
445
|
+
state: Uint32Array
|
|
446
|
+
): BigInt64Array {
|
|
447
|
+
const outputWords = new Uint32Array(output.buffer, output.byteOffset, output.length * 2);
|
|
448
|
+
const minimumDeltaWords = new Uint32Array(2);
|
|
449
|
+
let outputIndex = 0;
|
|
450
|
+
writeInt64Words(outputWords, outputOffset + outputIndex++, state[0], state[1]);
|
|
451
|
+
|
|
452
|
+
while (outputIndex < count) {
|
|
453
|
+
readZigZagVarIntWords(cursor, minimumDeltaWords);
|
|
454
|
+
const bitWidths = readBitWidths(cursor, miniBlockCount, 64);
|
|
455
|
+
const activeMiniBlockCount = Math.min(
|
|
456
|
+
miniBlockCount,
|
|
457
|
+
Math.ceil((count - outputIndex) / valuesPerMiniBlock)
|
|
458
|
+
);
|
|
459
|
+
// Preserve the equal-width fusion used by the wide-column benchmark. Splitting this back into
|
|
460
|
+
// four mini-block calls repeats state loads/stores and loses measurable throughput.
|
|
461
|
+
if (haveEqualBitWidths(bitWidths, activeMiniBlockCount)) {
|
|
462
|
+
const bitWidth = bitWidths[0];
|
|
463
|
+
const valueCount = Math.min(valuesPerMiniBlock * activeMiniBlockCount, count - outputIndex);
|
|
464
|
+
const packedByteLength = (valuesPerMiniBlock * activeMiniBlockCount * bitWidth) / 8;
|
|
465
|
+
assertReadable(cursor, packedByteLength);
|
|
466
|
+
decodeInt64ArrowMiniBlock(
|
|
467
|
+
cursor.buffer,
|
|
468
|
+
cursor.offset,
|
|
469
|
+
bitWidth,
|
|
470
|
+
valueCount,
|
|
471
|
+
minimumDeltaWords[0],
|
|
472
|
+
minimumDeltaWords[1],
|
|
473
|
+
state,
|
|
474
|
+
outputWords,
|
|
475
|
+
outputOffset + outputIndex
|
|
476
|
+
);
|
|
477
|
+
outputIndex += valueCount;
|
|
478
|
+
cursor.offset += packedByteLength;
|
|
479
|
+
continue;
|
|
480
|
+
}
|
|
481
|
+
for (const bitWidth of bitWidths) {
|
|
482
|
+
const packedOffset = cursor.offset;
|
|
483
|
+
const packedByteLength = (valuesPerMiniBlock * bitWidth) / 8;
|
|
484
|
+
assertReadable(cursor, packedByteLength);
|
|
485
|
+
const valueCount = Math.min(valuesPerMiniBlock, count - outputIndex);
|
|
486
|
+
decodeInt64ArrowMiniBlock(
|
|
487
|
+
cursor.buffer,
|
|
488
|
+
packedOffset,
|
|
489
|
+
bitWidth,
|
|
490
|
+
valueCount,
|
|
491
|
+
minimumDeltaWords[0],
|
|
492
|
+
minimumDeltaWords[1],
|
|
493
|
+
state,
|
|
494
|
+
outputWords,
|
|
495
|
+
outputOffset + outputIndex
|
|
496
|
+
);
|
|
497
|
+
outputIndex += valueCount;
|
|
498
|
+
cursor.offset += packedByteLength;
|
|
499
|
+
if (outputIndex === count) break;
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
return output;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
/** Returns whether all mini-blocks in one DELTA_BINARY_PACKED block use one bit width. */
|
|
506
|
+
function haveEqualBitWidths(bitWidths: Uint8Array, count: number): boolean {
|
|
507
|
+
const firstBitWidth = bitWidths[0];
|
|
508
|
+
for (let index = 1; index < count; index++) {
|
|
509
|
+
if (bitWidths[index] !== firstBitWidth) return false;
|
|
510
|
+
}
|
|
511
|
+
return true;
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
/** Decodes one INT64 mini-block directly into the two 32-bit words backing Arrow Int64. */
|
|
515
|
+
function decodeInt64ArrowMiniBlock(
|
|
516
|
+
buffer: Uint8Array,
|
|
517
|
+
packedOffset: number,
|
|
518
|
+
bitWidth: number,
|
|
519
|
+
count: number,
|
|
520
|
+
minimumDeltaLow: number,
|
|
521
|
+
minimumDeltaHigh: number,
|
|
522
|
+
state: Uint32Array,
|
|
523
|
+
outputWords: Uint32Array,
|
|
524
|
+
outputOffset: number
|
|
525
|
+
): void {
|
|
526
|
+
let stateLow = state[0];
|
|
527
|
+
let stateHigh = state[1];
|
|
528
|
+
const lowWordOffset = IS_LITTLE_ENDIAN ? 0 : 1;
|
|
529
|
+
const highWordOffset = IS_LITTLE_ENDIAN ? 1 : 0;
|
|
530
|
+
|
|
531
|
+
if (bitWidth === 0) {
|
|
532
|
+
for (let index = 0; index < count; index++) {
|
|
533
|
+
const lowSum = stateLow + minimumDeltaLow;
|
|
534
|
+
stateLow = lowSum >>> 0;
|
|
535
|
+
// V8 strength-reduces division by this constant; explicit carry branches benchmark slower.
|
|
536
|
+
stateHigh = (stateHigh + minimumDeltaHigh + Math.floor(lowSum / UINT32_BASE)) >>> 0;
|
|
537
|
+
const wordOffset = (outputOffset + index) * 2;
|
|
538
|
+
outputWords[wordOffset + lowWordOffset] = stateLow;
|
|
539
|
+
outputWords[wordOffset + highWordOffset] = stateHigh;
|
|
540
|
+
}
|
|
541
|
+
state[0] = stateLow;
|
|
542
|
+
state[1] = stateHigh;
|
|
543
|
+
return;
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
if (bitWidth <= 24) {
|
|
547
|
+
decodeNarrowInt64ArrowMiniBlock(
|
|
548
|
+
buffer,
|
|
549
|
+
packedOffset,
|
|
550
|
+
bitWidth,
|
|
551
|
+
count,
|
|
552
|
+
minimumDeltaLow,
|
|
553
|
+
minimumDeltaHigh,
|
|
554
|
+
state,
|
|
555
|
+
outputWords,
|
|
556
|
+
outputOffset
|
|
557
|
+
);
|
|
558
|
+
return;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
if (bitWidth <= 45) {
|
|
562
|
+
const divisor = 2 ** bitWidth;
|
|
563
|
+
let packedBits = 0;
|
|
564
|
+
let packedBitCount = 0;
|
|
565
|
+
let byteOffset = packedOffset;
|
|
566
|
+
for (let index = 0; index < count; index++) {
|
|
567
|
+
while (packedBitCount < bitWidth) {
|
|
568
|
+
packedBits += buffer[byteOffset++] * 2 ** packedBitCount;
|
|
569
|
+
packedBitCount += 8;
|
|
570
|
+
}
|
|
571
|
+
const packedDelta = packedBits % divisor;
|
|
572
|
+
packedBits = Math.floor(packedBits / divisor);
|
|
573
|
+
packedBitCount -= bitWidth;
|
|
574
|
+
const packedDeltaLow = packedDelta >>> 0;
|
|
575
|
+
const packedDeltaHigh = Math.floor(packedDelta / UINT32_BASE);
|
|
576
|
+
const lowSum = stateLow + minimumDeltaLow + packedDeltaLow;
|
|
577
|
+
stateLow = lowSum >>> 0;
|
|
578
|
+
// V8 strength-reduces division by this constant; explicit carry branches benchmark slower.
|
|
579
|
+
stateHigh =
|
|
580
|
+
(stateHigh + minimumDeltaHigh + packedDeltaHigh + Math.floor(lowSum / UINT32_BASE)) >>> 0;
|
|
581
|
+
const wordOffset = (outputOffset + index) * 2;
|
|
582
|
+
outputWords[wordOffset + lowWordOffset] = stateLow;
|
|
583
|
+
outputWords[wordOffset + highWordOffset] = stateHigh;
|
|
584
|
+
}
|
|
585
|
+
state[0] = stateLow;
|
|
586
|
+
state[1] = stateHigh;
|
|
587
|
+
return;
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
const highBitWidth = bitWidth - 32;
|
|
591
|
+
const highMask = highBitWidth === 32 ? 0xffff_ffff : 2 ** highBitWidth - 1;
|
|
592
|
+
for (let index = 0; index < count; index++) {
|
|
593
|
+
const packedBitOffset = index * bitWidth;
|
|
594
|
+
const byteOffset = packedOffset + Math.floor(packedBitOffset / 8);
|
|
595
|
+
const shift = packedBitOffset & 7;
|
|
596
|
+
const lowerWord = readUint32LELoose(buffer, byteOffset);
|
|
597
|
+
const middleWord = readUint32LELoose(buffer, byteOffset + 4);
|
|
598
|
+
let packedDeltaLow: number;
|
|
599
|
+
let packedDeltaHigh: number;
|
|
600
|
+
if (shift === 0) {
|
|
601
|
+
packedDeltaLow = lowerWord;
|
|
602
|
+
packedDeltaHigh = middleWord & highMask;
|
|
603
|
+
} else {
|
|
604
|
+
const upperByte = buffer[byteOffset + 8] ?? 0;
|
|
605
|
+
packedDeltaLow = ((lowerWord >>> shift) | (middleWord << (32 - shift))) >>> 0;
|
|
606
|
+
packedDeltaHigh = ((middleWord >>> shift) | (upperByte << (32 - shift))) & highMask;
|
|
607
|
+
}
|
|
608
|
+
const lowSum = stateLow + minimumDeltaLow + packedDeltaLow;
|
|
609
|
+
stateLow = lowSum >>> 0;
|
|
610
|
+
// V8 strength-reduces division by this constant; explicit carry branches benchmark slower.
|
|
611
|
+
stateHigh =
|
|
612
|
+
(stateHigh + minimumDeltaHigh + packedDeltaHigh + Math.floor(lowSum / UINT32_BASE)) >>> 0;
|
|
613
|
+
const wordOffset = (outputOffset + index) * 2;
|
|
614
|
+
outputWords[wordOffset + lowWordOffset] = stateLow;
|
|
615
|
+
outputWords[wordOffset + highWordOffset] = stateHigh;
|
|
616
|
+
}
|
|
617
|
+
state[0] = stateLow;
|
|
618
|
+
state[1] = stateHigh;
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
/** Decodes an INT64 mini-block whose packed deltas fit a 32-bit bit reservoir. */
|
|
622
|
+
function decodeNarrowInt64ArrowMiniBlock(
|
|
623
|
+
buffer: Uint8Array,
|
|
624
|
+
packedOffset: number,
|
|
625
|
+
bitWidth: number,
|
|
626
|
+
count: number,
|
|
627
|
+
minimumDeltaLow: number,
|
|
628
|
+
minimumDeltaHigh: number,
|
|
629
|
+
state: Uint32Array,
|
|
630
|
+
outputWords: Uint32Array,
|
|
631
|
+
outputOffset: number
|
|
632
|
+
): void {
|
|
633
|
+
const mask = 2 ** bitWidth - 1;
|
|
634
|
+
const lowWordOffset = IS_LITTLE_ENDIAN ? 0 : 1;
|
|
635
|
+
const highWordOffset = IS_LITTLE_ENDIAN ? 1 : 0;
|
|
636
|
+
let stateLow = state[0];
|
|
637
|
+
let stateHigh = state[1];
|
|
638
|
+
let packedBits = 0;
|
|
639
|
+
let packedBitCount = 0;
|
|
640
|
+
let byteOffset = packedOffset;
|
|
641
|
+
|
|
642
|
+
for (let index = 0; index < count; index++) {
|
|
643
|
+
while (packedBitCount < bitWidth) {
|
|
644
|
+
packedBits |= buffer[byteOffset++] << packedBitCount;
|
|
645
|
+
packedBitCount += 8;
|
|
646
|
+
}
|
|
647
|
+
const packedDelta = packedBits & mask;
|
|
648
|
+
packedBits >>>= bitWidth;
|
|
649
|
+
packedBitCount -= bitWidth;
|
|
650
|
+
const lowSum = stateLow + minimumDeltaLow + packedDelta;
|
|
651
|
+
stateLow = lowSum >>> 0;
|
|
652
|
+
// V8 strength-reduces division by this constant; explicit carry branches benchmark slower.
|
|
653
|
+
stateHigh = (stateHigh + minimumDeltaHigh + Math.floor(lowSum / UINT32_BASE)) >>> 0;
|
|
654
|
+
const wordOffset = (outputOffset + index) * 2;
|
|
655
|
+
outputWords[wordOffset + lowWordOffset] = stateLow;
|
|
656
|
+
outputWords[wordOffset + highWordOffset] = stateHigh;
|
|
657
|
+
}
|
|
658
|
+
state[0] = stateLow;
|
|
659
|
+
state[1] = stateHigh;
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
/** Reads an unaligned little-endian word, treating bytes beyond a mini-block as zero. */
|
|
663
|
+
function readUint32LELoose(buffer: Uint8Array, offset: number): number {
|
|
664
|
+
return (
|
|
665
|
+
((buffer[offset] ?? 0) |
|
|
666
|
+
((buffer[offset + 1] ?? 0) << 8) |
|
|
667
|
+
((buffer[offset + 2] ?? 0) << 16) |
|
|
668
|
+
((buffer[offset + 3] ?? 0) << 24)) >>>
|
|
669
|
+
0
|
|
670
|
+
);
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
/** Writes one pair of 32-bit words into a platform-endian BigInt64Array backing buffer. */
|
|
674
|
+
function writeInt64Words(
|
|
675
|
+
outputWords: Uint32Array,
|
|
676
|
+
outputIndex: number,
|
|
677
|
+
low: number,
|
|
678
|
+
high: number
|
|
679
|
+
): void {
|
|
680
|
+
const wordOffset = outputIndex * 2;
|
|
681
|
+
outputWords[wordOffset + (IS_LITTLE_ENDIAN ? 0 : 1)] = low;
|
|
682
|
+
outputWords[wordOffset + (IS_LITTLE_ENDIAN ? 1 : 0)] = high;
|
|
683
|
+
}
|
|
684
|
+
|
|
374
685
|
/** Decodes one INT64 mini-block, using numbers whenever the packed value remains exact. */
|
|
375
686
|
function decodeInt64MiniBlock(
|
|
376
687
|
buffer: Uint8Array,
|
|
@@ -457,14 +768,49 @@ export function decodeDeltaLengthByteArrayValues(
|
|
|
457
768
|
options: ParquetCodecOptions
|
|
458
769
|
): ParquetValueBuffer {
|
|
459
770
|
assertByteArrayType(type, 'DELTA_LENGTH_BYTE_ARRAY');
|
|
460
|
-
const lengths =
|
|
771
|
+
const lengths = new Int32Array(count);
|
|
772
|
+
decodeDeltaBinaryPackedValues('INT32', cursor, count, {output: lengths});
|
|
773
|
+
if (options.byteArrayOutput) {
|
|
774
|
+
return decodeDeltaLengthByteArraysToContiguousOutput(cursor, lengths, options);
|
|
775
|
+
}
|
|
461
776
|
const {output, outputOffset} = getParquetValueOutput(options, count);
|
|
462
777
|
for (let index = 0; index < count; index++) {
|
|
463
|
-
output[outputOffset + index] = readByteArray(cursor,
|
|
778
|
+
output[outputOffset + index] = readByteArray(cursor, lengths[index]);
|
|
464
779
|
}
|
|
465
780
|
return output;
|
|
466
781
|
}
|
|
467
782
|
|
|
783
|
+
/** Copies DELTA_LENGTH_BYTE_ARRAY's contiguous payload directly into an Arrow byte buffer. */
|
|
784
|
+
function decodeDeltaLengthByteArraysToContiguousOutput(
|
|
785
|
+
cursor: CursorBuffer,
|
|
786
|
+
lengths: Int32Array,
|
|
787
|
+
options: ParquetCodecOptions
|
|
788
|
+
): ParquetValueBuffer {
|
|
789
|
+
const byteArrayOutput = options.byteArrayOutput!;
|
|
790
|
+
const outputOffset = options.outputOffset || 0;
|
|
791
|
+
let payloadByteLength = 0;
|
|
792
|
+
for (const length of lengths) {
|
|
793
|
+
if (length < 0) {
|
|
794
|
+
throw new Error(`Invalid delta byte-array length ${length}`);
|
|
795
|
+
}
|
|
796
|
+
payloadByteLength += length;
|
|
797
|
+
}
|
|
798
|
+
assertReadable(cursor, payloadByteLength);
|
|
799
|
+
reserveParquetByteArrayOutput(byteArrayOutput, payloadByteLength);
|
|
800
|
+
|
|
801
|
+
let byteOffset = byteArrayOutput.byteLength;
|
|
802
|
+
byteArrayOutput.valueOffsets[outputOffset] = byteOffset;
|
|
803
|
+
const payloadEnd = cursor.offset + payloadByteLength;
|
|
804
|
+
byteArrayOutput.data.set(cursor.buffer.subarray(cursor.offset, payloadEnd), byteOffset);
|
|
805
|
+
cursor.offset = payloadEnd;
|
|
806
|
+
for (let valueIndex = 0; valueIndex < lengths.length; valueIndex++) {
|
|
807
|
+
byteOffset += lengths[valueIndex];
|
|
808
|
+
byteArrayOutput.valueOffsets[outputOffset + valueIndex + 1] = byteOffset;
|
|
809
|
+
}
|
|
810
|
+
byteArrayOutput.byteLength = byteOffset;
|
|
811
|
+
return options.output || [];
|
|
812
|
+
}
|
|
813
|
+
|
|
468
814
|
/** Decodes prefix lengths and delta-length suffixes into complete byte-array values. */
|
|
469
815
|
export function decodeDeltaByteArrayValues(
|
|
470
816
|
type: PrimitiveType,
|
|
@@ -473,17 +819,25 @@ export function decodeDeltaByteArrayValues(
|
|
|
473
819
|
options: ParquetCodecOptions
|
|
474
820
|
): ParquetValueBuffer {
|
|
475
821
|
assertByteArrayType(type, 'DELTA_BYTE_ARRAY');
|
|
476
|
-
|
|
477
|
-
|
|
822
|
+
// One combined allocation is faster than separate prefix/suffix buffers in V8. Keep the two
|
|
823
|
+
// subarray views: reusing Arrow offsets as scratch storage deoptimizes reconstruction.
|
|
824
|
+
const lengths = new Int32Array(count * 2);
|
|
825
|
+
const prefixLengths = lengths.subarray(0, count);
|
|
826
|
+
const suffixLengths = lengths.subarray(count);
|
|
827
|
+
decodeDeltaBinaryPackedValues('INT32', cursor, count, {output: prefixLengths});
|
|
828
|
+
decodeDeltaBinaryPackedValues('INT32', cursor, count, {output: suffixLengths});
|
|
829
|
+
if (options.byteArrayOutput) {
|
|
830
|
+
return decodeDeltaByteArraysToContiguousOutput(cursor, prefixLengths, suffixLengths, options);
|
|
831
|
+
}
|
|
478
832
|
const {output, outputOffset} = getParquetValueOutput(options, count);
|
|
479
833
|
let previousValue: Uint8Array | undefined;
|
|
480
834
|
|
|
481
835
|
for (let index = 0; index < count; index++) {
|
|
482
|
-
const prefixLength =
|
|
483
|
-
const suffix = suffixes[index] as Uint8Array;
|
|
836
|
+
const prefixLength = prefixLengths[index];
|
|
484
837
|
if (prefixLength < 0 || (prefixLength > 0 && prefixLength > (previousValue?.length || 0))) {
|
|
485
838
|
throw new Error(`Invalid DELTA_BYTE_ARRAY prefix length ${prefixLength}`);
|
|
486
839
|
}
|
|
840
|
+
const suffix = readByteArray(cursor, suffixLengths[index]);
|
|
487
841
|
if (prefixLength === 0) {
|
|
488
842
|
output[outputOffset + index] = suffix;
|
|
489
843
|
previousValue = suffix;
|
|
@@ -499,6 +853,76 @@ export function decodeDeltaByteArrayValues(
|
|
|
499
853
|
return output;
|
|
500
854
|
}
|
|
501
855
|
|
|
856
|
+
/** Reconstructs DELTA_BYTE_ARRAY values directly in one Arrow-compatible byte buffer. */
|
|
857
|
+
function decodeDeltaByteArraysToContiguousOutput(
|
|
858
|
+
cursor: CursorBuffer,
|
|
859
|
+
prefixLengths: Int32Array,
|
|
860
|
+
suffixLengths: Int32Array,
|
|
861
|
+
options: ParquetCodecOptions
|
|
862
|
+
): ParquetValueBuffer {
|
|
863
|
+
const byteArrayOutput = options.byteArrayOutput!;
|
|
864
|
+
const outputOffset = options.outputOffset || 0;
|
|
865
|
+
let byteOffset = byteArrayOutput.byteLength;
|
|
866
|
+
let previousValueOffset = byteOffset;
|
|
867
|
+
let previousValueLength = 0;
|
|
868
|
+
byteArrayOutput.valueOffsets[outputOffset] = byteOffset;
|
|
869
|
+
|
|
870
|
+
let requiredByteLength = 0;
|
|
871
|
+
let requiredSuffixByteLength = 0;
|
|
872
|
+
for (let valueIndex = 0; valueIndex < prefixLengths.length; valueIndex++) {
|
|
873
|
+
const prefixLength = prefixLengths[valueIndex];
|
|
874
|
+
const suffixLength = suffixLengths[valueIndex];
|
|
875
|
+
if (prefixLength < 0 || prefixLength > previousValueLength) {
|
|
876
|
+
throw new Error(`Invalid DELTA_BYTE_ARRAY prefix length ${prefixLength}`);
|
|
877
|
+
}
|
|
878
|
+
if (suffixLength < 0) {
|
|
879
|
+
throw new Error(`Invalid delta byte-array length ${suffixLength}`);
|
|
880
|
+
}
|
|
881
|
+
previousValueLength = prefixLength + suffixLength;
|
|
882
|
+
requiredByteLength += previousValueLength;
|
|
883
|
+
requiredSuffixByteLength += suffixLength;
|
|
884
|
+
}
|
|
885
|
+
assertReadable(cursor, requiredSuffixByteLength);
|
|
886
|
+
reserveParquetByteArrayOutput(byteArrayOutput, requiredByteLength);
|
|
887
|
+
|
|
888
|
+
const data = byteArrayOutput.data;
|
|
889
|
+
const valueOffsets = byteArrayOutput.valueOffsets;
|
|
890
|
+
const inputBuffer = cursor.buffer;
|
|
891
|
+
let inputOffset = cursor.offset;
|
|
892
|
+
previousValueLength = 0;
|
|
893
|
+
for (let valueIndex = 0; valueIndex < prefixLengths.length; valueIndex++) {
|
|
894
|
+
const prefixLength = prefixLengths[valueIndex];
|
|
895
|
+
const suffixLength = suffixLengths[valueIndex];
|
|
896
|
+
const valueLength = prefixLength + suffixLength;
|
|
897
|
+
if (prefixLength > 0) {
|
|
898
|
+
if (prefixLength <= 15) {
|
|
899
|
+
for (let byteIndex = 0; byteIndex < prefixLength; byteIndex++) {
|
|
900
|
+
data[byteOffset + byteIndex] = data[previousValueOffset + byteIndex];
|
|
901
|
+
}
|
|
902
|
+
} else {
|
|
903
|
+
data.copyWithin(byteOffset, previousValueOffset, previousValueOffset + prefixLength);
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
const suffixEnd = inputOffset + suffixLength;
|
|
907
|
+
if (suffixLength <= 15) {
|
|
908
|
+
let suffixOutputOffset = byteOffset + prefixLength;
|
|
909
|
+
while (inputOffset < suffixEnd) {
|
|
910
|
+
data[suffixOutputOffset++] = inputBuffer[inputOffset++];
|
|
911
|
+
}
|
|
912
|
+
} else {
|
|
913
|
+
data.set(inputBuffer.subarray(inputOffset, suffixEnd), byteOffset + prefixLength);
|
|
914
|
+
inputOffset = suffixEnd;
|
|
915
|
+
}
|
|
916
|
+
previousValueOffset = byteOffset;
|
|
917
|
+
previousValueLength = valueLength;
|
|
918
|
+
byteOffset += valueLength;
|
|
919
|
+
valueOffsets[outputOffset + valueIndex + 1] = byteOffset;
|
|
920
|
+
}
|
|
921
|
+
cursor.offset = inputOffset;
|
|
922
|
+
byteArrayOutput.byteLength = byteOffset;
|
|
923
|
+
return options.output || [];
|
|
924
|
+
}
|
|
925
|
+
|
|
502
926
|
/** Reads and validates a sequence of one-byte mini-block bit widths. */
|
|
503
927
|
function readBitWidths(cursor: CursorBuffer, count: number, maximumBitWidth: number): Uint8Array {
|
|
504
928
|
assertReadable(cursor, count);
|
|
@@ -512,6 +936,42 @@ function readBitWidths(cursor: CursorBuffer, count: number, maximumBitWidth: num
|
|
|
512
936
|
return bitWidths;
|
|
513
937
|
}
|
|
514
938
|
|
|
939
|
+
/** Reads one signed zig-zag INT64 directly into its low and high two's-complement words. */
|
|
940
|
+
function readZigZagVarIntWords(cursor: CursorBuffer, words: Uint32Array): void {
|
|
941
|
+
let low = 0;
|
|
942
|
+
let high = 0;
|
|
943
|
+
for (let byteIndex = 0; byteIndex < 10; byteIndex++) {
|
|
944
|
+
assertReadable(cursor, 1);
|
|
945
|
+
const byte = cursor.buffer[cursor.offset++];
|
|
946
|
+
const payload = byte & 0x7f;
|
|
947
|
+
const bitOffset = byteIndex * 7;
|
|
948
|
+
if (byteIndex === 9 && payload > 1) {
|
|
949
|
+
throw new Error('Invalid Parquet variable-length integer');
|
|
950
|
+
}
|
|
951
|
+
if (bitOffset < 32) {
|
|
952
|
+
low |= payload << bitOffset;
|
|
953
|
+
if (bitOffset > 25) {
|
|
954
|
+
high |= payload >>> (32 - bitOffset);
|
|
955
|
+
}
|
|
956
|
+
} else {
|
|
957
|
+
high |= payload << (bitOffset - 32);
|
|
958
|
+
}
|
|
959
|
+
if ((byte & 0x80) === 0) {
|
|
960
|
+
const negative = low & 1;
|
|
961
|
+
let decodedLow = ((low >>> 1) | ((high & 1) << 31)) >>> 0;
|
|
962
|
+
let decodedHigh = high >>> 1;
|
|
963
|
+
if (negative) {
|
|
964
|
+
decodedLow = ~decodedLow >>> 0;
|
|
965
|
+
decodedHigh = ~decodedHigh >>> 0;
|
|
966
|
+
}
|
|
967
|
+
words[0] = decodedLow;
|
|
968
|
+
words[1] = decodedHigh;
|
|
969
|
+
return;
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
throw new Error('Invalid Parquet variable-length integer');
|
|
973
|
+
}
|
|
974
|
+
|
|
515
975
|
/** Reads an unsigned base-128 variable-length integer. */
|
|
516
976
|
function readUnsignedVarInt(cursor: CursorBuffer): bigint {
|
|
517
977
|
let value = 0n;
|
|
@@ -23,6 +23,10 @@ export const PARQUET_CODECS: Record<ParquetCodec, ParquetCodecKit> = {
|
|
|
23
23
|
encodeValues: RLE.encodeValues,
|
|
24
24
|
decodeValues: RLE.decodeValues
|
|
25
25
|
},
|
|
26
|
+
BIT_PACKED: {
|
|
27
|
+
encodeValues: RLE.encodeBitPackedValues,
|
|
28
|
+
decodeValues: RLE.decodeBitPackedValues
|
|
29
|
+
},
|
|
26
30
|
// Using the PLAIN_DICTIONARY enum value is deprecated in the Parquet 2.0 specification.
|
|
27
31
|
PLAIN_DICTIONARY: {
|
|
28
32
|
// @ts-ignore
|