@gscdump/lakehouse 7.7.0 → 7.8.1
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/README.md +37 -2
- package/dist/_virtual/node_modules/.pnpm/hyparquet-compressors@1.1.2_patch_hash=3f8f44805c034b2563763dcd5d37050ea6b1d5d45b46ea37adc4a721e748a1c5/node_modules/hyparquet-compressors/src/gzip.mjs +196 -0
- package/dist/_virtual/node_modules/.pnpm/hyparquet@1.31.1/node_modules/hyparquet/src/column.mjs +1 -1
- package/dist/_virtual/node_modules/.pnpm/hyparquet@1.31.1/node_modules/hyparquet/src/datapage.mjs +1 -1
- package/dist/_virtual/node_modules/.pnpm/hyparquet@1.31.1/node_modules/hyparquet/src/index.mjs +1 -1
- package/dist/_virtual/node_modules/.pnpm/hyparquet@1.31.1/node_modules/hyparquet/src/indexes.mjs +1 -1
- package/dist/_virtual/node_modules/.pnpm/hyparquet@1.31.1/node_modules/hyparquet/src/metadata.mjs +1 -1
- package/dist/_virtual/node_modules/.pnpm/hyparquet@1.31.1/node_modules/hyparquet/src/node.mjs +1 -1
- package/dist/_virtual/node_modules/.pnpm/icebird@0.8.30_patch_hash=1359a91da68522a736babe444880ae391f19455fbe47c346f76cec92c5c2e471/node_modules/icebird/src/avro/avro.read.mjs +3 -3
- package/dist/_virtual/node_modules/.pnpm/icebird@0.8.30_patch_hash=1359a91da68522a736babe444880ae391f19455fbe47c346f76cec92c5c2e471/node_modules/icebird/src/fetch.mjs +5 -39
- package/dist/_virtual/node_modules/.pnpm/icebird@0.8.30_patch_hash=1359a91da68522a736babe444880ae391f19455fbe47c346f76cec92c5c2e471/node_modules/icebird/src/read.mjs +2 -2
- package/dist/_virtual/node_modules/.pnpm/icebird@0.8.30_patch_hash=1359a91da68522a736babe444880ae391f19455fbe47c346f76cec92c5c2e471/node_modules/icebird/types/index.d.mts +1 -1
- package/dist/catalog.d.mts +11 -3
- package/dist/catalog.mjs +24 -9
- package/dist/dataset.d.mts +4 -0
- package/dist/dataset.mjs +4 -1
- package/dist/icebird-resolver.d.mts +10 -0
- package/dist/index.d.mts +3 -1
- package/dist/manifest-read-limits.d.mts +2 -0
- package/dist/manifest-read-limits.mjs +26 -0
- package/dist/resolver-byte-cache.mjs +85 -0
- package/package.json +1 -1
- package/dist/_virtual/node_modules/.pnpm/hyparquet-compressors@1.1.2_patch_hash=821c89dbb6181f0c34d9abebd844451458a4f16c04e7aa7a19abca0c09c2238d/node_modules/hyparquet-compressors/src/gzip.mjs +0 -186
- /package/dist/_virtual/node_modules/.pnpm/{hyparquet-compressors@1.1.2_patch_hash=821c89dbb6181f0c34d9abebd844451458a4f16c04e7aa7a19abca0c09c2238d → hyparquet-compressors@1.1.2_patch_hash=3f8f44805c034b2563763dcd5d37050ea6b1d5d45b46ea37adc4a721e748a1c5}/node_modules/hyparquet-compressors/src/brotli.bitreader.mjs +0 -0
- /package/dist/_virtual/node_modules/.pnpm/{hyparquet-compressors@1.1.2_patch_hash=821c89dbb6181f0c34d9abebd844451458a4f16c04e7aa7a19abca0c09c2238d → hyparquet-compressors@1.1.2_patch_hash=3f8f44805c034b2563763dcd5d37050ea6b1d5d45b46ea37adc4a721e748a1c5}/node_modules/hyparquet-compressors/src/brotli.blocks.mjs +0 -0
- /package/dist/_virtual/node_modules/.pnpm/{hyparquet-compressors@1.1.2_patch_hash=821c89dbb6181f0c34d9abebd844451458a4f16c04e7aa7a19abca0c09c2238d → hyparquet-compressors@1.1.2_patch_hash=3f8f44805c034b2563763dcd5d37050ea6b1d5d45b46ea37adc4a721e748a1c5}/node_modules/hyparquet-compressors/src/brotli.context.mjs +0 -0
- /package/dist/_virtual/node_modules/.pnpm/{hyparquet-compressors@1.1.2_patch_hash=821c89dbb6181f0c34d9abebd844451458a4f16c04e7aa7a19abca0c09c2238d → hyparquet-compressors@1.1.2_patch_hash=3f8f44805c034b2563763dcd5d37050ea6b1d5d45b46ea37adc4a721e748a1c5}/node_modules/hyparquet-compressors/src/brotli.contextmap.mjs +0 -0
- /package/dist/_virtual/node_modules/.pnpm/{hyparquet-compressors@1.1.2_patch_hash=821c89dbb6181f0c34d9abebd844451458a4f16c04e7aa7a19abca0c09c2238d → hyparquet-compressors@1.1.2_patch_hash=3f8f44805c034b2563763dcd5d37050ea6b1d5d45b46ea37adc4a721e748a1c5}/node_modules/hyparquet-compressors/src/brotli.dictionary.mjs +0 -0
- /package/dist/_virtual/node_modules/.pnpm/{hyparquet-compressors@1.1.2_patch_hash=821c89dbb6181f0c34d9abebd844451458a4f16c04e7aa7a19abca0c09c2238d → hyparquet-compressors@1.1.2_patch_hash=3f8f44805c034b2563763dcd5d37050ea6b1d5d45b46ea37adc4a721e748a1c5}/node_modules/hyparquet-compressors/src/brotli.huffman.mjs +0 -0
- /package/dist/_virtual/node_modules/.pnpm/{hyparquet-compressors@1.1.2_patch_hash=821c89dbb6181f0c34d9abebd844451458a4f16c04e7aa7a19abca0c09c2238d → hyparquet-compressors@1.1.2_patch_hash=3f8f44805c034b2563763dcd5d37050ea6b1d5d45b46ea37adc4a721e748a1c5}/node_modules/hyparquet-compressors/src/brotli.mjs +0 -0
- /package/dist/_virtual/node_modules/.pnpm/{hyparquet-compressors@1.1.2_patch_hash=821c89dbb6181f0c34d9abebd844451458a4f16c04e7aa7a19abca0c09c2238d → hyparquet-compressors@1.1.2_patch_hash=3f8f44805c034b2563763dcd5d37050ea6b1d5d45b46ea37adc4a721e748a1c5}/node_modules/hyparquet-compressors/src/brotli.prefix.mjs +0 -0
- /package/dist/_virtual/node_modules/.pnpm/{hyparquet-compressors@1.1.2_patch_hash=821c89dbb6181f0c34d9abebd844451458a4f16c04e7aa7a19abca0c09c2238d → hyparquet-compressors@1.1.2_patch_hash=3f8f44805c034b2563763dcd5d37050ea6b1d5d45b46ea37adc4a721e748a1c5}/node_modules/hyparquet-compressors/src/brotli.streams.mjs +0 -0
- /package/dist/_virtual/node_modules/.pnpm/{hyparquet-compressors@1.1.2_patch_hash=821c89dbb6181f0c34d9abebd844451458a4f16c04e7aa7a19abca0c09c2238d → hyparquet-compressors@1.1.2_patch_hash=3f8f44805c034b2563763dcd5d37050ea6b1d5d45b46ea37adc4a721e748a1c5}/node_modules/hyparquet-compressors/src/brotli.transform.mjs +0 -0
- /package/dist/_virtual/node_modules/.pnpm/{hyparquet-compressors@1.1.2_patch_hash=821c89dbb6181f0c34d9abebd844451458a4f16c04e7aa7a19abca0c09c2238d → hyparquet-compressors@1.1.2_patch_hash=3f8f44805c034b2563763dcd5d37050ea6b1d5d45b46ea37adc4a721e748a1c5}/node_modules/hyparquet-compressors/src/compressors.mjs +0 -0
- /package/dist/_virtual/node_modules/.pnpm/{hyparquet-compressors@1.1.2_patch_hash=821c89dbb6181f0c34d9abebd844451458a4f16c04e7aa7a19abca0c09c2238d → hyparquet-compressors@1.1.2_patch_hash=3f8f44805c034b2563763dcd5d37050ea6b1d5d45b46ea37adc4a721e748a1c5}/node_modules/hyparquet-compressors/src/gzip.huffman.mjs +0 -0
- /package/dist/_virtual/node_modules/.pnpm/{hyparquet-compressors@1.1.2_patch_hash=821c89dbb6181f0c34d9abebd844451458a4f16c04e7aa7a19abca0c09c2238d → hyparquet-compressors@1.1.2_patch_hash=3f8f44805c034b2563763dcd5d37050ea6b1d5d45b46ea37adc4a721e748a1c5}/node_modules/hyparquet-compressors/src/index.mjs +0 -0
- /package/dist/_virtual/node_modules/.pnpm/{hyparquet-compressors@1.1.2_patch_hash=821c89dbb6181f0c34d9abebd844451458a4f16c04e7aa7a19abca0c09c2238d → hyparquet-compressors@1.1.2_patch_hash=3f8f44805c034b2563763dcd5d37050ea6b1d5d45b46ea37adc4a721e748a1c5}/node_modules/hyparquet-compressors/src/lz4.mjs +0 -0
package/README.md
CHANGED
|
@@ -49,8 +49,8 @@ Raw Icebird table creation and append functions live under `unsafe-raw` for pack
|
|
|
49
49
|
|
|
50
50
|
`icebergManifests` on `@gscdump/lakehouse/unsafe-raw` accepts an optional
|
|
51
51
|
`readLimits: ManifestReadLimits`. Omission preserves the existing reader and
|
|
52
|
-
caller-owned manifest cache behavior. No
|
|
53
|
-
|
|
52
|
+
caller-owned manifest cache behavior. No file resolver or host automatically
|
|
53
|
+
enables these limits.
|
|
54
54
|
|
|
55
55
|
```ts
|
|
56
56
|
import { icebergManifests } from '@gscdump/lakehouse/unsafe-raw'
|
|
@@ -113,6 +113,41 @@ physically cancelled by the AsyncBuffer interface, but a first failure stops new
|
|
|
113
113
|
dispatches and prevents late responses from being decoded. Choose compatible
|
|
114
114
|
limits and validate the complete consumer path before enabling them.
|
|
115
115
|
|
|
116
|
+
The same optional `readLimits` can be passed to `resolveIcebergDataFiles`,
|
|
117
|
+
`dataset.resolveDataFiles(..., { readLimits })`, and the engine's
|
|
118
|
+
`listIcebergDataFiles`. These wrappers capture and validate all ten values before
|
|
119
|
+
catalog reads or lazy imports, then perform one bounded manifest walk. Per-object
|
|
120
|
+
and aggregate limits remain independent upper bounds; a smaller aggregate limit
|
|
121
|
+
does not expand the per-object allowance. Invalid, missing or unknown values are
|
|
122
|
+
rejected even when the table has no current snapshot.
|
|
123
|
+
|
|
124
|
+
In this opt-in mode, decoded manifest, resolved-file and month caches are neither
|
|
125
|
+
read nor populated: old cache entries cannot establish compliance with a new
|
|
126
|
+
policy. The existing catalog configuration, snapshot pointer and table metadata
|
|
127
|
+
caches remain in use, with their existing identity/freshness rules. Catalog JSON
|
|
128
|
+
and those metadata caches are outside the Avro allocation bound. Existing
|
|
129
|
+
partition, Site, search-type, date pruning and output ordering are unchanged.
|
|
130
|
+
|
|
131
|
+
This has an explicit warm-read cost. A default exact-range cache hit can avoid
|
|
132
|
+
all Avro reads; a default month hit can need only the manifest list. A bounded
|
|
133
|
+
call reads the list and every selected manifest again (subject to any injected
|
|
134
|
+
resolver's own byte cache).
|
|
135
|
+
|
|
136
|
+
A connection from `connectIcebergCatalog` keeps the objects it reads in a
|
|
137
|
+
per-connection byte cache. That cache holds at most 16 MiB of fetched bytes.
|
|
138
|
+
If a read takes it over 16 MiB, it evicts the least recently read object
|
|
139
|
+
first. It does not keep an object larger than 16 MiB, and it does not keep a
|
|
140
|
+
failed read. Concurrent reads of one path share one S3 request. A successful
|
|
141
|
+
write or delete of a path evicts that path. A bounded call reads through the uncached
|
|
142
|
+
S3 resolver instead, so the connection keeps none of its manifest bytes after
|
|
143
|
+
the call. It also does not reuse bytes that earlier unbounded calls cached. If
|
|
144
|
+
you replace `connection.resolver`, the bounded call uses your resolver, and your
|
|
145
|
+
resolver owns its retention. Each concurrent bounded call owns its own limits;
|
|
146
|
+
the option does not impose a connection-wide or process-wide budget. There is
|
|
147
|
+
no automatic fallback to cached or unbounded results after refusal. Validate
|
|
148
|
+
retained files and request costs before enabling a policy in a host; this does
|
|
149
|
+
not bound a remote SQL provider's internal manifest planner.
|
|
150
|
+
|
|
116
151
|
## Append retries
|
|
117
152
|
|
|
118
153
|
Supply a durable `commitRetry.appendId` when a dataset append belongs to a job or receipt.
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import { fixedDistance, fixedDistanceExtraBits, fixedDistanceMap, fixedLength, fixedLengthExtraBits, fixedLengthMap, huffMap } from "./gzip.huffman.mjs";
|
|
2
|
+
const codeLengthIndexMap = new Uint8Array([
|
|
3
|
+
16,
|
|
4
|
+
17,
|
|
5
|
+
18,
|
|
6
|
+
0,
|
|
7
|
+
8,
|
|
8
|
+
7,
|
|
9
|
+
9,
|
|
10
|
+
6,
|
|
11
|
+
10,
|
|
12
|
+
5,
|
|
13
|
+
11,
|
|
14
|
+
4,
|
|
15
|
+
12,
|
|
16
|
+
3,
|
|
17
|
+
13,
|
|
18
|
+
2,
|
|
19
|
+
14,
|
|
20
|
+
1,
|
|
21
|
+
15
|
|
22
|
+
]);
|
|
23
|
+
function bits(input, pos, mask) {
|
|
24
|
+
const o = pos / 8 | 0;
|
|
25
|
+
return (input[o] | input[o + 1] << 8) >> (pos & 7) & mask;
|
|
26
|
+
}
|
|
27
|
+
function bits16(d, p) {
|
|
28
|
+
const o = p / 8 | 0;
|
|
29
|
+
return (d[o] | d[o + 1] << 8 | d[o + 2] << 16) >> (p & 7);
|
|
30
|
+
}
|
|
31
|
+
function shft(p) {
|
|
32
|
+
return (p + 7) / 8 | 0;
|
|
33
|
+
}
|
|
34
|
+
function gzipStart(input, i) {
|
|
35
|
+
if (input[i++] !== 31 || input[i++] !== 139 || input[i++] !== 8) return 0;
|
|
36
|
+
const flag = input[i++];
|
|
37
|
+
if (flag & 224) throw new Error("invalid gzip header flags");
|
|
38
|
+
i += 6;
|
|
39
|
+
if (flag & 4) i += (input[i] | input[i + 1] << 8) + 2;
|
|
40
|
+
for (let zs = (flag >> 3 & 1) + (flag >> 4 & 1); zs > 0; zs -= Number(!input[i++]));
|
|
41
|
+
return i + (flag & 2);
|
|
42
|
+
}
|
|
43
|
+
function gunzip(input, output, inputIndex = 0, outputIndex = 0, limits) {
|
|
44
|
+
const maximum = limits?.maxOutputBytes;
|
|
45
|
+
if (limits && (limits.raw !== true || !Number.isSafeInteger(maximum) || maximum < 0 || output || inputIndex !== 0 || outputIndex !== 0)) throw new RangeError("Invalid bounded raw DEFLATE options");
|
|
46
|
+
let out = output ?? new Uint8Array(limits ? Math.min(1024, maximum) : 1024);
|
|
47
|
+
if (limits && !input.length) throw new Error("unexpected EOF");
|
|
48
|
+
if (!(input.length - inputIndex)) return out;
|
|
49
|
+
const totalBits = input.length * 8;
|
|
50
|
+
function ensureSize(length) {
|
|
51
|
+
if (limits && (!Number.isSafeInteger(length) || length > maximum)) throw new RangeError("DEFLATE output byte limit exceeded");
|
|
52
|
+
if (!output && length > out.length) {
|
|
53
|
+
const old = out;
|
|
54
|
+
out = new Uint8Array(limits ? Math.min(maximum, Math.max(old.length * 2, length)) : Math.max(old.length * 2, length));
|
|
55
|
+
out.set(old);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
let memberStart = inputIndex;
|
|
59
|
+
for (;;) {
|
|
60
|
+
const payloadStart = limits ? 0 : gzipStart(input, memberStart);
|
|
61
|
+
const isGzip = !limits && payloadStart > 0;
|
|
62
|
+
if (isGzip && payloadStart === input.length - 8) break;
|
|
63
|
+
if (isGzip && payloadStart > input.length - 8) throw new Error("unexpected EOF");
|
|
64
|
+
const pos = inflate(payloadStart * 8);
|
|
65
|
+
if (limits && Math.ceil(pos / 8) !== input.length) throw new Error("trailing raw DEFLATE bytes");
|
|
66
|
+
if (!isGzip || output && outputIndex >= out.length) break;
|
|
67
|
+
const nextBlock = Math.ceil(pos / 8) + 8;
|
|
68
|
+
if (nextBlock > input.length) throw new Error("unexpected EOF");
|
|
69
|
+
if (nextBlock === input.length) break;
|
|
70
|
+
if (input[nextBlock] !== 31 || input[nextBlock + 1] !== 139 || input[nextBlock + 2] !== 8) throw new Error("invalid gzip member");
|
|
71
|
+
memberStart = nextBlock;
|
|
72
|
+
}
|
|
73
|
+
function inflate(pos) {
|
|
74
|
+
let final = 0;
|
|
75
|
+
let lengthBits = 0;
|
|
76
|
+
let distBits = 0;
|
|
77
|
+
let lengthMap;
|
|
78
|
+
let distMap;
|
|
79
|
+
do {
|
|
80
|
+
if (!lengthMap) {
|
|
81
|
+
final = bits(input, pos, 1);
|
|
82
|
+
const type = bits(input, pos + 1, 3);
|
|
83
|
+
pos += 3;
|
|
84
|
+
if (!type) {
|
|
85
|
+
const s = shft(pos) + 4;
|
|
86
|
+
const l = input[s - 4] | input[s - 3] << 8;
|
|
87
|
+
if (limits && (s > input.length || ((input[s - 2] | input[s - 1] << 8) ^ l) !== 65535)) throw new Error("invalid stored block length");
|
|
88
|
+
const t = s + l;
|
|
89
|
+
if (t > input.length) throw new Error("unexpected EOF");
|
|
90
|
+
ensureSize(outputIndex + l);
|
|
91
|
+
out.set(input.subarray(s, t), outputIndex);
|
|
92
|
+
outputIndex += l;
|
|
93
|
+
pos = t * 8;
|
|
94
|
+
continue;
|
|
95
|
+
} else if (type === 1) {
|
|
96
|
+
lengthMap = fixedLengthMap;
|
|
97
|
+
distMap = fixedDistanceMap;
|
|
98
|
+
lengthBits = 9;
|
|
99
|
+
distBits = 5;
|
|
100
|
+
} else if (type === 2) {
|
|
101
|
+
const hLiteral = bits(input, pos, 31) + 257;
|
|
102
|
+
const hcLengths = bits(input, pos + 10, 15) + 4;
|
|
103
|
+
const tl = hLiteral + bits(input, pos + 5, 31) + 1;
|
|
104
|
+
pos += 14;
|
|
105
|
+
const lengthDistanceTree = new Uint8Array(tl);
|
|
106
|
+
const codeLengthTree = /* @__PURE__ */ new Uint8Array(19);
|
|
107
|
+
for (let i = 0; i < hcLengths; ++i) codeLengthTree[codeLengthIndexMap[i]] = bits(input, pos + i * 3, 7);
|
|
108
|
+
pos += hcLengths * 3;
|
|
109
|
+
const codeLengthBits = Math.max(...codeLengthTree);
|
|
110
|
+
const clbMask = (1 << codeLengthBits) - 1;
|
|
111
|
+
const codeLengthMap = huffMap(codeLengthTree, codeLengthBits, 1);
|
|
112
|
+
for (let i = 0; i < tl;) {
|
|
113
|
+
const r = codeLengthMap[bits(input, pos, clbMask)];
|
|
114
|
+
if (limits && !r) throw new Error("invalid code length");
|
|
115
|
+
pos += r & 15;
|
|
116
|
+
const symbol = r >> 4;
|
|
117
|
+
if (symbol < 16) lengthDistanceTree[i++] = symbol;
|
|
118
|
+
else {
|
|
119
|
+
let copy = 0;
|
|
120
|
+
let n = 0;
|
|
121
|
+
if (symbol === 16) {
|
|
122
|
+
if (limits && i === 0) throw new Error("invalid code length repeat");
|
|
123
|
+
n = 3 + bits(input, pos, 3);
|
|
124
|
+
pos += 2;
|
|
125
|
+
copy = lengthDistanceTree[i - 1];
|
|
126
|
+
} else if (symbol === 17) {
|
|
127
|
+
n = 3 + bits(input, pos, 7);
|
|
128
|
+
pos += 3;
|
|
129
|
+
} else if (symbol === 18) {
|
|
130
|
+
n = 11 + bits(input, pos, 127);
|
|
131
|
+
pos += 7;
|
|
132
|
+
}
|
|
133
|
+
if (limits && i + n > tl) throw new Error("invalid code length repeat");
|
|
134
|
+
while (n--) lengthDistanceTree[i++] = copy;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
const lengthTree = lengthDistanceTree.subarray(0, hLiteral);
|
|
138
|
+
const distanceTree = lengthDistanceTree.subarray(hLiteral);
|
|
139
|
+
lengthBits = Math.max(...lengthTree);
|
|
140
|
+
distBits = Math.max(...distanceTree);
|
|
141
|
+
lengthMap = huffMap(lengthTree, lengthBits, 1);
|
|
142
|
+
distMap = huffMap(distanceTree, distBits, 1);
|
|
143
|
+
} else throw new Error("invalid block type");
|
|
144
|
+
if (pos > totalBits) throw new Error("unexpected EOF");
|
|
145
|
+
}
|
|
146
|
+
ensureSize(limits ? Math.min(maximum, outputIndex + 131072) : outputIndex + 131072);
|
|
147
|
+
const lms = (1 << lengthBits) - 1;
|
|
148
|
+
const dms = (1 << distBits) - 1;
|
|
149
|
+
for (;;) {
|
|
150
|
+
const code = lengthMap[bits16(input, pos) & lms];
|
|
151
|
+
const sym = code >> 4;
|
|
152
|
+
pos += code & 15;
|
|
153
|
+
if (pos > totalBits) throw new Error("unexpected EOF");
|
|
154
|
+
if (!code) throw new Error("invalid length/literal");
|
|
155
|
+
if (sym < 256) {
|
|
156
|
+
if (limits) ensureSize(outputIndex + 1);
|
|
157
|
+
out[outputIndex++] = sym;
|
|
158
|
+
} else if (sym === 256) {
|
|
159
|
+
lengthMap = void 0;
|
|
160
|
+
break;
|
|
161
|
+
} else {
|
|
162
|
+
let add = sym - 254;
|
|
163
|
+
if (sym > 264) {
|
|
164
|
+
const index = sym - 257;
|
|
165
|
+
const b = fixedLengthExtraBits[index];
|
|
166
|
+
add = bits(input, pos, (1 << b) - 1) + fixedLength[index];
|
|
167
|
+
pos += b;
|
|
168
|
+
}
|
|
169
|
+
if (!distMap) throw new Error("invalid distance map");
|
|
170
|
+
const d = distMap[bits16(input, pos) & dms];
|
|
171
|
+
const dsym = d >> 4;
|
|
172
|
+
if (!d) throw new Error("invalid distance");
|
|
173
|
+
if (limits && dsym > 29) throw new Error("invalid distance symbol");
|
|
174
|
+
pos += d & 15;
|
|
175
|
+
let dt = fixedDistance[dsym];
|
|
176
|
+
if (dsym > 3) {
|
|
177
|
+
const b = fixedDistanceExtraBits[dsym];
|
|
178
|
+
dt += bits16(input, pos) & (1 << b) - 1;
|
|
179
|
+
pos += b;
|
|
180
|
+
}
|
|
181
|
+
if (pos > totalBits) throw new Error("unexpected EOF");
|
|
182
|
+
const end = outputIndex + add;
|
|
183
|
+
if (outputIndex < dt) throw new Error("unexpected dictionary case");
|
|
184
|
+
ensureSize(end);
|
|
185
|
+
for (; outputIndex < end; outputIndex++) out[outputIndex] = out[outputIndex - dt];
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
if (lengthMap) final = 1;
|
|
189
|
+
} while (!final);
|
|
190
|
+
return pos;
|
|
191
|
+
}
|
|
192
|
+
if (limits && outputIndex !== out.length) return out.slice(0, outputIndex);
|
|
193
|
+
if (!output) return out.subarray(0, outputIndex);
|
|
194
|
+
return out;
|
|
195
|
+
}
|
|
196
|
+
export { gunzip };
|
package/dist/_virtual/node_modules/.pnpm/hyparquet@1.31.1/node_modules/hyparquet/src/column.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Encodings, PageTypes } from "./constants.mjs";
|
|
2
1
|
import { convert, convertWithDictionary } from "./convert.mjs";
|
|
2
|
+
import { Encodings, PageTypes } from "./constants.mjs";
|
|
3
3
|
import { isFlatColumn } from "./schema.mjs";
|
|
4
4
|
import { deserializeTCompactProtocol } from "./thrift.mjs";
|
|
5
5
|
import { assembleLists } from "./assemble.mjs";
|
package/dist/_virtual/node_modules/.pnpm/hyparquet@1.31.1/node_modules/hyparquet/src/datapage.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
+
import { snappyUncompress } from "./snappy.mjs";
|
|
1
2
|
import { getMaxDefinitionLevel, getMaxRepetitionLevel } from "./schema.mjs";
|
|
2
3
|
import { deltaBinaryUnpack, deltaByteArray, deltaLengthByteArray } from "./delta.mjs";
|
|
3
4
|
import { byteStreamSplit, readRleBitPackedHybrid } from "./encoding.mjs";
|
|
4
5
|
import { readPlain } from "./plain.mjs";
|
|
5
|
-
import { snappyUncompress } from "./snappy.mjs";
|
|
6
6
|
function readDataPage(bytes, daph, { type, element, schemaPath }) {
|
|
7
7
|
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
8
8
|
const reader = {
|
package/dist/_virtual/node_modules/.pnpm/hyparquet@1.31.1/node_modules/hyparquet/src/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import "./snappy.mjs";
|
|
1
2
|
import { parquetMetadataAsync, parquetSchema } from "./metadata.mjs";
|
|
2
3
|
import "./indexes.mjs";
|
|
3
4
|
import { asyncBufferFromUrl, cachedAsyncBuffer, toJson } from "./utils.mjs";
|
|
4
|
-
import "./snappy.mjs";
|
|
5
5
|
import { parquetScan } from "./scan.mjs";
|
|
6
6
|
import { parquetReadObjects } from "./read.mjs";
|
|
7
7
|
import "./query.mjs";
|
package/dist/_virtual/node_modules/.pnpm/hyparquet@1.31.1/node_modules/hyparquet/src/indexes.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { BoundaryOrders } from "./constants.mjs";
|
|
2
1
|
import { DEFAULT_PARSERS } from "./convert.mjs";
|
|
2
|
+
import { BoundaryOrders } from "./constants.mjs";
|
|
3
3
|
import { deserializeTCompactProtocol } from "./thrift.mjs";
|
|
4
4
|
import { convertMetadata } from "./metadata.mjs";
|
|
5
5
|
function readColumnIndex(reader, schema, parsers = void 0) {
|
package/dist/_virtual/node_modules/.pnpm/hyparquet@1.31.1/node_modules/hyparquet/src/metadata.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { CompressionCodecs, ConvertedTypes, EdgeInterpolationAlgorithms, Encodings, FieldRepetitionTypes, PageTypes, ParquetTypes } from "./constants.mjs";
|
|
2
1
|
import { DEFAULT_PARSERS, parseDecimal, parseFloat16 } from "./convert.mjs";
|
|
2
|
+
import { CompressionCodecs, ConvertedTypes, EdgeInterpolationAlgorithms, Encodings, FieldRepetitionTypes, PageTypes, ParquetTypes } from "./constants.mjs";
|
|
3
3
|
import { getSchemaPath } from "./schema.mjs";
|
|
4
4
|
import { deserializeTCompactProtocol } from "./thrift.mjs";
|
|
5
5
|
import { markGeoColumns } from "./geoparquet.mjs";
|
package/dist/_virtual/node_modules/.pnpm/hyparquet@1.31.1/node_modules/hyparquet/src/node.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import "./snappy.mjs";
|
|
1
2
|
import { parquetMetadataAsync, parquetSchema } from "./metadata.mjs";
|
|
2
3
|
import "./indexes.mjs";
|
|
3
4
|
import { asyncBufferFromUrl, cachedAsyncBuffer, toJson } from "./utils.mjs";
|
|
4
|
-
import "./snappy.mjs";
|
|
5
5
|
import { parquetScan } from "./scan.mjs";
|
|
6
6
|
import { parquetReadObjects } from "./read.mjs";
|
|
7
7
|
import "./index.mjs";
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { parseDecimal } from "../../../../../hyparquet@1.31.1/node_modules/hyparquet/src/convert.mjs";
|
|
2
|
-
import { gunzip } from "../../../../../hyparquet-compressors@1.1.2_patch_hash=821c89dbb6181f0c34d9abebd844451458a4f16c04e7aa7a19abca0c09c2238d/node_modules/hyparquet-compressors/src/gzip.mjs";
|
|
3
|
-
import "../../../../../hyparquet-compressors@1.1.2_patch_hash=821c89dbb6181f0c34d9abebd844451458a4f16c04e7aa7a19abca0c09c2238d/node_modules/hyparquet-compressors/src/index.mjs";
|
|
4
1
|
import { boundedBytes } from "./avro.budget.mjs";
|
|
5
2
|
import { checkBlockEnd, readBlockEnd, readZigZag, readZigZagBigInt } from "./avro.metadata.mjs";
|
|
3
|
+
import { gunzip } from "../../../../../hyparquet-compressors@1.1.2_patch_hash=3f8f44805c034b2563763dcd5d37050ea6b1d5d45b46ea37adc4a721e748a1c5/node_modules/hyparquet-compressors/src/gzip.mjs";
|
|
4
|
+
import "../../../../../hyparquet-compressors@1.1.2_patch_hash=3f8f44805c034b2563763dcd5d37050ea6b1d5d45b46ea37adc4a721e748a1c5/node_modules/hyparquet-compressors/src/index.mjs";
|
|
5
|
+
import { parseDecimal } from "../../../../../hyparquet@1.31.1/node_modules/hyparquet/src/convert.mjs";
|
|
6
6
|
const textDecoder = new TextDecoder();
|
|
7
7
|
function avroRead({ reader, metadata, syncMarker, recordKind = "entries" }) {
|
|
8
8
|
const budget = reader.budget;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
+
import { avroMetadata } from "./avro/avro.metadata.mjs";
|
|
2
|
+
import { compressors } from "../../../../hyparquet-compressors@1.1.2_patch_hash=3f8f44805c034b2563763dcd5d37050ea6b1d5d45b46ea37adc4a721e748a1c5/node_modules/hyparquet-compressors/src/compressors.mjs";
|
|
3
|
+
import "../../../../hyparquet-compressors@1.1.2_patch_hash=3f8f44805c034b2563763dcd5d37050ea6b1d5d45b46ea37adc4a721e748a1c5/node_modules/hyparquet-compressors/src/index.mjs";
|
|
4
|
+
import { avroRead } from "./avro/avro.read.mjs";
|
|
1
5
|
import { parquetMetadataAsync } from "../../../../hyparquet@1.31.1/node_modules/hyparquet/src/metadata.mjs";
|
|
2
6
|
import { asyncBufferFromUrl, cachedAsyncBuffer } from "../../../../hyparquet@1.31.1/node_modules/hyparquet/src/utils.mjs";
|
|
3
7
|
import { parquetReadObjects } from "../../../../hyparquet@1.31.1/node_modules/hyparquet/src/read.mjs";
|
|
4
8
|
import "../../../../hyparquet@1.31.1/node_modules/hyparquet/src/node.mjs";
|
|
5
|
-
import { compressors } from "../../../../hyparquet-compressors@1.1.2_patch_hash=821c89dbb6181f0c34d9abebd844451458a4f16c04e7aa7a19abca0c09c2238d/node_modules/hyparquet-compressors/src/compressors.mjs";
|
|
6
|
-
import "../../../../hyparquet-compressors@1.1.2_patch_hash=821c89dbb6181f0c34d9abebd844451458a4f16c04e7aa7a19abca0c09c2238d/node_modules/hyparquet-compressors/src/index.mjs";
|
|
7
9
|
import { ByteWriter } from "../../../../hyparquet-writer@0.16.10_patch_hash=d26d002aede61ad95dd633d6557b56897cdcbc45dfc3a5d93fa0e9075ad5425f/node_modules/hyparquet-writer/src/bytewriter.mjs";
|
|
8
10
|
import "../../../../hyparquet-writer@0.16.10_patch_hash=d26d002aede61ad95dd633d6557b56897cdcbc45dfc3a5d93fa0e9075ad5425f/node_modules/hyparquet-writer/src/node.mjs";
|
|
9
|
-
import { avroMetadata } from "./avro/avro.metadata.mjs";
|
|
10
|
-
import { avroRead } from "./avro/avro.read.mjs";
|
|
11
11
|
import { sanitize } from "./utils.mjs";
|
|
12
12
|
import { isDeletionVector } from "./delete.mjs";
|
|
13
13
|
import { puffinReadDeletionVector } from "./puffin/puffin.mjs";
|
|
@@ -68,40 +68,6 @@ function urlResolver({ requestInit } = {}) {
|
|
|
68
68
|
}
|
|
69
69
|
};
|
|
70
70
|
}
|
|
71
|
-
function cachingResolver(base) {
|
|
72
|
-
const cache = /* @__PURE__ */ new Map();
|
|
73
|
-
const out = { reader(path, byteLength) {
|
|
74
|
-
let buf = cache.get(path);
|
|
75
|
-
if (!buf) {
|
|
76
|
-
buf = (async () => cachedAsyncBuffer(await base.reader(path, byteLength)))();
|
|
77
|
-
cache.set(path, buf);
|
|
78
|
-
buf.catch(() => {
|
|
79
|
-
if (cache.get(path) === buf) cache.delete(path);
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
return buf;
|
|
83
|
-
} };
|
|
84
|
-
if (base.writer) {
|
|
85
|
-
const baseWriter = base.writer;
|
|
86
|
-
out.writer = (path, options) => {
|
|
87
|
-
const w = baseWriter(path, options);
|
|
88
|
-
const origFinish = w.finish.bind(w);
|
|
89
|
-
w.finish = async function() {
|
|
90
|
-
await origFinish();
|
|
91
|
-
cache.delete(path);
|
|
92
|
-
};
|
|
93
|
-
return w;
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
if (base.deleter) {
|
|
97
|
-
const baseDeleter = base.deleter;
|
|
98
|
-
out.deleter = async (path) => {
|
|
99
|
-
await baseDeleter(path);
|
|
100
|
-
cache.delete(path);
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
return out;
|
|
104
|
-
}
|
|
105
71
|
function s3Lister({ requestInit } = {}) {
|
|
106
72
|
return async function list(url) {
|
|
107
73
|
const s3parts = s3ParseUrl(url);
|
|
@@ -299,4 +265,4 @@ async function fetchBoundedAvroObject(url, resolver, byteLength, budget, recordK
|
|
|
299
265
|
return budget.fail(error);
|
|
300
266
|
}
|
|
301
267
|
}
|
|
302
|
-
export {
|
|
268
|
+
export { fetchAvroRecords, fetchBoundedAvroObject, fetchDeleteMaps, readParquetMetadata, resolveText, s3Lister, s3ParseUrl, translateS3Url, urlResolver };
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { compressors } from "../../../../hyparquet-compressors@1.1.2_patch_hash=3f8f44805c034b2563763dcd5d37050ea6b1d5d45b46ea37adc4a721e748a1c5/node_modules/hyparquet-compressors/src/compressors.mjs";
|
|
2
|
+
import "../../../../hyparquet-compressors@1.1.2_patch_hash=3f8f44805c034b2563763dcd5d37050ea6b1d5d45b46ea37adc4a721e748a1c5/node_modules/hyparquet-compressors/src/index.mjs";
|
|
1
3
|
import { isListLike, isMapLike } from "../../../../hyparquet@1.31.1/node_modules/hyparquet/src/schema.mjs";
|
|
2
4
|
import { parquetSchema } from "../../../../hyparquet@1.31.1/node_modules/hyparquet/src/metadata.mjs";
|
|
3
5
|
import { cachedAsyncBuffer } from "../../../../hyparquet@1.31.1/node_modules/hyparquet/src/utils.mjs";
|
|
@@ -5,8 +7,6 @@ import { columnsNeededForFilter, matchFilter } from "../../../../hyparquet@1.31.
|
|
|
5
7
|
import { parquetScan } from "../../../../hyparquet@1.31.1/node_modules/hyparquet/src/scan.mjs";
|
|
6
8
|
import { parquetReadObjects } from "../../../../hyparquet@1.31.1/node_modules/hyparquet/src/read.mjs";
|
|
7
9
|
import "../../../../hyparquet@1.31.1/node_modules/hyparquet/src/node.mjs";
|
|
8
|
-
import { compressors } from "../../../../hyparquet-compressors@1.1.2_patch_hash=821c89dbb6181f0c34d9abebd844451458a4f16c04e7aa7a19abca0c09c2238d/node_modules/hyparquet-compressors/src/compressors.mjs";
|
|
9
|
-
import "../../../../hyparquet-compressors@1.1.2_patch_hash=821c89dbb6181f0c34d9abebd844451458a4f16c04e7aa7a19abca0c09c2238d/node_modules/hyparquet-compressors/src/index.mjs";
|
|
10
10
|
import { equalityMatch, sanitize } from "./utils.mjs";
|
|
11
11
|
import { applicablePositionDeletes, deleteFileAppliesToDataEntry } from "./delete.mjs";
|
|
12
12
|
import { readParquetMetadata } from "./fetch.mjs";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { icebergManifests } from "./manifest.mjs";
|
|
2
2
|
import { icebergAppend, icebergCreateTable, icebergDropTable } from "./write/write.mjs";
|
|
3
|
-
import { restCatalogConnect, restCatalogCreateNamespace, restCatalogListTables, restCatalogLoadTable } from "./catalog/rest.mjs";
|
|
4
3
|
import { cachingResolver } from "./fetch.mjs";
|
|
4
|
+
import { restCatalogConnect, restCatalogCreateNamespace, restCatalogListTables, restCatalogLoadTable } from "./catalog/rest.mjs";
|
|
5
5
|
import "./create.mjs";
|
|
6
6
|
import "./catalog/file.mjs";
|
|
7
7
|
import { s3SignedResolver } from "./s3.mjs";
|
package/dist/catalog.d.mts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { ManifestReadCache } from "./_virtual/node_modules/.pnpm/icebird@0.8.30_patch_hash=1359a91da68522a736babe444880ae391f19455fbe47c346f76cec92c5c2e471/node_modules/icebird/types/manifest.mjs";
|
|
1
|
+
import { ManifestReadCache, ManifestReadLimits } from "./_virtual/node_modules/.pnpm/icebird@0.8.30_patch_hash=1359a91da68522a736babe444880ae391f19455fbe47c346f76cec92c5c2e471/node_modules/icebird/types/manifest.mjs";
|
|
2
2
|
import { icebergAppend } from "./_virtual/node_modules/.pnpm/icebird@0.8.30_patch_hash=1359a91da68522a736babe444880ae391f19455fbe47c346f76cec92c5c2e471/node_modules/icebird/types/write/write.mjs";
|
|
3
3
|
import { CatalogCache } from "./catalog-cache.mjs";
|
|
4
|
+
import { Resolver } from "./icebird-resolver.mjs";
|
|
5
|
+
import "./manifest-read-limits.mjs";
|
|
4
6
|
import { IcebergPrimitiveType, IcebergS3Config } from "./schema.mjs";
|
|
5
7
|
import { PartitionValueMatch } from "./partition-prune.mjs";
|
|
6
8
|
import { restCatalogConnect, restCatalogLoadTable } from "./_virtual/node_modules/.pnpm/icebird@0.8.30_patch_hash=1359a91da68522a736babe444880ae391f19455fbe47c346f76cec92c5c2e471/node_modules/icebird/types/catalog/rest.mjs";
|
|
7
|
-
import { cachingResolver } from "./_virtual/node_modules/.pnpm/icebird@0.8.30_patch_hash=1359a91da68522a736babe444880ae391f19455fbe47c346f76cec92c5c2e471/node_modules/icebird/types/fetch.mjs";
|
|
8
9
|
/** A field in an icebird table `Schema`. */
|
|
9
10
|
export interface IcebergSchemaField {
|
|
10
11
|
id: number;
|
|
@@ -61,7 +62,7 @@ export interface IcebergConnection {
|
|
|
61
62
|
/** icebird REST catalog context, passed as `{ catalog }` to icebird write fns. */
|
|
62
63
|
catalog: Awaited<ReturnType<typeof restCatalogConnect>>;
|
|
63
64
|
/** icebird S3 resolver (caching-wrapped), passed as `{ resolver }` to icebird fns. */
|
|
64
|
-
resolver:
|
|
65
|
+
resolver: Resolver;
|
|
65
66
|
/** The namespace the dataset's table lives under. */
|
|
66
67
|
namespace: string;
|
|
67
68
|
/**
|
|
@@ -259,6 +260,13 @@ export interface ResolveIcebergDataFilesOptions {
|
|
|
259
260
|
cache?: CatalogCache;
|
|
260
261
|
clock?: () => number;
|
|
261
262
|
profiler?: QueryProfiler;
|
|
263
|
+
/**
|
|
264
|
+
* Opt-in Avro source/decode-work limits for one uncached manifest walk.
|
|
265
|
+
* Bypasses decoded manifest, month and resolved-file caches; catalog metadata
|
|
266
|
+
* and snapshot caching keep their existing authority and are not byte-bounded
|
|
267
|
+
* by this option. No default limits or fallback to unbounded decoding.
|
|
268
|
+
*/
|
|
269
|
+
readLimits?: ManifestReadLimits;
|
|
262
270
|
}
|
|
263
271
|
/**
|
|
264
272
|
* Drop the cached snapshot pointer for `(namespace, table)` so the next read
|
package/dist/catalog.mjs
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { stringifyBigintSafe } from "./bigint.mjs";
|
|
2
2
|
import { restCatalogConnect, restCatalogCreateNamespace, restCatalogListTables, restCatalogLoadTable } from "./_virtual/node_modules/.pnpm/icebird@0.8.30_patch_hash=1359a91da68522a736babe444880ae391f19455fbe47c346f76cec92c5c2e471/node_modules/icebird/src/catalog/rest.mjs";
|
|
3
|
-
import { cachingResolver } from "./_virtual/node_modules/.pnpm/icebird@0.8.30_patch_hash=1359a91da68522a736babe444880ae391f19455fbe47c346f76cec92c5c2e471/node_modules/icebird/src/fetch.mjs";
|
|
4
3
|
import { icebergManifests } from "./_virtual/node_modules/.pnpm/icebird@0.8.30_patch_hash=1359a91da68522a736babe444880ae391f19455fbe47c346f76cec92c5c2e471/node_modules/icebird/src/manifest.mjs";
|
|
5
4
|
import { s3SignedResolver } from "./_virtual/node_modules/.pnpm/icebird@0.8.30_patch_hash=1359a91da68522a736babe444880ae391f19455fbe47c346f76cec92c5c2e471/node_modules/icebird/src/s3.mjs";
|
|
6
5
|
import { deriveAppendIdentity } from "./append-identity.mjs";
|
|
7
6
|
import { cacheGet, cachePut, reportCatalogCacheError } from "./catalog-cache.mjs";
|
|
8
7
|
import { toIcebergDayCount } from "./date.mjs";
|
|
8
|
+
import { captureManifestReadLimits } from "./manifest-read-limits.mjs";
|
|
9
9
|
import { MULTI_MONTH_MANIFEST, buildManifestPartitionFilter, manifestMonthBucket } from "./partition-prune.mjs";
|
|
10
|
+
import { byteCappedCachingResolver } from "./resolver-byte-cache.mjs";
|
|
10
11
|
const connectionReadBatch = Symbol("iceberg-connection-read-batch");
|
|
11
12
|
function beginConnectionRead(conn) {
|
|
12
13
|
const batch = conn[connectionReadBatch];
|
|
@@ -115,7 +116,7 @@ async function connectIcebergCatalog(config, opts = {}) {
|
|
|
115
116
|
endpoint: config.s3.endpoint,
|
|
116
117
|
pathStyle: true
|
|
117
118
|
});
|
|
118
|
-
const resolver = withVerifiedWriterByteLengths(
|
|
119
|
+
const resolver = withUncachedReader(withVerifiedWriterByteLengths(byteCappedCachingResolver(s3Resolver)), s3Resolver);
|
|
119
120
|
return {
|
|
120
121
|
catalog,
|
|
121
122
|
resolver,
|
|
@@ -128,6 +129,17 @@ async function connectIcebergCatalog(config, opts = {}) {
|
|
|
128
129
|
}
|
|
129
130
|
};
|
|
130
131
|
}
|
|
132
|
+
const uncachedReader = Symbol("iceberg-uncached-reader");
|
|
133
|
+
function withUncachedReader(resolver, base) {
|
|
134
|
+
return {
|
|
135
|
+
...resolver,
|
|
136
|
+
[uncachedReader]: (path, byteLength) => base.reader(path, byteLength)
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
function boundedReadResolver(resolver) {
|
|
140
|
+
const read = resolver[uncachedReader];
|
|
141
|
+
return read ? { reader: read } : resolver;
|
|
142
|
+
}
|
|
131
143
|
function withVerifiedWriterByteLengths(resolver) {
|
|
132
144
|
if (!resolver.writer) return resolver;
|
|
133
145
|
const baseWriter = resolver.writer;
|
|
@@ -643,12 +655,14 @@ function toListedFile(entry, matches, monthFieldName, wantedMonths, dateFieldId)
|
|
|
643
655
|
...dateBounds ? { dateBounds } : {}
|
|
644
656
|
};
|
|
645
657
|
}
|
|
646
|
-
async function resolveViaFullWalk(conn, metadata, partitionFilter, matches, monthFieldName, wantedMonths, dateFieldId, manifestCache) {
|
|
658
|
+
async function resolveViaFullWalk(conn, metadata, partitionFilter, matches, monthFieldName, wantedMonths, dateFieldId, manifestCache, readLimits) {
|
|
659
|
+
const resolver = readLimits ? boundedReadResolver(conn.resolver) : conn.resolver;
|
|
647
660
|
const manifests = await icebergManifests({
|
|
648
661
|
metadata,
|
|
649
|
-
resolver
|
|
662
|
+
resolver,
|
|
650
663
|
partitionFilter,
|
|
651
|
-
manifestCache
|
|
664
|
+
manifestCache,
|
|
665
|
+
readLimits
|
|
652
666
|
});
|
|
653
667
|
const entries = [];
|
|
654
668
|
for (const m of manifests) for (const entry of m.entries) {
|
|
@@ -745,6 +759,7 @@ function resolveIcebergDataFiles(conn, opts) {
|
|
|
745
759
|
return resolveIcebergDataFilesInBatch(conn, opts).finally(release);
|
|
746
760
|
}
|
|
747
761
|
async function resolveIcebergDataFilesInBatch(conn, opts) {
|
|
762
|
+
const readLimits = captureManifestReadLimits(opts.readLimits);
|
|
748
763
|
const { namespace, table } = opts;
|
|
749
764
|
const profiler = opts.profiler;
|
|
750
765
|
const now = (opts.clock ?? Date.now)();
|
|
@@ -756,7 +771,7 @@ async function resolveIcebergDataFilesInBatch(conn, opts) {
|
|
|
756
771
|
if (snapshotId == null) return [];
|
|
757
772
|
const scope = conn.cacheScope ?? "";
|
|
758
773
|
const filesKey = resolvedFilesKey(scope, namespace, table, snapshotId, opts.matches, opts.range);
|
|
759
|
-
if (opts.cache) {
|
|
774
|
+
if (opts.cache && !readLimits) {
|
|
760
775
|
const endCache = profiler?.start("iceberg.cache");
|
|
761
776
|
const cached = await cacheGet(opts.cache, filesKey, now);
|
|
762
777
|
endCache?.({ hit: cached !== void 0 });
|
|
@@ -778,8 +793,8 @@ async function resolveIcebergDataFilesInBatch(conn, opts) {
|
|
|
778
793
|
const monthFieldName = monthField?.name;
|
|
779
794
|
const dateFieldId = dateColumnFieldId(metadata, monthField?.sourceColumn);
|
|
780
795
|
const dayWindow = rangeDayWindow(opts.range);
|
|
781
|
-
const manifestCache = manifestReadCacheFor(conn, namespace, table, metadata);
|
|
782
|
-
const walk = opts.cache && monthFieldName ? await resolveViaMonthCache(conn, opts.cache, metadata, partitionFilter, opts.partitionSpec, opts.matches, monthFieldName, wantedMonths, dateFieldId, scope, namespace, table, now, manifestCache) : await resolveViaFullWalk(conn, metadata, partitionFilter, opts.matches, monthFieldName, wantedMonths, dateFieldId, manifestCache);
|
|
796
|
+
const manifestCache = readLimits ? void 0 : manifestReadCacheFor(conn, namespace, table, metadata);
|
|
797
|
+
const walk = opts.cache && monthFieldName && !readLimits ? await resolveViaMonthCache(conn, opts.cache, metadata, partitionFilter, opts.partitionSpec, opts.matches, monthFieldName, wantedMonths, dateFieldId, scope, namespace, table, now, manifestCache) : await resolveViaFullWalk(conn, metadata, partitionFilter, opts.matches, monthFieldName, wantedMonths, dateFieldId, manifestCache, readLimits);
|
|
783
798
|
let boundsPruned = 0;
|
|
784
799
|
const out = [];
|
|
785
800
|
for (const file of walk.entries) {
|
|
@@ -798,7 +813,7 @@ async function resolveIcebergDataFilesInBatch(conn, opts) {
|
|
|
798
813
|
monthsHit: walk.monthsHit,
|
|
799
814
|
manifestsWalked: walk.manifestsWalked
|
|
800
815
|
});
|
|
801
|
-
if (opts.cache) {
|
|
816
|
+
if (opts.cache && !readLimits) {
|
|
802
817
|
const freshKey = resolvedFilesKey(scope, namespace, table, snapshotId, opts.matches, opts.range);
|
|
803
818
|
await cachePut(opts.cache, freshKey, out, RESOLVED_FILES_TTL_MS, now);
|
|
804
819
|
}
|
package/dist/dataset.d.mts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { ManifestReadLimits } from "./_virtual/node_modules/.pnpm/icebird@0.8.30_patch_hash=1359a91da68522a736babe444880ae391f19455fbe47c346f76cec92c5c2e471/node_modules/icebird/types/manifest.mjs";
|
|
1
2
|
import { CatalogCache } from "./catalog-cache.mjs";
|
|
3
|
+
import "./manifest-read-limits.mjs";
|
|
2
4
|
import { IcebergColumnType, IcebergPartitionField, IcebergTableSpec } from "./schema.mjs";
|
|
3
5
|
import { ManifestPartitionFilter, PartitionValueMatch } from "./partition-prune.mjs";
|
|
4
6
|
import { CommitRetryOptions, ConnectIcebergOptions, IcebergCatalogConfig, IcebergConnection, IcebergListedDataFile, IcebergPartitionSpec, IcebergSchema, IcebergSortOrder, IcebergTableOpResult, QueryProfiler } from "./catalog.mjs";
|
|
@@ -97,6 +99,8 @@ export interface ResolveDataFilesOptions {
|
|
|
97
99
|
cache?: CatalogCache;
|
|
98
100
|
clock?: () => number;
|
|
99
101
|
profiler?: QueryProfiler;
|
|
102
|
+
/** Uncached Avro read limits; catalog metadata/snapshot caching is unchanged. */
|
|
103
|
+
readLimits?: ManifestReadLimits;
|
|
100
104
|
}
|
|
101
105
|
export interface IcebergDataset {
|
|
102
106
|
readonly def: IcebergDatasetDef;
|
package/dist/dataset.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { coerceBigIntToNumber } from "./bigint.mjs";
|
|
2
|
+
import { captureManifestReadLimits } from "./manifest-read-limits.mjs";
|
|
2
3
|
import { buildManifestPartitionFilter } from "./partition-prune.mjs";
|
|
3
4
|
import { ICEBERG_TYPE_MAP } from "./schema.mjs";
|
|
4
5
|
const INT32_MIN = -2147483648;
|
|
@@ -299,6 +300,7 @@ function defineIcebergDataset(def) {
|
|
|
299
300
|
});
|
|
300
301
|
}
|
|
301
302
|
async function resolveDataFiles(conn, identity, range, dims, opts = {}) {
|
|
303
|
+
const readLimits = captureManifestReadLimits(opts.readLimits);
|
|
302
304
|
const { resolveDatasetDataFiles } = await import("./dataset-runtime.mjs");
|
|
303
305
|
return resolveDatasetDataFiles(conn, {
|
|
304
306
|
namespace: def.namespace,
|
|
@@ -308,7 +310,8 @@ function defineIcebergDataset(def) {
|
|
|
308
310
|
range,
|
|
309
311
|
cache: opts.cache,
|
|
310
312
|
clock: opts.clock,
|
|
311
|
-
profiler: opts.profiler
|
|
313
|
+
profiler: opts.profiler,
|
|
314
|
+
readLimits
|
|
312
315
|
});
|
|
313
316
|
}
|
|
314
317
|
return {
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { cachingResolver } from "./_virtual/node_modules/.pnpm/icebird@0.8.30_patch_hash=1359a91da68522a736babe444880ae391f19455fbe47c346f76cec92c5c2e471/node_modules/icebird/types/fetch.mjs";
|
|
2
|
+
/**
|
|
3
|
+
* icebird's file `Resolver`.
|
|
4
|
+
*
|
|
5
|
+
* Derive it from `cachingResolver` and never import `icebird/src/types.js`.
|
|
6
|
+
* That specifier has no declaration under icebird's `types/` folder, so the
|
|
7
|
+
* declaration bundler keeps it as an external import. icebird is bundled and
|
|
8
|
+
* consumers do not install it, so the type would resolve to `any` for them.
|
|
9
|
+
*/
|
|
10
|
+
export type Resolver = ReturnType<typeof cachingResolver>;
|
package/dist/index.d.mts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { bigintJsonReplacer, coerceBigIntToNumber, encodeJsonBigintSafe, stringifyBigintSafe } from "./bigint.mjs";
|
|
2
|
+
import { ManifestReadLimits } from "./_virtual/node_modules/.pnpm/icebird@0.8.30_patch_hash=1359a91da68522a736babe444880ae391f19455fbe47c346f76cec92c5c2e471/node_modules/icebird/types/manifest.mjs";
|
|
2
3
|
import { CatalogCache, CatalogCacheGetOutcome, cacheGet, cachePut } from "./catalog-cache.mjs";
|
|
4
|
+
import "./manifest-read-limits.mjs";
|
|
3
5
|
import { DEFAULT_PARTITION_KEY_ENCODING, ICEBERG_TYPE_MAP, IcebergColumn, IcebergColumnType, IcebergPartitionField, IcebergPartitionTransform, IcebergPrimitiveType, IcebergS3Config, IcebergTableSpec, PartitionKeyEncoding } from "./schema.mjs";
|
|
4
6
|
import { IcebergFieldSummary, ManifestPartitionFilter, PartitionValueMatch, buildManifestPartitionFilter } from "./partition-prune.mjs";
|
|
5
7
|
import { CommitRetryOptions, ConnectIcebergOptions, IcebergCatalogConfig, IcebergConnection, IcebergDataFileDateBounds, IcebergListedDataFile, IcebergPartitionSpec, IcebergPartitionSpecField, IcebergSchema, IcebergSchemaField, IcebergSortOrder, IcebergSortOrderField, IcebergTableOpResult, QueryProfiler, ResolveIcebergDataFilesOptions, catalogCacheScope, connectIcebergCatalog, createIcebergNamespace, dropIcebergTables, ensureIcebergNamespace, invalidateSnapshotRef, listIcebergTables, resolveIcebergDataFiles } from "./catalog.mjs";
|
|
6
8
|
import { AppendBatchSource, AppendBatchesOptions, AppendBatchesResult, AppendCommitOptions, AppendResult, AppendSink, AppendSinkCloseResult, AppendSinkOptions, DatasetDim, DatasetIdentity, IcebergDataset, IcebergDatasetColumnDef, IcebergDatasetDef, IcebergDatasetLedger, ResolveDataFilesOptions, defineIcebergDataset, deriveTableSpec } from "./dataset.mjs";
|
|
7
9
|
import { toIcebergDayCount } from "./date.mjs";
|
|
8
|
-
export { type AppendBatchSource, type AppendBatchesOptions, type AppendBatchesResult, type AppendCommitOptions, type AppendResult, type AppendSink, type AppendSinkCloseResult, type AppendSinkOptions, type CatalogCache, type CatalogCacheGetOutcome, type CommitRetryOptions, type ConnectIcebergOptions, DEFAULT_PARTITION_KEY_ENCODING, type DatasetDim, type DatasetIdentity, ICEBERG_TYPE_MAP, type IcebergCatalogConfig, type IcebergColumn, type IcebergColumnType, type IcebergConnection, type IcebergDataFileDateBounds, type IcebergDataset, type IcebergDatasetColumnDef, type IcebergDatasetDef, type IcebergDatasetLedger, type IcebergFieldSummary, type IcebergListedDataFile, type IcebergPartitionField, type IcebergPartitionSpec, type IcebergPartitionSpecField, type IcebergPartitionTransform, type IcebergPrimitiveType, type IcebergS3Config, type IcebergSchema, type IcebergSchemaField, type IcebergSortOrder, type IcebergSortOrderField, type IcebergTableOpResult, type IcebergTableSpec, type ManifestPartitionFilter, type PartitionKeyEncoding, type PartitionValueMatch, type QueryProfiler, type ResolveDataFilesOptions, type ResolveIcebergDataFilesOptions, bigintJsonReplacer, buildManifestPartitionFilter, cacheGet, cachePut, catalogCacheScope, coerceBigIntToNumber, connectIcebergCatalog, createIcebergNamespace, defineIcebergDataset, deriveTableSpec, dropIcebergTables, encodeJsonBigintSafe, ensureIcebergNamespace, invalidateSnapshotRef, listIcebergTables, resolveIcebergDataFiles, stringifyBigintSafe, toIcebergDayCount };
|
|
10
|
+
export { type AppendBatchSource, type AppendBatchesOptions, type AppendBatchesResult, type AppendCommitOptions, type AppendResult, type AppendSink, type AppendSinkCloseResult, type AppendSinkOptions, type CatalogCache, type CatalogCacheGetOutcome, type CommitRetryOptions, type ConnectIcebergOptions, DEFAULT_PARTITION_KEY_ENCODING, type DatasetDim, type DatasetIdentity, ICEBERG_TYPE_MAP, type IcebergCatalogConfig, type IcebergColumn, type IcebergColumnType, type IcebergConnection, type IcebergDataFileDateBounds, type IcebergDataset, type IcebergDatasetColumnDef, type IcebergDatasetDef, type IcebergDatasetLedger, type IcebergFieldSummary, type IcebergListedDataFile, type IcebergPartitionField, type IcebergPartitionSpec, type IcebergPartitionSpecField, type IcebergPartitionTransform, type IcebergPrimitiveType, type IcebergS3Config, type IcebergSchema, type IcebergSchemaField, type IcebergSortOrder, type IcebergSortOrderField, type IcebergTableOpResult, type IcebergTableSpec, type ManifestPartitionFilter, type ManifestReadLimits, type PartitionKeyEncoding, type PartitionValueMatch, type QueryProfiler, type ResolveDataFilesOptions, type ResolveIcebergDataFilesOptions, bigintJsonReplacer, buildManifestPartitionFilter, cacheGet, cachePut, catalogCacheScope, coerceBigIntToNumber, connectIcebergCatalog, createIcebergNamespace, defineIcebergDataset, deriveTableSpec, dropIcebergTables, encodeJsonBigintSafe, ensureIcebergNamespace, invalidateSnapshotRef, listIcebergTables, resolveIcebergDataFiles, stringifyBigintSafe, toIcebergDayCount };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
const fields = [
|
|
2
|
+
"maxObjectBytes",
|
|
3
|
+
"maxTotalObjectBytes",
|
|
4
|
+
"maxManifests",
|
|
5
|
+
"maxEntries",
|
|
6
|
+
"maxInflatedBlockBytes",
|
|
7
|
+
"maxTotalInflatedBytes",
|
|
8
|
+
"maxValueBytes",
|
|
9
|
+
"maxDecodedValues",
|
|
10
|
+
"maxHeaderBytes",
|
|
11
|
+
"maxSchemaDepth"
|
|
12
|
+
];
|
|
13
|
+
function captureManifestReadLimits(options) {
|
|
14
|
+
if (options === void 0) return void 0;
|
|
15
|
+
if (!options || typeof options !== "object" || Array.isArray(options)) throw new TypeError("Invalid manifest read limits");
|
|
16
|
+
for (const key of Object.keys(options)) if (!fields.includes(key)) throw new TypeError(`Unknown manifest read limit: ${key}`);
|
|
17
|
+
const limits = {};
|
|
18
|
+
for (const key of fields) {
|
|
19
|
+
const value = options[key];
|
|
20
|
+
if (!Number.isSafeInteger(value) || value <= 0) throw new RangeError(`Invalid manifest read limit: ${key}`);
|
|
21
|
+
limits[key] = value;
|
|
22
|
+
}
|
|
23
|
+
if (limits.maxSchemaDepth > 128) throw new RangeError("Manifest schema depth must not exceed 128");
|
|
24
|
+
return Object.freeze(limits);
|
|
25
|
+
}
|
|
26
|
+
export { captureManifestReadLimits };
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { cachedAsyncBuffer } from "./_virtual/node_modules/.pnpm/hyparquet@1.31.1/node_modules/hyparquet/src/utils.mjs";
|
|
2
|
+
import "./_virtual/node_modules/.pnpm/hyparquet@1.31.1/node_modules/hyparquet/src/node.mjs";
|
|
3
|
+
const CONNECTION_CACHE_MAX_BYTES = 16777216;
|
|
4
|
+
function byteCappedCachingResolver(base, maxBytes = CONNECTION_CACHE_MAX_BYTES) {
|
|
5
|
+
const entries = /* @__PURE__ */ new Map();
|
|
6
|
+
let totalBytes = 0;
|
|
7
|
+
function touch(path, entry) {
|
|
8
|
+
entries.delete(path);
|
|
9
|
+
entries.set(path, entry);
|
|
10
|
+
}
|
|
11
|
+
function evict(path, account) {
|
|
12
|
+
if (entries.get(path)?.account !== account) return;
|
|
13
|
+
entries.delete(path);
|
|
14
|
+
totalBytes -= account.bytes;
|
|
15
|
+
}
|
|
16
|
+
function retain(path, account, bytes) {
|
|
17
|
+
const entry = entries.get(path);
|
|
18
|
+
if (entry?.account !== account) return;
|
|
19
|
+
account.bytes += bytes;
|
|
20
|
+
totalBytes += bytes;
|
|
21
|
+
touch(path, entry);
|
|
22
|
+
if (account.bytes > maxBytes) {
|
|
23
|
+
evict(path, account);
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
for (const [oldest, old] of entries) {
|
|
27
|
+
if (totalBytes <= maxBytes) break;
|
|
28
|
+
if (old.account.bytes > 0) evict(oldest, old.account);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function counted(path, account, file) {
|
|
32
|
+
return {
|
|
33
|
+
byteLength: file.byteLength,
|
|
34
|
+
slice(start, end) {
|
|
35
|
+
return Promise.resolve(file.slice(start, end)).then((bytes) => {
|
|
36
|
+
retain(path, account, bytes.byteLength);
|
|
37
|
+
return bytes;
|
|
38
|
+
}, (error) => {
|
|
39
|
+
evict(path, account);
|
|
40
|
+
throw error;
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
function invalidate(path) {
|
|
46
|
+
const entry = entries.get(path);
|
|
47
|
+
if (entry) evict(path, entry.account);
|
|
48
|
+
}
|
|
49
|
+
const out = { reader(path, byteLength) {
|
|
50
|
+
const hit = entries.get(path);
|
|
51
|
+
if (hit) {
|
|
52
|
+
touch(path, hit);
|
|
53
|
+
return hit.buffer;
|
|
54
|
+
}
|
|
55
|
+
const account = { bytes: 0 };
|
|
56
|
+
const buffer = (async () => cachedAsyncBuffer(counted(path, account, await base.reader(path, byteLength))))();
|
|
57
|
+
entries.set(path, {
|
|
58
|
+
buffer,
|
|
59
|
+
account
|
|
60
|
+
});
|
|
61
|
+
buffer.catch(() => evict(path, account));
|
|
62
|
+
return buffer;
|
|
63
|
+
} };
|
|
64
|
+
if (base.writer) {
|
|
65
|
+
const baseWriter = base.writer;
|
|
66
|
+
out.writer = (path, options) => {
|
|
67
|
+
const writer = baseWriter(path, options);
|
|
68
|
+
const finish = writer.finish.bind(writer);
|
|
69
|
+
writer.finish = async function() {
|
|
70
|
+
await finish();
|
|
71
|
+
invalidate(path);
|
|
72
|
+
};
|
|
73
|
+
return writer;
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
if (base.deleter) {
|
|
77
|
+
const baseDeleter = base.deleter;
|
|
78
|
+
out.deleter = async (path) => {
|
|
79
|
+
await baseDeleter(path);
|
|
80
|
+
invalidate(path);
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
return out;
|
|
84
|
+
}
|
|
85
|
+
export { CONNECTION_CACHE_MAX_BYTES, byteCappedCachingResolver };
|
package/package.json
CHANGED
|
@@ -1,186 +0,0 @@
|
|
|
1
|
-
import { fixedDistance, fixedDistanceExtraBits, fixedDistanceMap, fixedLength, fixedLengthExtraBits, fixedLengthMap, huffMap } from "./gzip.huffman.mjs";
|
|
2
|
-
const codeLengthIndexMap = new Uint8Array([
|
|
3
|
-
16,
|
|
4
|
-
17,
|
|
5
|
-
18,
|
|
6
|
-
0,
|
|
7
|
-
8,
|
|
8
|
-
7,
|
|
9
|
-
9,
|
|
10
|
-
6,
|
|
11
|
-
10,
|
|
12
|
-
5,
|
|
13
|
-
11,
|
|
14
|
-
4,
|
|
15
|
-
12,
|
|
16
|
-
3,
|
|
17
|
-
13,
|
|
18
|
-
2,
|
|
19
|
-
14,
|
|
20
|
-
1,
|
|
21
|
-
15
|
|
22
|
-
]);
|
|
23
|
-
function bits(input, pos, mask) {
|
|
24
|
-
const o = pos / 8 | 0;
|
|
25
|
-
return (input[o] | input[o + 1] << 8) >> (pos & 7) & mask;
|
|
26
|
-
}
|
|
27
|
-
function bits16(d, p) {
|
|
28
|
-
const o = p / 8 | 0;
|
|
29
|
-
return (d[o] | d[o + 1] << 8 | d[o + 2] << 16) >> (p & 7);
|
|
30
|
-
}
|
|
31
|
-
function shft(p) {
|
|
32
|
-
return (p + 7) / 8 | 0;
|
|
33
|
-
}
|
|
34
|
-
function gzipStart(input, i) {
|
|
35
|
-
if (input[i++] !== 31 || input[i++] !== 139 || input[i++] !== 8) return 0;
|
|
36
|
-
const flag = input[i++];
|
|
37
|
-
i += 6;
|
|
38
|
-
if (flag & 4) i += (input[i + 10] | input[i + 11] << 8) + 2;
|
|
39
|
-
for (let zs = (flag >> 3 & 1) + (flag >> 4 & 1); zs > 0; zs -= Number(!input[i++]));
|
|
40
|
-
return i + (flag & 2);
|
|
41
|
-
}
|
|
42
|
-
function gunzip(input, output, inputIndex = 0, outputIndex = 0, limits) {
|
|
43
|
-
const maximum = limits?.maxOutputBytes;
|
|
44
|
-
if (limits && (limits.raw !== true || !Number.isSafeInteger(maximum) || maximum < 0 || output || inputIndex !== 0 || outputIndex !== 0)) throw new RangeError("Invalid bounded raw DEFLATE options");
|
|
45
|
-
let out = output ?? new Uint8Array(limits ? Math.min(1024, maximum) : 1024);
|
|
46
|
-
if (limits && !input.length) throw new Error("unexpected EOF");
|
|
47
|
-
if (!(input.length - inputIndex)) return out;
|
|
48
|
-
const payloadStart = limits ? 0 : gzipStart(input, inputIndex);
|
|
49
|
-
if (!limits && payloadStart === input.length - 8) return out;
|
|
50
|
-
if (!limits && payloadStart > input.length - 8) throw new Error("unexpected EOF");
|
|
51
|
-
let pos = payloadStart * 8;
|
|
52
|
-
let final = 0;
|
|
53
|
-
let lengthBits = 0;
|
|
54
|
-
let distBits = 0;
|
|
55
|
-
let lengthMap;
|
|
56
|
-
let distMap;
|
|
57
|
-
const totalBits = input.length * 8;
|
|
58
|
-
function ensureSize(length) {
|
|
59
|
-
if (limits && (!Number.isSafeInteger(length) || length > maximum)) throw new RangeError("DEFLATE output byte limit exceeded");
|
|
60
|
-
if (!output && length > out.length) {
|
|
61
|
-
const old = out;
|
|
62
|
-
out = new Uint8Array(limits ? Math.min(maximum, Math.max(old.length * 2, length)) : Math.max(old.length * 2, length));
|
|
63
|
-
out.set(old);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
do {
|
|
67
|
-
if (!lengthMap) {
|
|
68
|
-
final = bits(input, pos, 1);
|
|
69
|
-
const type = bits(input, pos + 1, 3);
|
|
70
|
-
pos += 3;
|
|
71
|
-
if (!type) {
|
|
72
|
-
const s = shft(pos) + 4;
|
|
73
|
-
const l = input[s - 4] | input[s - 3] << 8;
|
|
74
|
-
if (limits && (s > input.length || ((input[s - 2] | input[s - 1] << 8) ^ l) !== 65535)) throw new Error("invalid stored block length");
|
|
75
|
-
const t = s + l;
|
|
76
|
-
if (t > input.length) throw new Error("unexpected EOF");
|
|
77
|
-
ensureSize(outputIndex + l);
|
|
78
|
-
out.set(input.subarray(s, t), outputIndex);
|
|
79
|
-
outputIndex += l;
|
|
80
|
-
pos = t * 8;
|
|
81
|
-
continue;
|
|
82
|
-
} else if (type === 1) {
|
|
83
|
-
lengthMap = fixedLengthMap;
|
|
84
|
-
distMap = fixedDistanceMap;
|
|
85
|
-
lengthBits = 9;
|
|
86
|
-
distBits = 5;
|
|
87
|
-
} else if (type === 2) {
|
|
88
|
-
const hLiteral = bits(input, pos, 31) + 257;
|
|
89
|
-
const hcLengths = bits(input, pos + 10, 15) + 4;
|
|
90
|
-
const tl = hLiteral + bits(input, pos + 5, 31) + 1;
|
|
91
|
-
pos += 14;
|
|
92
|
-
const lengthDistanceTree = new Uint8Array(tl);
|
|
93
|
-
const codeLengthTree = /* @__PURE__ */ new Uint8Array(19);
|
|
94
|
-
for (let i = 0; i < hcLengths; ++i) codeLengthTree[codeLengthIndexMap[i]] = bits(input, pos + i * 3, 7);
|
|
95
|
-
pos += hcLengths * 3;
|
|
96
|
-
const codeLengthBits = Math.max(...codeLengthTree);
|
|
97
|
-
const clbMask = (1 << codeLengthBits) - 1;
|
|
98
|
-
const codeLengthMap = huffMap(codeLengthTree, codeLengthBits, 1);
|
|
99
|
-
for (let i = 0; i < tl;) {
|
|
100
|
-
const r = codeLengthMap[bits(input, pos, clbMask)];
|
|
101
|
-
if (limits && !r) throw new Error("invalid code length");
|
|
102
|
-
pos += r & 15;
|
|
103
|
-
const symbol = r >> 4;
|
|
104
|
-
if (symbol < 16) lengthDistanceTree[i++] = symbol;
|
|
105
|
-
else {
|
|
106
|
-
let copy = 0;
|
|
107
|
-
let n = 0;
|
|
108
|
-
if (symbol === 16) {
|
|
109
|
-
if (limits && i === 0) throw new Error("invalid code length repeat");
|
|
110
|
-
n = 3 + bits(input, pos, 3);
|
|
111
|
-
pos += 2;
|
|
112
|
-
copy = lengthDistanceTree[i - 1];
|
|
113
|
-
} else if (symbol === 17) {
|
|
114
|
-
n = 3 + bits(input, pos, 7);
|
|
115
|
-
pos += 3;
|
|
116
|
-
} else if (symbol === 18) {
|
|
117
|
-
n = 11 + bits(input, pos, 127);
|
|
118
|
-
pos += 7;
|
|
119
|
-
}
|
|
120
|
-
if (limits && i + n > tl) throw new Error("invalid code length repeat");
|
|
121
|
-
while (n--) lengthDistanceTree[i++] = copy;
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
const lengthTree = lengthDistanceTree.subarray(0, hLiteral);
|
|
125
|
-
const distanceTree = lengthDistanceTree.subarray(hLiteral);
|
|
126
|
-
lengthBits = Math.max(...lengthTree);
|
|
127
|
-
distBits = Math.max(...distanceTree);
|
|
128
|
-
lengthMap = huffMap(lengthTree, lengthBits, 1);
|
|
129
|
-
distMap = huffMap(distanceTree, distBits, 1);
|
|
130
|
-
} else throw new Error("invalid block type");
|
|
131
|
-
if (pos > totalBits) throw new Error("unexpected EOF");
|
|
132
|
-
}
|
|
133
|
-
ensureSize(limits ? Math.min(maximum, outputIndex + 131072) : outputIndex + 131072);
|
|
134
|
-
const lms = (1 << lengthBits) - 1;
|
|
135
|
-
const dms = (1 << distBits) - 1;
|
|
136
|
-
for (;;) {
|
|
137
|
-
const code = lengthMap[bits16(input, pos) & lms];
|
|
138
|
-
const sym = code >> 4;
|
|
139
|
-
pos += code & 15;
|
|
140
|
-
if (pos > totalBits) throw new Error("unexpected EOF");
|
|
141
|
-
if (!code) throw new Error("invalid length/literal");
|
|
142
|
-
if (sym < 256) {
|
|
143
|
-
if (limits) ensureSize(outputIndex + 1);
|
|
144
|
-
out[outputIndex++] = sym;
|
|
145
|
-
} else if (sym === 256) {
|
|
146
|
-
lengthMap = void 0;
|
|
147
|
-
break;
|
|
148
|
-
} else {
|
|
149
|
-
let add = sym - 254;
|
|
150
|
-
if (sym > 264) {
|
|
151
|
-
const index = sym - 257;
|
|
152
|
-
const b = fixedLengthExtraBits[index];
|
|
153
|
-
add = bits(input, pos, (1 << b) - 1) + fixedLength[index];
|
|
154
|
-
pos += b;
|
|
155
|
-
}
|
|
156
|
-
if (!distMap) throw new Error("invalid distance map");
|
|
157
|
-
const d = distMap[bits16(input, pos) & dms];
|
|
158
|
-
const dsym = d >> 4;
|
|
159
|
-
if (!d) throw new Error("invalid distance");
|
|
160
|
-
if (limits && dsym > 29) throw new Error("invalid distance symbol");
|
|
161
|
-
pos += d & 15;
|
|
162
|
-
let dt = fixedDistance[dsym];
|
|
163
|
-
if (dsym > 3) {
|
|
164
|
-
const b = fixedDistanceExtraBits[dsym];
|
|
165
|
-
dt += bits16(input, pos) & (1 << b) - 1;
|
|
166
|
-
pos += b;
|
|
167
|
-
}
|
|
168
|
-
if (pos > totalBits) throw new Error("unexpected EOF");
|
|
169
|
-
const end = outputIndex + add;
|
|
170
|
-
if (outputIndex < dt) throw new Error("unexpected dictionary case");
|
|
171
|
-
ensureSize(end);
|
|
172
|
-
for (; outputIndex < end; outputIndex++) out[outputIndex] = out[outputIndex - dt];
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
if (lengthMap) final = 1;
|
|
176
|
-
} while (!final);
|
|
177
|
-
if (limits && Math.ceil(pos / 8) !== input.length) throw new Error("trailing raw DEFLATE bytes");
|
|
178
|
-
if (!limits && outputIndex < out.length) {
|
|
179
|
-
const nextBlock = Math.ceil(pos / 8) + 8;
|
|
180
|
-
gunzip(input, out, nextBlock, outputIndex);
|
|
181
|
-
}
|
|
182
|
-
if (limits && outputIndex !== out.length) return out.slice(0, outputIndex);
|
|
183
|
-
if (!output) return out.subarray(0, outputIndex);
|
|
184
|
-
return out;
|
|
185
|
-
}
|
|
186
|
-
export { gunzip };
|