@loaders.gl/scan 5.0.0-alpha.3 → 5.0.0-alpha.5

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/dist/delta.cjs CHANGED
@@ -3135,6 +3135,12 @@ function serializeArrowType(arrowType) {
3135
3135
  type: "list",
3136
3136
  children: [serializeArrowField(listField)]
3137
3137
  };
3138
+ case arrow.LargeList:
3139
+ const largeListType = arrowType;
3140
+ return {
3141
+ type: "large-list",
3142
+ children: [serializeArrowField(largeListType.valueField)]
3143
+ };
3138
3144
  case arrow.FixedSizeList:
3139
3145
  const fixedSizeList = arrowType;
3140
3146
  return {
@@ -3148,6 +3154,15 @@ function serializeArrowType(arrowType) {
3148
3154
  type: "struct",
3149
3155
  children: structType.children.map((arrowField) => serializeArrowField(arrowField))
3150
3156
  };
3157
+ case arrow.SparseUnion:
3158
+ case arrow.DenseUnion:
3159
+ const unionType = arrowType;
3160
+ return {
3161
+ type: unionType instanceof arrow.DenseUnion ? "dense-union" : "sparse-union",
3162
+ typeIds: unionType.typeIds,
3163
+ children: unionType.children.map((arrowField) => serializeArrowField(arrowField)),
3164
+ typeIdToChildIndex: { ...unionType.typeIdToChildIndex }
3165
+ };
3151
3166
  case arrow.Dictionary:
3152
3167
  const dictionaryType = arrowType;
3153
3168
  return {
@@ -3176,6 +3191,10 @@ function deserializeArrowType(dataType, options) {
3176
3191
  const field = deserializeArrowField(dataType.children[0], options);
3177
3192
  return new arrow.List(field);
3178
3193
  }
3194
+ case "large-list": {
3195
+ const field = deserializeArrowField(dataType.children[0], options);
3196
+ return new arrow.LargeList(field);
3197
+ }
3179
3198
  case "fixed-size-list": {
3180
3199
  const child = deserializeArrowField(dataType.children[0], options);
3181
3200
  return new arrow.FixedSizeList(dataType.listSize, child);
@@ -3188,6 +3207,13 @@ function deserializeArrowType(dataType, options) {
3188
3207
  );
3189
3208
  return new arrow.Struct(children);
3190
3209
  }
3210
+ case "sparse-union":
3211
+ case "dense-union": {
3212
+ const children = dataType.children.map(
3213
+ (arrowField) => deserializeArrowField(arrowField, options)
3214
+ );
3215
+ return dataType.type === "dense-union" ? new arrow.DenseUnion(dataType.typeIds, children) : new arrow.SparseUnion(dataType.typeIds, children);
3216
+ }
3191
3217
  case "dictionary": {
3192
3218
  return new arrow.Dictionary(
3193
3219
  deserializeArrowType(dataType.dictionary, options),
@@ -3825,8 +3851,85 @@ var init_deprecated = __esm({
3825
3851
  }
3826
3852
  });
3827
3853
 
3828
- // ../schema-utils/src/index.ts
3854
+ // ../schema/src/metadata.ts
3855
+ function getMetadataValue(metadata, key) {
3856
+ return metadata instanceof Map ? metadata.get(key) || null : metadata[key] || null;
3857
+ }
3858
+ function setMetadataValue(metadata, key, value) {
3859
+ if (metadata instanceof Map) {
3860
+ metadata.set(key, value);
3861
+ } else {
3862
+ metadata[key] = value;
3863
+ }
3864
+ }
3865
+ function getGeoMetadata(metadata) {
3866
+ if (!metadata) {
3867
+ return null;
3868
+ }
3869
+ const stringifiedGeoMetadata = getMetadataValue(metadata, "geo");
3870
+ const geoMetadata = stringifiedGeoMetadata && parseJSONStringMetadata(stringifiedGeoMetadata);
3871
+ if (!geoMetadata) {
3872
+ return null;
3873
+ }
3874
+ for (const column of Object.values(geoMetadata.columns || {})) {
3875
+ if (column && typeof column === "object" && typeof column.encoding === "string") {
3876
+ column.encoding = column.encoding.toLowerCase();
3877
+ }
3878
+ }
3879
+ return geoMetadata;
3880
+ }
3881
+ function unpackGeoMetadata(metadata) {
3882
+ const geoMetadata = getGeoMetadata(metadata);
3883
+ if (!geoMetadata) {
3884
+ return;
3885
+ }
3886
+ const { version: version2, primary_column: primaryColumn, columns } = geoMetadata;
3887
+ if (version2) {
3888
+ setMetadataValue(metadata, "geo.version", version2);
3889
+ }
3890
+ if (primaryColumn) {
3891
+ setMetadataValue(metadata, "geo.primary_column", primaryColumn);
3892
+ }
3893
+ setMetadataValue(metadata, "geo.columns", Object.keys(columns || {}).join(","));
3894
+ }
3895
+ function unpackJSONStringMetadata(metadata, metadataKey) {
3896
+ const stringifiedMetadata = getMetadataValue(metadata, metadataKey);
3897
+ const json = stringifiedMetadata && parseJSONStringMetadata(stringifiedMetadata);
3898
+ for (const [key, value] of Object.entries(json || {})) {
3899
+ setMetadataValue(
3900
+ metadata,
3901
+ `${metadataKey}.${key}`,
3902
+ typeof value === "string" ? value : JSON.stringify(value)
3903
+ );
3904
+ }
3905
+ }
3906
+ function parseJSONStringMetadata(stringifiedMetadata) {
3907
+ if (!stringifiedMetadata) {
3908
+ return null;
3909
+ }
3910
+ try {
3911
+ const metadata = JSON.parse(stringifiedMetadata);
3912
+ return metadata && typeof metadata === "object" ? metadata : null;
3913
+ } catch {
3914
+ return null;
3915
+ }
3916
+ }
3917
+ var init_metadata = __esm({
3918
+ "../schema/src/metadata.ts"() {
3919
+ "use strict";
3920
+ }
3921
+ });
3922
+
3923
+ // ../schema/src/index.ts
3829
3924
  var init_src3 = __esm({
3925
+ "../schema/src/index.ts"() {
3926
+ "use strict";
3927
+ init_metadata();
3928
+ }
3929
+ });
3930
+
3931
+ // ../schema-utils/src/index.ts
3932
+ var init_src4 = __esm({
3830
3933
  "../schema-utils/src/index.ts"() {
3831
3934
  "use strict";
3832
3935
  init_convert_arrow_schema();
@@ -4815,35 +4918,26 @@ var init_arrow_table_transport = __esm({
4815
4918
  "../arrow/src/lib/utils/arrow-table-transport.ts"() {
4816
4919
  "use strict";
4817
4920
  arrow6 = __toESM(require("apache-arrow"), 1);
4818
- init_src3();
4921
+ init_src4();
4819
4922
  init_split_arrow_buffers();
4820
4923
  }
4821
4924
  });
4822
4925
 
4823
4926
  // ../gis/src/lib/geoarrow/metadata-utils.ts
4824
- function getMetadataValue(metadata, key) {
4825
- return metadata instanceof Map ? metadata.get(key) || null : metadata[key] || null;
4826
- }
4827
- function setMetadataValue(metadata, key, value) {
4828
- if (metadata instanceof Map) {
4829
- metadata.set(key, value);
4830
- } else {
4831
- metadata[key] = value;
4832
- }
4833
- }
4834
4927
  var init_metadata_utils = __esm({
4835
4928
  "../gis/src/lib/geoarrow/metadata-utils.ts"() {
4836
4929
  "use strict";
4930
+ init_src3();
4837
4931
  }
4838
4932
  });
4839
4933
 
4840
4934
  // ../gis/src/lib/geoarrow/geoparquet-metadata.ts
4841
- function getGeoMetadata(metadata) {
4935
+ function getGeoMetadata2(metadata) {
4842
4936
  if (!metadata) {
4843
4937
  return null;
4844
4938
  }
4845
4939
  const stringifiedGeoMetadata = getMetadataValue(metadata, "geo");
4846
- const geoMetadata = stringifiedGeoMetadata && parseJSONStringMetadata(stringifiedGeoMetadata);
4940
+ const geoMetadata = stringifiedGeoMetadata && parseJSONStringMetadata2(stringifiedGeoMetadata);
4847
4941
  if (!geoMetadata) {
4848
4942
  return null;
4849
4943
  }
@@ -4854,32 +4948,7 @@ function getGeoMetadata(metadata) {
4854
4948
  }
4855
4949
  return geoMetadata;
4856
4950
  }
4857
- function unpackGeoMetadata(metadata) {
4858
- const geoMetadata = getGeoMetadata(metadata);
4859
- if (!geoMetadata) {
4860
- return;
4861
- }
4862
- const { version: version2, primary_column, columns } = geoMetadata;
4863
- if (version2) {
4864
- setMetadataValue(metadata, "geo.version", version2);
4865
- }
4866
- if (primary_column) {
4867
- setMetadataValue(metadata, "geo.primary_column", primary_column);
4868
- }
4869
- setMetadataValue(metadata, "geo.columns", Object.keys(columns || {}).join(","));
4870
- }
4871
- function unpackJSONStringMetadata(metadata, metadataKey) {
4872
- const stringifiedMetadata = getMetadataValue(metadata, metadataKey);
4873
- const json = stringifiedMetadata && parseJSONStringMetadata(stringifiedMetadata);
4874
- for (const [key, value] of Object.entries(json || {})) {
4875
- setMetadataValue(
4876
- metadata,
4877
- `${metadataKey}.${key}`,
4878
- typeof value === "string" ? value : JSON.stringify(value)
4879
- );
4880
- }
4881
- }
4882
- function parseJSONStringMetadata(stringifiedMetadata) {
4951
+ function parseJSONStringMetadata2(stringifiedMetadata) {
4883
4952
  if (!stringifiedMetadata) {
4884
4953
  return null;
4885
4954
  }
@@ -4901,16 +4970,15 @@ var init_geoparquet_metadata = __esm({
4901
4970
  });
4902
4971
 
4903
4972
  // ../gis/src/index.ts
4904
- var init_src4 = __esm({
4973
+ var init_src5 = __esm({
4905
4974
  "../gis/src/index.ts"() {
4906
4975
  "use strict";
4907
- init_metadata_utils();
4908
4976
  init_geoparquet_metadata();
4909
4977
  }
4910
4978
  });
4911
4979
 
4912
4980
  // ../arrow/src/index.ts
4913
- var init_src5 = __esm({
4981
+ var init_src6 = __esm({
4914
4982
  "../arrow/src/index.ts"() {
4915
4983
  "use strict";
4916
4984
  init_indexed_arrow_table();
@@ -5154,10 +5222,11 @@ function getGeoArrowMetadataFromGeoParquetField(field, columnMetadata) {
5154
5222
  if (!extensionName) {
5155
5223
  return null;
5156
5224
  }
5157
- if (normalizedEncoding === "wkb" && field.type !== "binary") {
5225
+ const isBinaryGeospatialEncoding = normalizedEncoding === "wkb" || normalizedEncoding === "geometry" || normalizedEncoding === "geography";
5226
+ if (isBinaryGeospatialEncoding && !isBinaryFieldType(field.type)) {
5158
5227
  return null;
5159
5228
  }
5160
- if (normalizedEncoding !== "wkb" && (field.type === "binary" || field.type === "utf8")) {
5229
+ if (!isBinaryGeospatialEncoding && (isBinaryFieldType(field.type) || isStringFieldType(field.type))) {
5161
5230
  return null;
5162
5231
  }
5163
5232
  const extensionMetadata = {};
@@ -5171,18 +5240,34 @@ function getGeoArrowMetadataFromGeoParquetField(field, columnMetadata) {
5171
5240
  if (columnMetadata.edges && columnMetadata.edges !== "planar") {
5172
5241
  extensionMetadata.edges = columnMetadata.edges;
5173
5242
  }
5243
+ if (normalizedEncoding === "geography" && !extensionMetadata.edges) {
5244
+ extensionMetadata.edges = "spherical";
5245
+ }
5246
+ for (const [metadataKey, metadataValue] of Object.entries(columnMetadata)) {
5247
+ if (metadataValue !== void 0 && metadataValue !== null && !["encoding", "geometry_types", "crs", "edges"].includes(metadataKey)) {
5248
+ extensionMetadata[metadataKey] = metadataValue;
5249
+ }
5250
+ }
5174
5251
  return Object.keys(extensionMetadata).length > 0 ? { extensionName, extensionMetadata } : { extensionName };
5175
5252
  }
5253
+ function isBinaryFieldType(fieldType) {
5254
+ return typeof fieldType === "string" && (fieldType === "binary" || fieldType === "binary-view");
5255
+ }
5256
+ function isStringFieldType(fieldType) {
5257
+ return typeof fieldType === "string" && (fieldType === "utf8" || fieldType === "utf8-view");
5258
+ }
5176
5259
  var arrow7, GEOARROW_EXTENSION_NAME_KEY, GEOARROW_EXTENSION_METADATA_KEY, GEOPARQUET_TO_GEOARROW_ENCODINGS;
5177
5260
  var init_geospatial_metadata = __esm({
5178
5261
  "../parquet/src/lib/geo/geospatial-metadata.ts"() {
5179
5262
  "use strict";
5180
5263
  arrow7 = __toESM(require("apache-arrow"), 1);
5181
- init_src4();
5264
+ init_src3();
5182
5265
  GEOARROW_EXTENSION_NAME_KEY = "ARROW:extension:name";
5183
5266
  GEOARROW_EXTENSION_METADATA_KEY = "ARROW:extension:metadata";
5184
5267
  GEOPARQUET_TO_GEOARROW_ENCODINGS = {
5185
5268
  wkb: "geoarrow.wkb",
5269
+ geometry: "geoarrow.wkb",
5270
+ geography: "geoarrow.wkb",
5186
5271
  point: "geoarrow.point",
5187
5272
  linestring: "geoarrow.linestring",
5188
5273
  polygon: "geoarrow.polygon",
@@ -5208,7 +5293,7 @@ async function getSchemaFromParquetReader(reader) {
5208
5293
  var init_get_parquet_schema = __esm({
5209
5294
  "../parquet/src/lib/parsers/get-parquet-schema.ts"() {
5210
5295
  "use strict";
5211
- init_src4();
5296
+ init_src3();
5212
5297
  init_convert_schema_from_parquet();
5213
5298
  init_geospatial_metadata();
5214
5299
  }
@@ -5320,7 +5405,7 @@ function doLongitudeIntervalsIntersect(firstWest, firstEast, secondWest, secondE
5320
5405
  var init_geoparquet_covering = __esm({
5321
5406
  "../parquet/src/lib/geo/geoparquet-covering.ts"() {
5322
5407
  "use strict";
5323
- init_src4();
5408
+ init_src3();
5324
5409
  }
5325
5410
  });
5326
5411
 
@@ -12044,7 +12129,7 @@ var init_parse_bson = __esm({
12044
12129
  });
12045
12130
 
12046
12131
  // ../bson/src/index.ts
12047
- var init_src6 = __esm({
12132
+ var init_src7 = __esm({
12048
12133
  "../bson/src/index.ts"() {
12049
12134
  "use strict";
12050
12135
  init_bson_writer();
@@ -12453,7 +12538,7 @@ var PARQUET_LOGICAL_TYPES, kMillisPerDay;
12453
12538
  var init_types = __esm({
12454
12539
  "../parquet/src/parquetjs/schema/types.ts"() {
12455
12540
  "use strict";
12456
- init_src6();
12541
+ init_src7();
12457
12542
  init_binary_utils();
12458
12543
  PARQUET_LOGICAL_TYPES = {
12459
12544
  BOOLEAN: {
@@ -16474,7 +16559,7 @@ var init_default_codecs = __esm({
16474
16559
  });
16475
16560
 
16476
16561
  // ../compression/src/index.ts
16477
- var init_src7 = __esm({
16562
+ var init_src8 = __esm({
16478
16563
  "../compression/src/index.ts"() {
16479
16564
  "use strict";
16480
16565
  init_compression();
@@ -16587,7 +16672,7 @@ var PARQUET_COMPRESSION_METHODS, ParquetSnappyDecompressor;
16587
16672
  var init_compression2 = __esm({
16588
16673
  "../parquet/src/parquetjs/compression.ts"() {
16589
16674
  "use strict";
16590
- init_src7();
16675
+ init_src8();
16591
16676
  init_snappy_decompressor_hysnappy();
16592
16677
  init_src2();
16593
16678
  init_binary_utils();
@@ -20676,6 +20761,201 @@ var init_decoders = __esm({
20676
20761
  }
20677
20762
  });
20678
20763
 
20764
+ // ../parquet/src/parquetjs/parser/encoded-pages.ts
20765
+ async function scanParquetEncodedPages(buffer, context) {
20766
+ const pages = [];
20767
+ let offset = 0;
20768
+ let dataPageOrdinal = 0;
20769
+ while (offset < buffer.byteLength) {
20770
+ const { pageHeader, length: headerByteLength } = decodePageHeader(buffer, offset);
20771
+ const bodyOffset = offset + headerByteLength;
20772
+ const bodyEnd = bodyOffset + pageHeader.compressed_page_size;
20773
+ if (pageHeader.compressed_page_size < 0 || pageHeader.uncompressed_page_size < 0 || bodyEnd > buffer.byteLength) {
20774
+ throw new Error("Parquet page extends beyond the available column-chunk buffer");
20775
+ }
20776
+ const compressedBody = buffer.subarray(bodyOffset, bodyEnd);
20777
+ verifyEncodedPageChecksum(compressedBody, pageHeader, context.verifyPageChecksums);
20778
+ const pageType = getThriftEnum(PageType, pageHeader.type);
20779
+ if (pageType === "DICTIONARY_PAGE") {
20780
+ pages.push(await createDictionaryPage(compressedBody, pageHeader, context));
20781
+ } else if (pageType === "DATA_PAGE") {
20782
+ pages.push(await createDataPageV1(compressedBody, pageHeader, context, dataPageOrdinal++));
20783
+ } else if (pageType === "DATA_PAGE_V2") {
20784
+ pages.push(await createDataPageV2(compressedBody, pageHeader, context, dataPageOrdinal++));
20785
+ } else {
20786
+ throw new Error(`Unsupported Parquet page type ${pageType}`);
20787
+ }
20788
+ offset = bodyEnd;
20789
+ }
20790
+ return pages;
20791
+ }
20792
+ async function createDictionaryPage(compressedBody, pageHeader, context) {
20793
+ const dictionaryHeader = pageHeader.dictionary_page_header;
20794
+ if (!dictionaryHeader) {
20795
+ throw new Error("Parquet dictionary page is missing its dictionary header");
20796
+ }
20797
+ const preserveCompression = shouldPreserveCompression(context);
20798
+ const data = preserveCompression ? compressedBody : await decompressPageBody(compressedBody, pageHeader.uncompressed_page_size, context);
20799
+ return Object.freeze({
20800
+ type: "dictionary",
20801
+ pageOrdinal: -1,
20802
+ encoding: getThriftEnum(Encoding, dictionaryHeader.encoding),
20803
+ compression: context.compression,
20804
+ compressionState: preserveCompression ? "compressed" : "decompressed",
20805
+ valueCount: dictionaryHeader.num_values,
20806
+ nonNullValueCount: dictionaryHeader.num_values,
20807
+ data,
20808
+ values: preserveCompression ? void 0 : createSection(0, data.byteLength),
20809
+ compressedByteLength: pageHeader.compressed_page_size,
20810
+ uncompressedByteLength: pageHeader.uncompressed_page_size
20811
+ });
20812
+ }
20813
+ async function createDataPageV1(compressedBody, pageHeader, context, pageOrdinal) {
20814
+ const dataHeader = pageHeader.data_page_header;
20815
+ if (!dataHeader) {
20816
+ throw new Error("Parquet V1 data page is missing its data header");
20817
+ }
20818
+ const preserveCompression = shouldPreserveCompression(context);
20819
+ const data = preserveCompression ? compressedBody : await decompressPageBody(compressedBody, pageHeader.uncompressed_page_size, context);
20820
+ let repetitionLevels;
20821
+ let definitionLevels;
20822
+ let values;
20823
+ if (!preserveCompression) {
20824
+ let sectionOffset = 0;
20825
+ const repetitionLevelEncoding = getThriftEnum(Encoding, dataHeader.repetition_level_encoding);
20826
+ repetitionLevels = readV1LevelSection(
20827
+ data,
20828
+ sectionOffset,
20829
+ dataHeader.num_values,
20830
+ context.column.rLevelMax,
20831
+ repetitionLevelEncoding
20832
+ );
20833
+ sectionOffset = repetitionLevels.byteOffset + repetitionLevels.byteLength;
20834
+ const definitionLevelEncoding = getThriftEnum(Encoding, dataHeader.definition_level_encoding);
20835
+ definitionLevels = readV1LevelSection(
20836
+ data,
20837
+ sectionOffset,
20838
+ dataHeader.num_values,
20839
+ context.column.dLevelMax,
20840
+ definitionLevelEncoding
20841
+ );
20842
+ sectionOffset = definitionLevels.byteOffset + definitionLevels.byteLength;
20843
+ values = createSection(sectionOffset, data.byteLength - sectionOffset);
20844
+ }
20845
+ return Object.freeze({
20846
+ type: "data-v1",
20847
+ pageOrdinal,
20848
+ encoding: getThriftEnum(Encoding, dataHeader.encoding),
20849
+ repetitionLevelEncoding: getThriftEnum(Encoding, dataHeader.repetition_level_encoding),
20850
+ definitionLevelEncoding: getThriftEnum(Encoding, dataHeader.definition_level_encoding),
20851
+ compression: context.compression,
20852
+ compressionState: preserveCompression ? "compressed" : "decompressed",
20853
+ valueCount: dataHeader.num_values,
20854
+ data,
20855
+ repetitionLevels,
20856
+ definitionLevels,
20857
+ values,
20858
+ compressedByteLength: pageHeader.compressed_page_size,
20859
+ uncompressedByteLength: pageHeader.uncompressed_page_size
20860
+ });
20861
+ }
20862
+ async function createDataPageV2(compressedBody, pageHeader, context, pageOrdinal) {
20863
+ const dataHeader = pageHeader.data_page_header_v2;
20864
+ if (!dataHeader) {
20865
+ throw new Error("Parquet V2 data page is missing its data header");
20866
+ }
20867
+ const repetitionByteLength = dataHeader.repetition_levels_byte_length;
20868
+ const definitionByteLength = dataHeader.definition_levels_byte_length;
20869
+ const levelsByteLength = repetitionByteLength + definitionByteLength;
20870
+ if (levelsByteLength > compressedBody.byteLength) {
20871
+ throw new Error("Parquet V2 level sections extend beyond the page body");
20872
+ }
20873
+ const valuesAreCompressed = dataHeader.is_compressed !== false && context.compression !== "UNCOMPRESSED";
20874
+ const preserveCompression = valuesAreCompressed && shouldPreserveCompression(context);
20875
+ let data = compressedBody;
20876
+ if (valuesAreCompressed && !preserveCompression) {
20877
+ const uncompressedValuesByteLength = pageHeader.uncompressed_page_size - levelsByteLength;
20878
+ if (uncompressedValuesByteLength < 0) {
20879
+ throw new Error("Invalid Parquet V2 uncompressed value length");
20880
+ }
20881
+ const values = await context.decompressPage(
20882
+ compressedBody.subarray(levelsByteLength),
20883
+ uncompressedValuesByteLength
20884
+ );
20885
+ data = new Uint8Array(levelsByteLength + values.byteLength);
20886
+ data.set(compressedBody.subarray(0, levelsByteLength));
20887
+ data.set(values, levelsByteLength);
20888
+ }
20889
+ return Object.freeze({
20890
+ type: "data-v2",
20891
+ pageOrdinal,
20892
+ encoding: getThriftEnum(Encoding, dataHeader.encoding),
20893
+ repetitionLevelEncoding: "RLE",
20894
+ definitionLevelEncoding: "RLE",
20895
+ compression: context.compression,
20896
+ compressionState: preserveCompression ? "compressed" : "decompressed",
20897
+ valueCount: dataHeader.num_values,
20898
+ nonNullValueCount: dataHeader.num_values - dataHeader.num_nulls,
20899
+ data,
20900
+ repetitionLevels: createSection(0, repetitionByteLength),
20901
+ definitionLevels: createSection(repetitionByteLength, definitionByteLength),
20902
+ values: createSection(levelsByteLength, data.byteLength - levelsByteLength),
20903
+ compressedByteLength: pageHeader.compressed_page_size,
20904
+ uncompressedByteLength: pageHeader.uncompressed_page_size
20905
+ });
20906
+ }
20907
+ function shouldPreserveCompression(context) {
20908
+ var _a;
20909
+ return context.compression !== "UNCOMPRESSED" && Boolean((_a = context.preserveCompression) == null ? void 0 : _a.has(context.compression));
20910
+ }
20911
+ async function decompressPageBody(compressedBody, uncompressedByteLength, context) {
20912
+ if (context.compression === "UNCOMPRESSED") return compressedBody;
20913
+ return await context.decompressPage(compressedBody, uncompressedByteLength);
20914
+ }
20915
+ function readV1LevelSection(data, offset, valueCount, maxLevel, encoding) {
20916
+ if (maxLevel === 0) return createSection(offset, 0);
20917
+ if (encoding === "RLE") {
20918
+ if (offset + 4 > data.byteLength) {
20919
+ throw new Error("Parquet V1 RLE level stream is missing its length prefix");
20920
+ }
20921
+ const byteLength = readUInt32LE(data, offset);
20922
+ const byteOffset = offset + 4;
20923
+ assertSectionBounds(data, byteOffset, byteLength);
20924
+ return createSection(byteOffset, byteLength);
20925
+ }
20926
+ if (encoding === "BIT_PACKED") {
20927
+ const byteLength = Math.ceil(valueCount / 8) * getBitWidth(maxLevel);
20928
+ assertSectionBounds(data, offset, byteLength);
20929
+ return createSection(offset, byteLength);
20930
+ }
20931
+ throw new Error(`Unsupported Parquet V1 level encoding ${encoding}`);
20932
+ }
20933
+ function createSection(byteOffset, byteLength) {
20934
+ return Object.freeze({ byteOffset, byteLength });
20935
+ }
20936
+ function assertSectionBounds(data, byteOffset, byteLength) {
20937
+ if (byteOffset < 0 || byteLength < 0 || byteOffset + byteLength > data.byteLength) {
20938
+ throw new Error("Parquet page section extends beyond the page body");
20939
+ }
20940
+ }
20941
+ function verifyEncodedPageChecksum(compressedBody, pageHeader, verifyPageChecksums = false) {
20942
+ if (!verifyPageChecksums || pageHeader.crc === void 0) return;
20943
+ const expected = pageHeader.crc >>> 0;
20944
+ const actual = crc32(compressedBody);
20945
+ if (actual !== expected) {
20946
+ throw new Error(`Parquet page checksum mismatch: expected ${expected}, calculated ${actual}`);
20947
+ }
20948
+ }
20949
+ var init_encoded_pages = __esm({
20950
+ "../parquet/src/parquetjs/parser/encoded-pages.ts"() {
20951
+ "use strict";
20952
+ init_parquet_thrift();
20953
+ init_crc32();
20954
+ init_binary_utils();
20955
+ init_read_utils();
20956
+ }
20957
+ });
20958
+
20679
20959
  // ../parquet/src/lib/parquet-encryption.ts
20680
20960
  function readParquetEncryptedModule(buffer, offset = 0) {
20681
20961
  if (offset + 4 > buffer.length) {
@@ -20918,6 +21198,7 @@ var init_parquet_reader = __esm({
20918
21198
  "use strict";
20919
21199
  init_schema();
20920
21200
  init_decoders();
21201
+ init_encoded_pages();
20921
21202
  init_shred();
20922
21203
  init_compression2();
20923
21204
  init_constants();
@@ -21404,6 +21685,50 @@ var init_parquet_reader = __esm({
21404
21685
  columnData: Object.fromEntries(columnEntries)
21405
21686
  };
21406
21687
  }
21688
+ /**
21689
+ * Reads selected column chunks as encoded page descriptors without materializing values.
21690
+ *
21691
+ * Page headers, encryption, checksums, and optional decompression remain reader concerns. Value,
21692
+ * dictionary, and level decoding is deliberately left to the downstream consumer.
21693
+ */
21694
+ async readRowGroupEncodedPages(schema, rowGroup, columnList, preserveCompression, signal, rowGroupOrdinal = 0) {
21695
+ await this.resolveColumnMetadata(rowGroup, rowGroupOrdinal, columnList);
21696
+ const selectedColumnChunks = [];
21697
+ for (let columnOrdinal = 0; columnOrdinal < rowGroup.columns.length; columnOrdinal++) {
21698
+ const columnChunk = rowGroup.columns[columnOrdinal];
21699
+ const path = getColumnChunkPath(columnChunk);
21700
+ if (columnList.length > 0 && (!path || fieldIndexOf(columnList, path) < 0)) continue;
21701
+ const physicalColumnOrdinal = getPhysicalColumnOrdinal(columnChunk, columnOrdinal);
21702
+ const metadata = columnChunk.meta_data || await this.getColumnMetadata(columnChunk, rowGroupOrdinal, physicalColumnOrdinal);
21703
+ if (columnList.length === 0 || fieldIndexOf(columnList, metadata.path_in_schema) >= 0) {
21704
+ selectedColumnChunks.push({
21705
+ columnChunk,
21706
+ metadata,
21707
+ columnOrdinal: physicalColumnOrdinal
21708
+ });
21709
+ }
21710
+ }
21711
+ const columns = [];
21712
+ for (let batchStart = 0; batchStart < selectedColumnChunks.length; batchStart += MAXIMUM_CONCURRENT_COLUMN_READS) {
21713
+ columns.push(
21714
+ ...await Promise.all(
21715
+ selectedColumnChunks.slice(batchStart, batchStart + MAXIMUM_CONCURRENT_COLUMN_READS).map(async ({ columnChunk, metadata, columnOrdinal }) => {
21716
+ const encodedColumn = await this.readColumnChunkEncodedPages(
21717
+ schema,
21718
+ columnChunk,
21719
+ preserveCompression,
21720
+ signal,
21721
+ rowGroupOrdinal,
21722
+ columnOrdinal,
21723
+ metadata
21724
+ );
21725
+ return encodedColumn;
21726
+ })
21727
+ )
21728
+ );
21729
+ }
21730
+ return Object.freeze(columns);
21731
+ }
21407
21732
  /** Reads independently materializable non-repeated columns for one row range using page indexes. */
21408
21733
  async readRowGroupRange(schema, rowGroup, columnList, rowRange, pageLocations, signal, rowGroupOrdinal = 0) {
21409
21734
  await this.resolveColumnMetadata(rowGroup, rowGroupOrdinal, columnList);
@@ -21596,6 +21921,99 @@ var init_parquet_reader = __esm({
21596
21921
  ) : chunkBuffer.subarray(pagesRelativeOffset, pagesRelativeOffset + pagesSize);
21597
21922
  return await decodeDataPages(pagesBuf, { ...context, dictionary });
21598
21923
  }
21924
+ /** Reads one column chunk as encoded dictionaries, levels, and values for deferred decoding. */
21925
+ async readColumnChunkEncodedPages(schema, columnChunk, preserveCompression, signal, rowGroupOrdinal = 0, columnOrdinal = 0, resolvedMetadata) {
21926
+ if (columnChunk.file_path !== void 0 && columnChunk.file_path !== null) {
21927
+ throw new Error("external references are not supported");
21928
+ }
21929
+ const metadata = resolvedMetadata || columnChunk.meta_data;
21930
+ if (!metadata) throw new Error("Parquet column metadata is missing");
21931
+ const field = schema.findField(metadata.path_in_schema);
21932
+ const physicalType = getThriftEnum(Type, metadata.type);
21933
+ if (physicalType !== field.primitiveType) {
21934
+ throw new Error(`chunk type not matching schema: ${physicalType}`);
21935
+ }
21936
+ const compression = getThriftEnum(CompressionCodec, metadata.codec);
21937
+ const dataPageOffset = Number(metadata.data_page_offset);
21938
+ const dictionaryPageOffset = metadata.dictionary_page_offset;
21939
+ const validDictionaryPageOffset = dictionaryPageOffset !== void 0 && Number(dictionaryPageOffset) > 0 ? Number(dictionaryPageOffset) : void 0;
21940
+ const chunkOffset = Math.min(dataPageOffset, validDictionaryPageOffset ?? dataPageOffset);
21941
+ const chunkEnd = chunkOffset + Number(metadata.total_compressed_size);
21942
+ const chunkByteLength = Math.min(
21943
+ this.file.size - chunkOffset,
21944
+ Math.max(0, chunkEnd - chunkOffset)
21945
+ );
21946
+ const chunkBuffer = await this.readBytes(chunkOffset, chunkByteLength, signal);
21947
+ const dataPageRelativeOffset = dataPageOffset - chunkOffset;
21948
+ const dataPageByteLength = Math.min(
21949
+ chunkBuffer.byteLength - dataPageRelativeOffset,
21950
+ Math.max(0, chunkEnd - dataPageOffset)
21951
+ );
21952
+ const context = {
21953
+ column: field,
21954
+ compression,
21955
+ decompressPage: this.getPageDecompressor(compression),
21956
+ preserveCompression,
21957
+ verifyPageChecksums: this.props.verifyPageChecksums
21958
+ };
21959
+ let dictionary;
21960
+ if (validDictionaryPageOffset !== void 0) {
21961
+ const dictionaryRelativeOffset = validDictionaryPageOffset - chunkOffset;
21962
+ const dictionaryByteLength = Math.min(
21963
+ Math.max(0, dataPageOffset - validDictionaryPageOffset),
21964
+ chunkBuffer.byteLength - dictionaryRelativeOffset,
21965
+ this.props.defaultDictionarySize
21966
+ );
21967
+ const dictionaryBuffer = chunkBuffer.subarray(
21968
+ dictionaryRelativeOffset,
21969
+ dictionaryRelativeOffset + dictionaryByteLength
21970
+ );
21971
+ const plaintextDictionaryBuffer = columnChunk.crypto_metadata ? await this.decryptColumnPages(
21972
+ dictionaryBuffer,
21973
+ {
21974
+ type: physicalType,
21975
+ rLevelMax: field.rLevelMax,
21976
+ dLevelMax: field.dLevelMax,
21977
+ compression,
21978
+ column: field
21979
+ },
21980
+ rowGroupOrdinal,
21981
+ columnOrdinal,
21982
+ this.getColumnKeyMetadata(columnChunk),
21983
+ true
21984
+ ) : dictionaryBuffer;
21985
+ dictionary = (await scanParquetEncodedPages(plaintextDictionaryBuffer, context))[0];
21986
+ }
21987
+ const dataPageBuffer = chunkBuffer.subarray(
21988
+ dataPageRelativeOffset,
21989
+ dataPageRelativeOffset + dataPageByteLength
21990
+ );
21991
+ const plaintextDataPageBuffer = columnChunk.crypto_metadata ? await this.decryptColumnPages(
21992
+ dataPageBuffer,
21993
+ {
21994
+ type: physicalType,
21995
+ rLevelMax: field.rLevelMax,
21996
+ dLevelMax: field.dLevelMax,
21997
+ compression,
21998
+ column: field
21999
+ },
22000
+ rowGroupOrdinal,
22001
+ columnOrdinal,
22002
+ this.getColumnKeyMetadata(columnChunk)
22003
+ ) : dataPageBuffer;
22004
+ const pages = await scanParquetEncodedPages(plaintextDataPageBuffer, context);
22005
+ return Object.freeze({
22006
+ path: Object.freeze([...metadata.path_in_schema]),
22007
+ physicalType,
22008
+ typeLength: field.typeLength,
22009
+ maxRepetitionLevel: field.rLevelMax,
22010
+ maxDefinitionLevel: field.dLevelMax,
22011
+ compression,
22012
+ valueCount: Number(metadata.num_values),
22013
+ dictionary,
22014
+ pages: Object.freeze(pages)
22015
+ });
22016
+ }
21599
22017
  /** Decrypts the length-prefixed page header and data modules in one column chunk. */
21600
22018
  async decryptColumnPages(encryptedPages, context, rowGroupOrdinal, columnOrdinal, keyMetadata, includesDictionary = false, dataPageOrdinalStart = 0) {
21601
22019
  if (!this.encryptionContext || !this.props.keyRetriever) {
@@ -22416,9 +22834,10 @@ var _preloadParquetSourceLoader, _createMetadataDataSource, ParquetSourceLoaderB
22416
22834
  var init_parquet_source_loader = __esm({
22417
22835
  "../parquet/src/parquet-source-loader.ts"() {
22418
22836
  "use strict";
22419
- init_src5();
22837
+ init_src6();
22420
22838
  init_src2();
22421
- init_src3();
22839
+ init_src4();
22840
+ init_src5();
22422
22841
  init_get_parquet_schema();
22423
22842
  init_geoparquet_covering();
22424
22843
  init_parquet_bloom_filter();
@@ -22572,6 +22991,73 @@ var init_parquet_source_loader = __esm({
22572
22991
  scan(options = {}) {
22573
22992
  return this.read(options);
22574
22993
  }
22994
+ /**
22995
+ * Reads candidate encoded pages without decoding values or constructing Arrow arrays.
22996
+ *
22997
+ * Footer statistics and Bloom filters prune complete row groups. Any exact predicate or spatial
22998
+ * filter is returned as residual work, and its hidden columns are included in the page batch.
22999
+ */
23000
+ async *readPages(options = {}) {
23001
+ const readOptions = this.getReadOptions({
23002
+ rowGroups: options.rowGroups,
23003
+ columns: options.columns,
23004
+ rowGroupFilter: options.rowGroupFilter,
23005
+ predicate: options.predicate,
23006
+ bbox: options.bbox,
23007
+ geometryColumn: options.geometryColumn,
23008
+ signal: options.signal
23009
+ });
23010
+ const readContext = createReadAbortContext(readOptions.signal);
23011
+ this.activeReadControllers.add(readContext.abortController);
23012
+ try {
23013
+ const initialization = await this.getInitialization(readContext.abortController.signal);
23014
+ await this.getCompressionInitialization();
23015
+ throwIfAborted2(readContext.abortController.signal);
23016
+ const physicalPlan = await this.planRowGroups(
23017
+ initialization,
23018
+ readOptions,
23019
+ readContext.abortController.signal
23020
+ );
23021
+ const projectedColumns = normalizeColumns(readOptions.columns, initialization.schema);
23022
+ const predicateColumns = physicalPlan.predicate ? getParquetPredicateColumns(physicalPlan.predicate) : [];
23023
+ const geoMetadata = readOptions.bbox ? getGeoMetadata2(initialization.schema.metadata) : void 0;
23024
+ const geometryColumn = readOptions.bbox ? readOptions.geometryColumn || (geoMetadata == null ? void 0 : geoMetadata.primary_column) : void 0;
23025
+ const filterColumns = [
23026
+ .../* @__PURE__ */ new Set([...predicateColumns, ...geometryColumn ? [geometryColumn] : []])
23027
+ ];
23028
+ const decodedColumns = projectedColumns.length === 0 ? [] : [.../* @__PURE__ */ new Set([...projectedColumns, ...filterColumns])];
23029
+ const columnList = decodedColumns.map((column) => [column]);
23030
+ const preserveCompression = new Set(options.preserveCompression ?? []);
23031
+ const residualFilter = readOptions.predicate || readOptions.bbox ? Object.freeze({
23032
+ predicate: readOptions.predicate,
23033
+ bbox: readOptions.bbox,
23034
+ geometryColumn
23035
+ }) : void 0;
23036
+ for (const rowGroupIndex of physicalPlan.rowGroupIndices) {
23037
+ throwIfAborted2(readContext.abortController.signal);
23038
+ const columns = await initialization.reader.readRowGroupEncodedPages(
23039
+ initialization.parquetSchema,
23040
+ initialization.fileMetadata.row_groups[rowGroupIndex],
23041
+ columnList,
23042
+ preserveCompression,
23043
+ readContext.abortController.signal,
23044
+ rowGroupIndex
23045
+ );
23046
+ yield Object.freeze({
23047
+ shape: "parquet-encoded-pages",
23048
+ rowGroup: initialization.metadata.rowGroups[rowGroupIndex],
23049
+ projectedColumns: Object.freeze([...projectedColumns]),
23050
+ filterColumns: Object.freeze(filterColumns),
23051
+ columns,
23052
+ residualFilter
23053
+ });
23054
+ }
23055
+ } finally {
23056
+ readContext.abortController.abort();
23057
+ readContext.removeSignalListener();
23058
+ this.activeReadControllers.delete(readContext.abortController);
23059
+ }
23060
+ }
22575
23061
  /** Returns a copy of cumulative transport, decode, conversion, and pruning telemetry. */
22576
23062
  getTelemetry() {
22577
23063
  return Object.freeze({ ...this.telemetry });