@loaders.gl/parquet 5.0.0-alpha.2 → 5.0.0-alpha.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 (336) hide show
  1. package/LICENSE +1 -1
  2. package/dist/bundled.d.ts +1 -1
  3. package/dist/bundled.d.ts.map +1 -1
  4. package/dist/bundled.js.map +1 -1
  5. package/dist/delta-format.d.ts +9 -0
  6. package/dist/delta-format.d.ts.map +1 -0
  7. package/dist/delta-format.js +12 -0
  8. package/dist/delta-format.js.map +1 -0
  9. package/dist/delta-source-loader-types.d.ts +27 -0
  10. package/dist/delta-source-loader-types.d.ts.map +1 -0
  11. package/dist/delta-source-loader-types.js +28 -0
  12. package/dist/delta-source-loader-types.js.map +1 -0
  13. package/dist/delta-source.d.ts +48 -0
  14. package/dist/delta-source.d.ts.map +1 -0
  15. package/dist/delta-source.js +222 -0
  16. package/dist/delta-source.js.map +1 -0
  17. package/dist/delta-types.d.ts +38 -0
  18. package/dist/delta-types.d.ts.map +1 -0
  19. package/dist/delta-types.js +5 -0
  20. package/dist/delta-types.js.map +1 -0
  21. package/dist/geoparquet-loader.js +1 -1
  22. package/dist/iceberg-rest-catalog.d.ts +49 -0
  23. package/dist/iceberg-rest-catalog.d.ts.map +1 -0
  24. package/dist/iceberg-rest-catalog.js +78 -0
  25. package/dist/iceberg-rest-catalog.js.map +1 -0
  26. package/dist/iceberg-table-source.d.ts +63 -0
  27. package/dist/iceberg-table-source.d.ts.map +1 -0
  28. package/dist/iceberg-table-source.js +797 -0
  29. package/dist/iceberg-table-source.js.map +1 -0
  30. package/dist/iceberg-types.d.ts +150 -0
  31. package/dist/iceberg-types.d.ts.map +1 -0
  32. package/dist/iceberg-types.js +5 -0
  33. package/dist/iceberg-types.js.map +1 -0
  34. package/dist/index.cjs +15841 -3306
  35. package/dist/index.cjs.map +3 -3
  36. package/dist/index.d.ts +8 -3
  37. package/dist/index.d.ts.map +1 -1
  38. package/dist/index.js +5 -1
  39. package/dist/index.js.map +1 -1
  40. package/dist/lib/arrow/convert-schema-from-parquet.d.ts +3 -1
  41. package/dist/lib/arrow/convert-schema-from-parquet.d.ts.map +1 -1
  42. package/dist/lib/arrow/convert-schema-from-parquet.js +94 -19
  43. package/dist/lib/arrow/convert-schema-from-parquet.js.map +1 -1
  44. package/dist/lib/arrow/create-nested-arrow-vector.js +89 -0
  45. package/dist/lib/arrow/create-nested-arrow-vector.js.map +1 -1
  46. package/dist/lib/constants.js +1 -1
  47. package/dist/lib/encoders/encode-table-to-parquet-js.d.ts.map +1 -1
  48. package/dist/lib/encoders/encode-table-to-parquet-js.js +202 -7
  49. package/dist/lib/encoders/encode-table-to-parquet-js.js.map +1 -1
  50. package/dist/lib/geo/geoparquet-covering.d.ts +19 -0
  51. package/dist/lib/geo/geoparquet-covering.d.ts.map +1 -0
  52. package/dist/lib/geo/geoparquet-covering.js +137 -0
  53. package/dist/lib/geo/geoparquet-covering.js.map +1 -0
  54. package/dist/lib/geo/geospatial-metadata.d.ts.map +1 -1
  55. package/dist/lib/geo/geospatial-metadata.js +39 -13
  56. package/dist/lib/geo/geospatial-metadata.js.map +1 -1
  57. package/dist/lib/parquet-bloom-filter-planner.d.ts +16 -0
  58. package/dist/lib/parquet-bloom-filter-planner.d.ts.map +1 -0
  59. package/dist/lib/parquet-bloom-filter-planner.js +57 -0
  60. package/dist/lib/parquet-bloom-filter-planner.js.map +1 -0
  61. package/dist/lib/parquet-bloom-filter.d.ts +30 -0
  62. package/dist/lib/parquet-bloom-filter.d.ts.map +1 -0
  63. package/dist/lib/parquet-bloom-filter.js +289 -0
  64. package/dist/lib/parquet-bloom-filter.js.map +1 -0
  65. package/dist/lib/parquet-encryption.d.ts +80 -0
  66. package/dist/lib/parquet-encryption.d.ts.map +1 -0
  67. package/dist/lib/parquet-encryption.js +190 -0
  68. package/dist/lib/parquet-encryption.js.map +1 -0
  69. package/dist/lib/parquet-page-index.d.ts +34 -5
  70. package/dist/lib/parquet-page-index.d.ts.map +1 -1
  71. package/dist/lib/parquet-page-index.js +114 -28
  72. package/dist/lib/parquet-page-index.js.map +1 -1
  73. package/dist/lib/parquet-predicate.d.ts +5 -1
  74. package/dist/lib/parquet-predicate.d.ts.map +1 -1
  75. package/dist/lib/parquet-predicate.js +42 -14
  76. package/dist/lib/parquet-predicate.js.map +1 -1
  77. package/dist/lib/parquet-source-worker-decoder.d.ts +4 -1
  78. package/dist/lib/parquet-source-worker-decoder.d.ts.map +1 -1
  79. package/dist/lib/parquet-source-worker-decoder.js +83 -17
  80. package/dist/lib/parquet-source-worker-decoder.js.map +1 -1
  81. package/dist/lib/parquet-source-worker-types.d.ts +24 -0
  82. package/dist/lib/parquet-source-worker-types.d.ts.map +1 -1
  83. package/dist/lib/parsers/get-parquet-schema.d.ts.map +1 -1
  84. package/dist/lib/parsers/get-parquet-schema.js +3 -1
  85. package/dist/lib/parsers/get-parquet-schema.js.map +1 -1
  86. package/dist/lib/parsers/parse-parquet-to-arrow-js.d.ts.map +1 -1
  87. package/dist/lib/parsers/parse-parquet-to-arrow-js.js +327 -18
  88. package/dist/lib/parsers/parse-parquet-to-arrow-js.js.map +1 -1
  89. package/dist/lib/parsers/parse-parquet-to-arrow.d.ts.map +1 -1
  90. package/dist/lib/parsers/parse-parquet-to-arrow.js +5 -5
  91. package/dist/lib/parsers/parse-parquet-to-arrow.js.map +1 -1
  92. package/dist/lib/parsers/parse-parquet-to-columns.d.ts.map +1 -1
  93. package/dist/lib/parsers/parse-parquet-to-columns.js +3 -1
  94. package/dist/lib/parsers/parse-parquet-to-columns.js.map +1 -1
  95. package/dist/lib/parsers/parse-parquet-to-json.d.ts.map +1 -1
  96. package/dist/lib/parsers/parse-parquet-to-json.js +18 -2
  97. package/dist/lib/parsers/parse-parquet-to-json.js.map +1 -1
  98. package/dist/lib/slice-parquet-batch.d.ts +9 -0
  99. package/dist/lib/slice-parquet-batch.d.ts.map +1 -0
  100. package/dist/lib/slice-parquet-batch.js +28 -0
  101. package/dist/lib/slice-parquet-batch.js.map +1 -0
  102. package/dist/lib/sources/parquet-range-file.d.ts +1 -1
  103. package/dist/lib/sources/parquet-range-file.d.ts.map +1 -1
  104. package/dist/lib/sources/parquet-range-file.js +28 -22
  105. package/dist/lib/sources/parquet-range-file.js.map +1 -1
  106. package/dist/lib/utils/normalize-parquet-options.d.ts.map +1 -1
  107. package/dist/lib/utils/normalize-parquet-options.js +15 -1
  108. package/dist/lib/utils/normalize-parquet-options.js.map +1 -1
  109. package/dist/parquet-dataset-source.cjs +16528 -4928
  110. package/dist/parquet-dataset-source.cjs.map +3 -3
  111. package/dist/parquet-dataset-source.d.ts +31 -4
  112. package/dist/parquet-dataset-source.d.ts.map +1 -1
  113. package/dist/parquet-dataset-source.js +296 -74
  114. package/dist/parquet-dataset-source.js.map +1 -1
  115. package/dist/parquet-encoded-page-types.d.ts +108 -0
  116. package/dist/parquet-encoded-page-types.d.ts.map +1 -0
  117. package/dist/parquet-encoded-page-types.js +5 -0
  118. package/dist/parquet-encoded-page-types.js.map +1 -0
  119. package/dist/parquet-js-loader-types.d.ts +2 -0
  120. package/dist/parquet-js-loader-types.d.ts.map +1 -1
  121. package/dist/parquet-js-loader-types.js +2 -1
  122. package/dist/parquet-js-loader-types.js.map +1 -1
  123. package/dist/parquet-js-loader.d.ts +1 -0
  124. package/dist/parquet-js-loader.d.ts.map +1 -1
  125. package/dist/parquet-js-loader.js +2 -1
  126. package/dist/parquet-js-loader.js.map +1 -1
  127. package/dist/parquet-js-writer.d.ts +23 -2
  128. package/dist/parquet-js-writer.d.ts.map +1 -1
  129. package/dist/parquet-js-writer.js +1 -1
  130. package/dist/parquet-js-writer.js.map +1 -1
  131. package/dist/parquet-loader-base.js +1 -1
  132. package/dist/parquet-loader-options.d.ts +11 -0
  133. package/dist/parquet-loader-options.d.ts.map +1 -1
  134. package/dist/parquet-loader-options.js.map +1 -1
  135. package/dist/parquet-source-capabilities.d.ts +8 -1
  136. package/dist/parquet-source-capabilities.d.ts.map +1 -1
  137. package/dist/parquet-source-capabilities.js +10 -0
  138. package/dist/parquet-source-capabilities.js.map +1 -1
  139. package/dist/parquet-source-loader-types.d.ts +10 -0
  140. package/dist/parquet-source-loader-types.d.ts.map +1 -1
  141. package/dist/parquet-source-loader-types.js +11 -1
  142. package/dist/parquet-source-loader-types.js.map +1 -1
  143. package/dist/parquet-source-loader.cjs +14121 -2796
  144. package/dist/parquet-source-loader.cjs.map +3 -3
  145. package/dist/parquet-source-loader.d.ts +51 -4
  146. package/dist/parquet-source-loader.d.ts.map +1 -1
  147. package/dist/parquet-source-loader.js +651 -38
  148. package/dist/parquet-source-loader.js.map +1 -1
  149. package/dist/parquet-source-types.d.ts +180 -30
  150. package/dist/parquet-source-types.d.ts.map +1 -1
  151. package/dist/parquet-source-worker.js +7378 -6989
  152. package/dist/parquet-source-worker.js.map +4 -4
  153. package/dist/parquet-worker-node.cjs +8501 -1045
  154. package/dist/parquet-worker-node.cjs.map +4 -4
  155. package/dist/parquet-worker-url.js +5 -1
  156. package/dist/parquet-worker-url.js.map +1 -1
  157. package/dist/parquet-worker.js +289 -218
  158. package/dist/parquet-worker.js.map +4 -4
  159. package/dist/parquetjs/codecs/declare.d.ts +15 -0
  160. package/dist/parquetjs/codecs/declare.d.ts.map +1 -1
  161. package/dist/parquetjs/codecs/declare.js +10 -0
  162. package/dist/parquetjs/codecs/declare.js.map +1 -1
  163. package/dist/parquetjs/codecs/delta.d.ts.map +1 -1
  164. package/dist/parquetjs/codecs/delta.js +356 -7
  165. package/dist/parquetjs/codecs/delta.js.map +1 -1
  166. package/dist/parquetjs/codecs/index.d.ts.map +1 -1
  167. package/dist/parquetjs/codecs/index.js +4 -0
  168. package/dist/parquetjs/codecs/index.js.map +1 -1
  169. package/dist/parquetjs/codecs/plain.d.ts +1 -1
  170. package/dist/parquetjs/codecs/plain.d.ts.map +1 -1
  171. package/dist/parquetjs/codecs/plain.js +153 -12
  172. package/dist/parquetjs/codecs/plain.js.map +1 -1
  173. package/dist/parquetjs/codecs/rle.d.ts +4 -0
  174. package/dist/parquetjs/codecs/rle.d.ts.map +1 -1
  175. package/dist/parquetjs/codecs/rle.js +406 -3
  176. package/dist/parquetjs/codecs/rle.js.map +1 -1
  177. package/dist/parquetjs/compression.d.ts +9 -0
  178. package/dist/parquetjs/compression.d.ts.map +1 -1
  179. package/dist/parquetjs/compression.js +86 -67
  180. package/dist/parquetjs/compression.js.map +1 -1
  181. package/dist/parquetjs/encoder/dictionary-planner.d.ts.map +1 -1
  182. package/dist/parquetjs/encoder/dictionary-planner.js +5 -2
  183. package/dist/parquetjs/encoder/dictionary-planner.js.map +1 -1
  184. package/dist/parquetjs/encoder/parquet-encoder.d.ts +43 -1
  185. package/dist/parquetjs/encoder/parquet-encoder.d.ts.map +1 -1
  186. package/dist/parquetjs/encoder/parquet-encoder.js +691 -34
  187. package/dist/parquetjs/encoder/parquet-encoder.js.map +1 -1
  188. package/dist/parquetjs/parquet-thrift/BoundingBox.d.ts +29 -0
  189. package/dist/parquetjs/parquet-thrift/BoundingBox.d.ts.map +1 -0
  190. package/dist/parquetjs/parquet-thrift/BoundingBox.js +85 -0
  191. package/dist/parquetjs/parquet-thrift/BoundingBox.js.map +1 -0
  192. package/dist/parquetjs/parquet-thrift/ColumnChunk.d.ts +5 -0
  193. package/dist/parquetjs/parquet-thrift/ColumnChunk.d.ts.map +1 -1
  194. package/dist/parquetjs/parquet-thrift/ColumnChunk.js +35 -0
  195. package/dist/parquetjs/parquet-thrift/ColumnChunk.js.map +1 -1
  196. package/dist/parquetjs/parquet-thrift/ColumnCryptoMetaData.d.ts +35 -0
  197. package/dist/parquetjs/parquet-thrift/ColumnCryptoMetaData.d.ts.map +1 -0
  198. package/dist/parquetjs/parquet-thrift/ColumnCryptoMetaData.js +135 -0
  199. package/dist/parquetjs/parquet-thrift/ColumnCryptoMetaData.js.map +1 -0
  200. package/dist/parquetjs/parquet-thrift/ColumnMetaData.d.ts +10 -0
  201. package/dist/parquetjs/parquet-thrift/ColumnMetaData.d.ts.map +1 -1
  202. package/dist/parquetjs/parquet-thrift/ColumnMetaData.js +73 -0
  203. package/dist/parquetjs/parquet-thrift/ColumnMetaData.js.map +1 -1
  204. package/dist/parquetjs/parquet-thrift/EncryptionAlgorithm.d.ts +22 -0
  205. package/dist/parquetjs/parquet-thrift/EncryptionAlgorithm.d.ts.map +1 -0
  206. package/dist/parquetjs/parquet-thrift/EncryptionAlgorithm.js +111 -0
  207. package/dist/parquetjs/parquet-thrift/EncryptionAlgorithm.js.map +1 -0
  208. package/dist/parquetjs/parquet-thrift/FileCryptoMetaData.d.ts +16 -0
  209. package/dist/parquetjs/parquet-thrift/FileCryptoMetaData.d.ts.map +1 -0
  210. package/dist/parquetjs/parquet-thrift/FileCryptoMetaData.js +57 -0
  211. package/dist/parquetjs/parquet-thrift/FileCryptoMetaData.js.map +1 -0
  212. package/dist/parquetjs/parquet-thrift/FileMetaData.d.ts +5 -0
  213. package/dist/parquetjs/parquet-thrift/FileMetaData.d.ts.map +1 -1
  214. package/dist/parquetjs/parquet-thrift/FileMetaData.js +35 -0
  215. package/dist/parquetjs/parquet-thrift/FileMetaData.js.map +1 -1
  216. package/dist/parquetjs/parquet-thrift/GeospatialStatistics.d.ts +18 -0
  217. package/dist/parquetjs/parquet-thrift/GeospatialStatistics.d.ts.map +1 -0
  218. package/dist/parquetjs/parquet-thrift/GeospatialStatistics.js +62 -0
  219. package/dist/parquetjs/parquet-thrift/GeospatialStatistics.js.map +1 -0
  220. package/dist/parquetjs/parquet-thrift/SizeStatistics.d.ts +26 -0
  221. package/dist/parquetjs/parquet-thrift/SizeStatistics.d.ts.map +1 -0
  222. package/dist/parquetjs/parquet-thrift/SizeStatistics.js +85 -0
  223. package/dist/parquetjs/parquet-thrift/SizeStatistics.js.map +1 -0
  224. package/dist/parquetjs/parquet-thrift/index.d.ts +6 -0
  225. package/dist/parquetjs/parquet-thrift/index.d.ts.map +1 -1
  226. package/dist/parquetjs/parquet-thrift/index.js +6 -0
  227. package/dist/parquetjs/parquet-thrift/index.js.map +1 -1
  228. package/dist/parquetjs/parser/decoders.d.ts +10 -1
  229. package/dist/parquetjs/parser/decoders.d.ts.map +1 -1
  230. package/dist/parquetjs/parser/decoders.js +318 -14
  231. package/dist/parquetjs/parser/decoders.js.map +1 -1
  232. package/dist/parquetjs/parser/encoded-pages.d.ts +24 -0
  233. package/dist/parquetjs/parser/encoded-pages.d.ts.map +1 -0
  234. package/dist/parquetjs/parser/encoded-pages.js +206 -0
  235. package/dist/parquetjs/parser/encoded-pages.js.map +1 -0
  236. package/dist/parquetjs/parser/parquet-reader.d.ts +88 -12
  237. package/dist/parquetjs/parser/parquet-reader.d.ts.map +1 -1
  238. package/dist/parquetjs/parser/parquet-reader.js +713 -66
  239. package/dist/parquetjs/parser/parquet-reader.js.map +1 -1
  240. package/dist/parquetjs/schema/declare.d.ts +22 -3
  241. package/dist/parquetjs/schema/declare.d.ts.map +1 -1
  242. package/dist/parquetjs/schema/declare.js.map +1 -1
  243. package/dist/parquetjs/schema/schema.d.ts.map +1 -1
  244. package/dist/parquetjs/schema/schema.js +10 -0
  245. package/dist/parquetjs/schema/schema.js.map +1 -1
  246. package/dist/parquetjs/schema/shred.d.ts.map +1 -1
  247. package/dist/parquetjs/schema/shred.js +219 -11
  248. package/dist/parquetjs/schema/shred.js.map +1 -1
  249. package/dist/parquetjs/schema/types.js +19 -21
  250. package/dist/parquetjs/schema/types.js.map +1 -1
  251. package/dist/parquetjs/schema/variant.d.ts +3 -0
  252. package/dist/parquetjs/schema/variant.d.ts.map +1 -0
  253. package/dist/parquetjs/schema/variant.js +248 -0
  254. package/dist/parquetjs/schema/variant.js.map +1 -0
  255. package/dist/parquetjs/utils/crc32.d.ts +3 -0
  256. package/dist/parquetjs/utils/crc32.d.ts.map +1 -0
  257. package/dist/parquetjs/utils/crc32.js +15 -0
  258. package/dist/parquetjs/utils/crc32.js.map +1 -0
  259. package/dist/parquetjs/utils/read-utils.d.ts +11 -1
  260. package/dist/parquetjs/utils/read-utils.d.ts.map +1 -1
  261. package/dist/parquetjs/utils/read-utils.js +21 -1
  262. package/dist/parquetjs/utils/read-utils.js.map +1 -1
  263. package/dist/unbundled.d.ts +2 -1
  264. package/dist/unbundled.d.ts.map +1 -1
  265. package/dist/unbundled.js +1 -0
  266. package/dist/unbundled.js.map +1 -1
  267. package/package.json +36 -13
  268. package/src/bundled.ts +10 -0
  269. package/src/delta-format.ts +12 -0
  270. package/src/delta-source-loader-types.ts +40 -0
  271. package/src/delta-source.ts +305 -0
  272. package/src/delta-types.ts +40 -0
  273. package/src/iceberg-rest-catalog.ts +122 -0
  274. package/src/iceberg-table-source.ts +1037 -0
  275. package/src/iceberg-types.ts +165 -0
  276. package/src/index.ts +59 -1
  277. package/src/lib/arrow/convert-schema-from-parquet.ts +113 -19
  278. package/src/lib/arrow/create-nested-arrow-vector.ts +116 -0
  279. package/src/lib/encoders/encode-table-to-parquet-js.ts +268 -7
  280. package/src/lib/geo/geoparquet-covering.ts +201 -0
  281. package/src/lib/geo/geospatial-metadata.ts +42 -15
  282. package/src/lib/parquet-bloom-filter-planner.ts +86 -0
  283. package/src/lib/parquet-bloom-filter.ts +345 -0
  284. package/src/lib/parquet-encryption.ts +344 -0
  285. package/src/lib/parquet-page-index.ts +180 -34
  286. package/src/lib/parquet-predicate.ts +52 -16
  287. package/src/lib/parquet-source-worker-decoder.ts +116 -20
  288. package/src/lib/parquet-source-worker-types.ts +25 -0
  289. package/src/lib/parsers/get-parquet-schema.ts +3 -1
  290. package/src/lib/parsers/parse-parquet-to-arrow-js.ts +397 -17
  291. package/src/lib/parsers/parse-parquet-to-arrow.ts +4 -5
  292. package/src/lib/parsers/parse-parquet-to-columns.ts +3 -1
  293. package/src/lib/parsers/parse-parquet-to-json.ts +18 -2
  294. package/src/lib/slice-parquet-batch.ts +32 -0
  295. package/src/lib/sources/parquet-range-file.ts +35 -29
  296. package/src/lib/utils/normalize-parquet-options.ts +17 -1
  297. package/src/parquet-dataset-source.ts +397 -85
  298. package/src/parquet-encoded-page-types.ts +122 -0
  299. package/src/parquet-js-loader-types.ts +1 -0
  300. package/src/parquet-js-loader.ts +2 -1
  301. package/src/parquet-js-writer.ts +30 -0
  302. package/src/parquet-loader-options.ts +11 -0
  303. package/src/parquet-source-capabilities.ts +18 -1
  304. package/src/parquet-source-loader-types.ts +10 -0
  305. package/src/parquet-source-loader.ts +1024 -52
  306. package/src/parquet-source-types.ts +197 -28
  307. package/src/parquet-worker-url.ts +6 -1
  308. package/src/parquetjs/codecs/declare.ts +27 -0
  309. package/src/parquetjs/codecs/delta.ts +466 -6
  310. package/src/parquetjs/codecs/index.ts +4 -0
  311. package/src/parquetjs/codecs/plain.ts +177 -11
  312. package/src/parquetjs/codecs/rle.ts +573 -3
  313. package/src/parquetjs/compression.ts +102 -76
  314. package/src/parquetjs/encoder/dictionary-planner.ts +7 -2
  315. package/src/parquetjs/encoder/parquet-encoder.ts +1016 -38
  316. package/src/parquetjs/parquet-thrift/BoundingBox.ts +108 -0
  317. package/src/parquetjs/parquet-thrift/ColumnChunk.ts +35 -0
  318. package/src/parquetjs/parquet-thrift/ColumnCryptoMetaData.ts +139 -0
  319. package/src/parquetjs/parquet-thrift/ColumnMetaData.ts +73 -0
  320. package/src/parquetjs/parquet-thrift/EncryptionAlgorithm.ts +127 -0
  321. package/src/parquetjs/parquet-thrift/FileCryptoMetaData.ts +60 -0
  322. package/src/parquetjs/parquet-thrift/FileMetaData.ts +35 -0
  323. package/src/parquetjs/parquet-thrift/GeospatialStatistics.ts +68 -0
  324. package/src/parquetjs/parquet-thrift/SizeStatistics.ts +98 -0
  325. package/src/parquetjs/parquet-thrift/index.ts +6 -0
  326. package/src/parquetjs/parser/decoders.ts +451 -26
  327. package/src/parquetjs/parser/encoded-pages.ts +278 -0
  328. package/src/parquetjs/parser/parquet-reader.ts +1112 -87
  329. package/src/parquetjs/schema/declare.ts +22 -2
  330. package/src/parquetjs/schema/schema.ts +10 -0
  331. package/src/parquetjs/schema/shred.ts +238 -11
  332. package/src/parquetjs/schema/types.ts +16 -25
  333. package/src/parquetjs/schema/variant.ts +313 -0
  334. package/src/parquetjs/utils/crc32.ts +15 -0
  335. package/src/parquetjs/utils/read-utils.ts +26 -1
  336. package/src/unbundled.ts +14 -0
@@ -11,6 +11,7 @@ import type {ParquetValueBuffer} from '../codecs/declare';
11
11
  export type ParquetCodec =
12
12
  | 'PLAIN'
13
13
  | 'RLE'
14
+ | 'BIT_PACKED'
14
15
  | 'PLAIN_DICTIONARY'
15
16
  | 'RLE_DICTIONARY'
16
17
  | 'DELTA_BINARY_PACKED'
@@ -193,6 +194,8 @@ export interface ParquetReaderContext {
193
194
  column: ParquetField;
194
195
  numValues?: Int64;
195
196
  dictionary?: ParquetDictionary;
197
+ /** Reader-scoped codec selected once and reused for independently compressed pages. */
198
+ decompressPage?: (value: Uint8Array, size: number) => Promise<Uint8Array>;
196
199
  /** If true, binary values are not converted to strings */
197
200
  preserveBinary?: boolean;
198
201
  /** Retain byte arrays as views into decoded page buffers for direct materialization. */
@@ -201,14 +204,22 @@ export interface ParquetReaderContext {
201
204
  useTypedValueBuffers?: boolean;
202
205
  /** Decode repetition and definition levels into compact unsigned typed arrays. */
203
206
  useTypedLevelBuffers?: boolean;
207
+ /** Decode eligible PLAIN BYTE_ARRAY columns into Arrow-compatible contiguous buffers. */
208
+ useArrowByteArrayBuffers?: boolean;
209
+ /** Column metadata guarantees every data page supports direct Arrow byte-array decoding. */
210
+ hasOnlyArrowByteArrayDataPages?: boolean;
211
+ /** Verify a page-header CRC when one is present. */
212
+ verifyPageChecksums?: boolean;
213
+ /** Decode legacy INT96 physical values as epoch nanoseconds. */
214
+ int96AsTimestamp?: boolean;
204
215
  }
205
216
 
206
217
  /** Mutable storage for decoded Parquet repetition and definition levels. */
207
218
  export type ParquetLevelBuffer = number[] | Uint8Array | Uint16Array | Uint32Array;
208
219
 
209
220
  export interface ParquetPageData {
210
- dlevels: number[];
211
- rlevels: number[];
221
+ dlevels: ParquetLevelBuffer;
222
+ rlevels: ParquetLevelBuffer;
212
223
  /** Actual column chunks */
213
224
  values: ParquetValueBuffer;
214
225
  /** Number of values written directly into the column destination, if one was supplied. */
@@ -242,6 +253,15 @@ export interface ParquetColumnChunk {
242
253
  dlevels: ParquetLevelBuffer;
243
254
  rlevels: ParquetLevelBuffer;
244
255
  values: ParquetValueBuffer;
256
+ /** Number of omitted physical values represented by definition levels when known. */
257
+ nullCount?: number;
258
+ /** Compact Arrow-compatible physical BYTE_ARRAY data produced by the Arrow reader path. */
259
+ byteArrayData?: {
260
+ /** Contiguous non-null physical value bytes. */
261
+ data: Uint8Array;
262
+ /** Offsets into `data`, with one entry beyond the final physical value. */
263
+ valueOffsets: Int32Array;
264
+ };
245
265
  count: number;
246
266
  pageHeaders: PageHeader[];
247
267
  }
@@ -43,9 +43,19 @@ export class ParquetSchema {
43
43
  */
44
44
  findField(path: string | string[]): ParquetField {
45
45
  if (typeof path === 'string') {
46
+ // Flat schemas dominate analytical Parquet. Avoid split/array allocation for every Arrow
47
+ // field lookup while retaining the existing traversal for genuinely nested paths.
48
+ if (!path.includes(',')) {
49
+ return this.fields[path];
50
+ }
46
51
  // tslint:disable-next-line:no-parameter-reassignment
47
52
  path = path.split(',');
48
53
  } else {
54
+ // Column metadata already stores paths as arrays; the one-segment case needs no defensive
55
+ // clone or shift and is exercised once per selected flat column.
56
+ if (path.length === 1) {
57
+ return this.fields[path[0]];
58
+ }
49
59
  // tslint:disable-next-line:no-parameter-reassignment
50
60
  path = path.slice(0); // clone array
51
61
  }
@@ -8,6 +8,7 @@ import {ArrayType} from '@loaders.gl/schema';
8
8
  import {ParquetRowGroup, ParquetColumnChunk, ParquetField, ParquetRow} from './declare';
9
9
  import {ParquetSchema} from './schema';
10
10
  import * as Types from './types';
11
+ import {decodeVariant} from './variant';
11
12
 
12
13
  export {ParquetRowGroup};
13
14
 
@@ -100,10 +101,33 @@ function shredRecordFields(
100
101
  record[field.name] !== undefined &&
101
102
  record[field.name] !== null
102
103
  ) {
103
- if (record[field.name].constructor === Array) {
104
- values = record[field.name];
104
+ const fieldValue = record[field.name];
105
+ if (field.logicalType?.type === 'LIST') {
106
+ // Normalize the high-level Arrow/list value to Parquet's standard
107
+ // three-level LIST representation before descending into the wrapper.
108
+ const listValues = Array.isArray(fieldValue) ? fieldValue : [];
109
+ if (field.fields?.list) {
110
+ values.push({list: listValues.map(element => ({element}))});
111
+ } else {
112
+ // Accept the legacy two-level LIST layout where the repeated field
113
+ // itself owns the element leaf.
114
+ values = listValues;
115
+ }
116
+ } else if (field.logicalType?.type === 'MAP') {
117
+ // Normalize Map/object/entry-array values to the standard MAP_KEY_VALUE
118
+ // wrapper expected by the shredding algorithm.
119
+ const mapEntries = normalizeMapEntries(fieldValue);
120
+ if (field.fields?.key_value) {
121
+ values.push({key_value: mapEntries});
122
+ } else {
123
+ // Accept legacy map layouts whose key/value group is the repeated
124
+ // field itself.
125
+ values = mapEntries;
126
+ }
127
+ } else if (fieldValue.constructor === Array) {
128
+ values = fieldValue;
105
129
  } else {
106
- values.push(record[field.name]);
130
+ values.push(fieldValue);
107
131
  }
108
132
  }
109
133
  // check values
@@ -143,6 +167,28 @@ function shredRecordFields(
143
167
  }
144
168
  }
145
169
 
170
+ /** Converts supported JavaScript map representations to Parquet map entries. */
171
+ function normalizeMapEntries(value: unknown): Array<{key: unknown; value: unknown}> {
172
+ if (value instanceof Map) {
173
+ return Array.from(value, ([key, mapValue]) => ({key, value: mapValue}));
174
+ }
175
+ if (Array.isArray(value)) {
176
+ return value.flatMap(entry => {
177
+ if (Array.isArray(entry) && entry.length >= 2) {
178
+ return [{key: entry[0], value: entry[1]}];
179
+ }
180
+ if (entry && typeof entry === 'object') {
181
+ return [{key: Reflect.get(entry, 'key'), value: Reflect.get(entry, 'value')}];
182
+ }
183
+ return [];
184
+ });
185
+ }
186
+ if (value && typeof value === 'object') {
187
+ return Object.entries(value).map(([key, mapValue]) => ({key, value: mapValue}));
188
+ }
189
+ return [];
190
+ }
191
+
146
192
  /**
147
193
  * 'Materialize' a list of <value, repetition_level, definition_level>
148
194
  * tuples back to nested records (objects/arrays) using the Google Dremel
@@ -173,9 +219,111 @@ export function materializeRows(schema: ParquetSchema, rowGroup: ParquetRowGroup
173
219
  materializeColumnAsRows(schema, columnData, key, rows);
174
220
  }
175
221
  }
222
+ decodeVariantFields(schema.fields, rows);
176
223
  return rows;
177
224
  }
178
225
 
226
+ /** Decodes complete unshredded VARIANT groups after their binary child columns are materialized. */
227
+ function decodeVariantFields(fields: Record<string, ParquetField>, records: unknown[]): void {
228
+ for (const field of Object.values(fields)) {
229
+ if (field.logicalType?.type === 'VARIANT') {
230
+ for (const record of records) {
231
+ if (record && typeof record === 'object') {
232
+ const row = record as Record<string, unknown>;
233
+ if (Object.prototype.hasOwnProperty.call(row, field.name)) {
234
+ row[field.name] = decodeVariantRecord(row[field.name], field);
235
+ }
236
+ }
237
+ }
238
+ } else if (field.fields) {
239
+ for (const record of records) {
240
+ if (record && typeof record === 'object') {
241
+ decodeVariantFields(field.fields, getNestedRecords(record, field.name));
242
+ }
243
+ }
244
+ }
245
+ }
246
+ }
247
+
248
+ /** Recursively decodes one materialized Variant group, preserving shredded values as records. */
249
+ function decodeVariantRecord(value: unknown, field?: ParquetField): unknown {
250
+ if (Array.isArray(value)) {
251
+ return value.map(item => decodeVariantRecord(item, field));
252
+ }
253
+ if (!value || typeof value !== 'object') {
254
+ return value;
255
+ }
256
+ const record = value as Record<string, unknown>;
257
+ const metadata = record.metadata;
258
+ const variantValue = record.value;
259
+ if (isByteArray(metadata) && isByteArray(variantValue)) {
260
+ return decodeVariant(metadata, variantValue);
261
+ }
262
+ // Shredded Variant encodings may materialize the typed_value child directly while
263
+ // omitting the unshredded metadata/value pair. Preserve that typed representation as
264
+ // the logical value instead of leaking the physical wrapper into object rows.
265
+ if (Object.prototype.hasOwnProperty.call(record, 'typed_value')) {
266
+ return decodeShreddedVariantValue(record.typed_value, field?.fields?.typed_value);
267
+ }
268
+ return value;
269
+ }
270
+
271
+ /** Collapses a declared one-field typed-value union used by shredded Variant layouts. */
272
+ function decodeShreddedVariantValue(value: unknown, field?: ParquetField): unknown {
273
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
274
+ return value;
275
+ }
276
+ const record = value as Record<string, unknown>;
277
+ const keys = Object.keys(record).filter(key => record[key] !== undefined);
278
+ if (keys.length === 1 && isVariantTypedValueField(field?.fields?.[keys[0]])) {
279
+ return decodeShreddedVariantValue(record[keys[0]], field?.fields?.[keys[0]]);
280
+ }
281
+ return value;
282
+ }
283
+
284
+ /** Identifies the declared members of the Parquet Variant typed-value union. */
285
+ function isVariantTypedValueField(field: ParquetField | undefined): boolean {
286
+ return Boolean(field && VARIANT_TYPED_VALUE_FIELD_NAMES.has(field.name));
287
+ }
288
+
289
+ const VARIANT_TYPED_VALUE_FIELD_NAMES = new Set([
290
+ 'null_value',
291
+ 'boolean_value',
292
+ 'int8_value',
293
+ 'int16_value',
294
+ 'int32_value',
295
+ 'int64_value',
296
+ 'uint8_value',
297
+ 'uint16_value',
298
+ 'uint32_value',
299
+ 'uint64_value',
300
+ 'float16_value',
301
+ 'float32_value',
302
+ 'float64_value',
303
+ 'decimal4_value',
304
+ 'decimal8_value',
305
+ 'decimal16_value',
306
+ 'string_value',
307
+ 'blob_value',
308
+ 'date_value',
309
+ 'timestamp_millis_value',
310
+ 'timestamp_micros_value',
311
+ 'timestamp_nanos_value',
312
+ 'object_value',
313
+ 'array_value'
314
+ ]);
315
+
316
+ /** Finds nested records while preserving repeated group values. */
317
+ function getNestedRecords(record: object, fieldName: string): unknown[] {
318
+ const value = Reflect.get(record, fieldName);
319
+ return Array.isArray(value) ? value : value && typeof value === 'object' ? [value] : [];
320
+ }
321
+
322
+ /** Identifies binary values emitted by Parquet primitive materialization. */
323
+ function isByteArray(value: unknown): value is ArrayBuffer | ArrayBufferView {
324
+ return value instanceof ArrayBuffer || ArrayBuffer.isView(value);
325
+ }
326
+
179
327
  /** Populate record fields for one column */
180
328
  // eslint-disable-next-line max-statements, complexity
181
329
  function materializeColumnAsRows(
@@ -199,13 +347,20 @@ function materializeColumnAsRows(
199
347
  const rLevels: number[] = new Array(field.rLevelMax + 1).fill(0);
200
348
  let vIndex = 0;
201
349
  for (let i = 0; i < columnData.count; i++) {
202
- const dLevel = columnData.dlevels[i];
203
- const rLevel = columnData.rlevels[i];
350
+ // Zero maximum levels are implicit and may use allocation-free empty buffers. Preserve both
351
+ // fallbacks: required nested scalars still need dLevel === 0 to materialize their leaf value.
352
+ const dLevel = columnData.dlevels[i] ?? 0;
353
+ const rLevel = columnData.rlevels[i] ?? 0;
204
354
  rLevels[rLevel]++;
205
355
  rLevels.fill(0, rLevel + 1);
206
356
 
207
357
  let rIndex = 0;
208
358
  let record = rows[rLevels[rIndex++] - 1];
359
+ if (!record) {
360
+ throw new Error(
361
+ `Parquet column ${key} referenced row ${rLevels[0] - 1} of ${rows.length} at value ${i} (rLevel ${rLevel}, dLevel ${dLevel})`
362
+ );
363
+ }
209
364
 
210
365
  // Internal nodes - Build a nested row object
211
366
  for (const step of branch) {
@@ -235,7 +390,7 @@ function materializeColumnAsRows(
235
390
 
236
391
  // Leaf node - Add the value
237
392
  if (dLevel === field.dLevelMax) {
238
- const primitiveValue = columnData.values[vIndex];
393
+ const primitiveValue = getDecodedColumnValue(columnData, vIndex);
239
394
  const value = fromPrimitive ? fromPrimitive(primitiveValue, field) : primitiveValue;
240
395
  vIndex++;
241
396
 
@@ -273,14 +428,24 @@ function materializeFlatColumnAsRows(
273
428
 
274
429
  if (field.repetitionType === 'REQUIRED' && !fromPrimitive) {
275
430
  for (let rowIndex = 0; rowIndex < count; rowIndex++) {
276
- rows[rowIndex][field.name] = columnData.values[rowIndex];
431
+ rows[rowIndex][field.name] = getDecodedColumnValue(columnData, rowIndex);
432
+ }
433
+ return;
434
+ }
435
+
436
+ if (field.repetitionType === 'REQUIRED') {
437
+ for (let rowIndex = 0; rowIndex < count; rowIndex++) {
438
+ rows[rowIndex][field.name] = fromPrimitive!(
439
+ getDecodedColumnValue(columnData, rowIndex),
440
+ field
441
+ );
277
442
  }
278
443
  return;
279
444
  }
280
445
 
281
446
  for (let rowIndex = 0; rowIndex < count; rowIndex++) {
282
447
  if (columnData.dlevels[rowIndex] === field.dLevelMax) {
283
- const primitiveValue = columnData.values[valueIndex];
448
+ const primitiveValue = getDecodedColumnValue(columnData, valueIndex);
284
449
  rows[rowIndex][field.name] = fromPrimitive
285
450
  ? fromPrimitive(primitiveValue, field)
286
451
  : primitiveValue;
@@ -318,12 +483,54 @@ export function materializeColumns(
318
483
  for (const key in rowGroup.columnData) {
319
484
  const column = materializeColumn(schema, rowGroup, key);
320
485
  if (column) {
321
- columns[schema.findFieldBranch(key)[0].name] = column;
486
+ const columnName = schema.findFieldBranch(key)[0].name;
487
+ columns[columnName] = columns[columnName]
488
+ ? mergeMaterializedColumn(columns[columnName], column)
489
+ : column;
322
490
  }
323
491
  }
324
492
  return columns;
325
493
  }
326
494
 
495
+ /** Merges independently decoded nested leaf columns into one top-level column. */
496
+ function mergeMaterializedColumn(existing: ArrayType, incoming: ArrayType): ArrayType {
497
+ const length = Math.max(existing.length, incoming.length);
498
+ const merged = new Array(length);
499
+ for (let index = 0; index < length; index++) {
500
+ merged[index] = mergeMaterializedValue(existing[index], incoming[index]);
501
+ }
502
+ return merged;
503
+ }
504
+
505
+ /** Recursively combines objects and corresponding repeated elements without losing scalar leaves. */
506
+ function mergeMaterializedValue(existing: unknown, incoming: unknown): unknown {
507
+ if (existing === null || existing === undefined) {
508
+ return incoming;
509
+ }
510
+ if (incoming === null || incoming === undefined) {
511
+ return existing;
512
+ }
513
+ if (Array.isArray(existing) && Array.isArray(incoming)) {
514
+ const length = Math.max(existing.length, incoming.length);
515
+ return Array.from({length}, (_, index) =>
516
+ mergeMaterializedValue(existing[index], incoming[index])
517
+ );
518
+ }
519
+ if (
520
+ typeof existing === 'object' &&
521
+ typeof incoming === 'object' &&
522
+ !ArrayBuffer.isView(existing) &&
523
+ !ArrayBuffer.isView(incoming)
524
+ ) {
525
+ const merged: Record<string, unknown> = {...(existing as Record<string, unknown>)};
526
+ for (const [key, value] of Object.entries(incoming as Record<string, unknown>)) {
527
+ merged[key] = mergeMaterializedValue(merged[key], value);
528
+ }
529
+ return merged;
530
+ }
531
+ return incoming;
532
+ }
533
+
327
534
  /** Materializes one decoded Parquet column into its top-level columnar representation. */
328
535
  export function materializeColumn(
329
536
  schema: ParquetSchema,
@@ -411,7 +618,7 @@ function materializeColumnAsColumnarArray(
411
618
  const value = Types.fromPrimitive(
412
619
  // @ts-ignore
413
620
  field.originalType || field.primitiveType,
414
- columnData.values[vIndex],
621
+ getDecodedColumnValue(columnData, vIndex),
415
622
  field
416
623
  );
417
624
  vIndex++;
@@ -463,14 +670,34 @@ function materializeFlatColumn(
463
670
  return columnData.values;
464
671
  }
465
672
 
673
+ if (field.repetitionType === 'REQUIRED') {
674
+ const column = new Array(rowCount).fill(null);
675
+ for (let rowIndex = 0; rowIndex < count; rowIndex++) {
676
+ column[rowIndex] = fromPrimitive
677
+ ? fromPrimitive(getDecodedColumnValue(columnData, rowIndex), field)
678
+ : getDecodedColumnValue(columnData, rowIndex);
679
+ }
680
+ return column;
681
+ }
682
+
466
683
  const column = new Array(rowCount).fill(null);
467
684
  let valueIndex = 0;
468
685
  for (let rowIndex = 0; rowIndex < count; rowIndex++) {
469
686
  if (columnData.dlevels[rowIndex] === field.dLevelMax) {
470
- const primitiveValue = columnData.values[valueIndex];
687
+ const primitiveValue = getDecodedColumnValue(columnData, valueIndex);
471
688
  column[rowIndex] = fromPrimitive ? fromPrimitive(primitiveValue, field) : primitiveValue;
472
689
  valueIndex++;
473
690
  }
474
691
  }
475
692
  return column;
476
693
  }
694
+
695
+ /** Returns one compact byte value or one value from the decoder's conventional destination. */
696
+ function getDecodedColumnValue(columnData: ParquetColumnChunk, valueIndex: number): unknown {
697
+ const byteArrayData = columnData.byteArrayData;
698
+ if (!byteArrayData) return columnData.values[valueIndex];
699
+ return byteArrayData.data.subarray(
700
+ byteArrayData.valueOffsets[valueIndex],
701
+ byteArrayData.valueOffsets[valueIndex + 1]
702
+ );
703
+ }
@@ -445,13 +445,19 @@ function toPrimitive_UINT64(value: unknown): bigint {
445
445
  return BigInt.asIntN(64, primitiveValue);
446
446
  }
447
447
 
448
- function toPrimitive_INT96(value: any) {
449
- const v = parseInt(value, 10);
450
- if (Number.isNaN(v)) {
448
+ function toPrimitive_INT96(value: unknown): number | bigint {
449
+ if (typeof value === 'bigint') return value;
450
+ if (typeof value === 'number') {
451
+ if (Number.isSafeInteger(value)) return value;
451
452
  throw new Error(`invalid value for INT96: ${value}`);
452
453
  }
453
-
454
- return v;
454
+ if (typeof value !== 'string' || !/^[+-]?\d+$/.test(value)) {
455
+ throw new Error(`invalid value for INT96: ${value}`);
456
+ }
457
+ const bigintValue = BigInt(value);
458
+ return bigintValue >= Number.MIN_SAFE_INTEGER && bigintValue <= Number.MAX_SAFE_INTEGER
459
+ ? Number(bigintValue)
460
+ : bigintValue;
455
461
  }
456
462
 
457
463
  function toPrimitive_BYTE_ARRAY(value: any): Uint8Array {
@@ -700,24 +706,9 @@ function decimalFromPrimitive_INT(value: any, field: ParquetField) {
700
706
  }
701
707
 
702
708
  function decimalFromPrimitive_BYTE_ARRAY(value: any, field: ParquetField) {
703
- let number = 0;
704
- if (value.length <= 4) {
705
- // Bytewise operators faster. Use them if it is possible
706
- for (let i = 0; i < value.length; i++) {
707
- // `value.length - i - 1` bytes have reverse order (big-endian)
708
- const component = value[i] << (8 * (value.length - i - 1));
709
- number += component;
710
- }
711
- } else {
712
- for (let i = 0; i < value.length; i++) {
713
- // `value.length - i - 1` bytes have reverse order (big-endian)
714
- const component = value[i] * 2 ** (8 * (value.length - 1 - i));
715
- number += component;
716
- }
717
- }
718
-
719
- const presisionInt = Math.round(
720
- ((number * 10 ** -field.presision!) % 1) * 10 ** field.presision!
721
- );
722
- return presisionInt * 10 ** -(field.scale || 0);
709
+ const bytes = toUint8Array(value);
710
+ let unscaledValue = 0n;
711
+ for (const byte of bytes) unscaledValue = (unscaledValue << 8n) | BigInt(byte);
712
+ if (bytes.length > 0 && (bytes[0] & 0x80) !== 0) unscaledValue -= 1n << BigInt(bytes.length * 8);
713
+ return Number(unscaledValue) / 10 ** (field.scale || 0);
723
714
  }