7z-iterator 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +42 -0
- package/README.md +142 -0
- package/dist/cjs/FileEntry.d.cts +12 -0
- package/dist/cjs/FileEntry.d.ts +12 -0
- package/dist/cjs/FileEntry.js +147 -0
- package/dist/cjs/FileEntry.js.map +1 -0
- package/dist/cjs/SevenZipIterator.d.cts +8 -0
- package/dist/cjs/SevenZipIterator.d.ts +8 -0
- package/dist/cjs/SevenZipIterator.js +204 -0
- package/dist/cjs/SevenZipIterator.js.map +1 -0
- package/dist/cjs/index.d.cts +4 -0
- package/dist/cjs/index.d.ts +4 -0
- package/dist/cjs/index.js +40 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/lib/Lock.d.cts +11 -0
- package/dist/cjs/lib/Lock.d.ts +11 -0
- package/dist/cjs/lib/Lock.js +65 -0
- package/dist/cjs/lib/Lock.js.map +1 -0
- package/dist/cjs/lib/streamToSource.d.cts +20 -0
- package/dist/cjs/lib/streamToSource.d.ts +20 -0
- package/dist/cjs/lib/streamToSource.js +116 -0
- package/dist/cjs/lib/streamToSource.js.map +1 -0
- package/dist/cjs/nextEntry.d.cts +4 -0
- package/dist/cjs/nextEntry.d.ts +4 -0
- package/dist/cjs/nextEntry.js +102 -0
- package/dist/cjs/nextEntry.js.map +1 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/sevenz/NumberCodec.d.cts +58 -0
- package/dist/cjs/sevenz/NumberCodec.d.ts +58 -0
- package/dist/cjs/sevenz/NumberCodec.js +133 -0
- package/dist/cjs/sevenz/NumberCodec.js.map +1 -0
- package/dist/cjs/sevenz/SevenZipParser.d.cts +96 -0
- package/dist/cjs/sevenz/SevenZipParser.d.ts +96 -0
- package/dist/cjs/sevenz/SevenZipParser.js +457 -0
- package/dist/cjs/sevenz/SevenZipParser.js.map +1 -0
- package/dist/cjs/sevenz/codecs/Aes.d.cts +22 -0
- package/dist/cjs/sevenz/codecs/Aes.d.ts +22 -0
- package/dist/cjs/sevenz/codecs/Aes.js +179 -0
- package/dist/cjs/sevenz/codecs/Aes.js.map +1 -0
- package/dist/cjs/sevenz/codecs/BZip2.d.cts +14 -0
- package/dist/cjs/sevenz/codecs/BZip2.d.ts +14 -0
- package/dist/cjs/sevenz/codecs/BZip2.js +37 -0
- package/dist/cjs/sevenz/codecs/BZip2.js.map +1 -0
- package/dist/cjs/sevenz/codecs/Bcj.d.cts +15 -0
- package/dist/cjs/sevenz/codecs/Bcj.d.ts +15 -0
- package/dist/cjs/sevenz/codecs/Bcj.js +89 -0
- package/dist/cjs/sevenz/codecs/Bcj.js.map +1 -0
- package/dist/cjs/sevenz/codecs/Copy.d.cts +14 -0
- package/dist/cjs/sevenz/codecs/Copy.d.ts +14 -0
- package/dist/cjs/sevenz/codecs/Copy.js +28 -0
- package/dist/cjs/sevenz/codecs/Copy.js.map +1 -0
- package/dist/cjs/sevenz/codecs/Deflate.d.cts +14 -0
- package/dist/cjs/sevenz/codecs/Deflate.d.ts +14 -0
- package/dist/cjs/sevenz/codecs/Deflate.js +39 -0
- package/dist/cjs/sevenz/codecs/Deflate.js.map +1 -0
- package/dist/cjs/sevenz/codecs/Delta.d.cts +15 -0
- package/dist/cjs/sevenz/codecs/Delta.d.ts +15 -0
- package/dist/cjs/sevenz/codecs/Delta.js +55 -0
- package/dist/cjs/sevenz/codecs/Delta.js.map +1 -0
- package/dist/cjs/sevenz/codecs/Lzma.d.cts +14 -0
- package/dist/cjs/sevenz/codecs/Lzma.d.ts +14 -0
- package/dist/cjs/sevenz/codecs/Lzma.js +53 -0
- package/dist/cjs/sevenz/codecs/Lzma.js.map +1 -0
- package/dist/cjs/sevenz/codecs/Lzma2.d.cts +14 -0
- package/dist/cjs/sevenz/codecs/Lzma2.d.ts +14 -0
- package/dist/cjs/sevenz/codecs/Lzma2.js +160 -0
- package/dist/cjs/sevenz/codecs/Lzma2.js.map +1 -0
- package/dist/cjs/sevenz/codecs/createBufferingDecoder.d.cts +7 -0
- package/dist/cjs/sevenz/codecs/createBufferingDecoder.d.ts +7 -0
- package/dist/cjs/sevenz/codecs/createBufferingDecoder.js +36 -0
- package/dist/cjs/sevenz/codecs/createBufferingDecoder.js.map +1 -0
- package/dist/cjs/sevenz/codecs/index.d.cts +24 -0
- package/dist/cjs/sevenz/codecs/index.d.ts +24 -0
- package/dist/cjs/sevenz/codecs/index.js +128 -0
- package/dist/cjs/sevenz/codecs/index.js.map +1 -0
- package/dist/cjs/sevenz/codecs/streams.d.cts +18 -0
- package/dist/cjs/sevenz/codecs/streams.d.ts +18 -0
- package/dist/cjs/sevenz/codecs/streams.js +79 -0
- package/dist/cjs/sevenz/codecs/streams.js.map +1 -0
- package/dist/cjs/sevenz/constants.d.cts +86 -0
- package/dist/cjs/sevenz/constants.d.ts +86 -0
- package/dist/cjs/sevenz/constants.js +162 -0
- package/dist/cjs/sevenz/constants.js.map +1 -0
- package/dist/cjs/sevenz/headers.d.cts +70 -0
- package/dist/cjs/sevenz/headers.d.ts +70 -0
- package/dist/cjs/sevenz/headers.js +661 -0
- package/dist/cjs/sevenz/headers.js.map +1 -0
- package/dist/cjs/sevenz/index.d.cts +4 -0
- package/dist/cjs/sevenz/index.d.ts +4 -0
- package/dist/cjs/sevenz/index.js +33 -0
- package/dist/cjs/sevenz/index.js.map +1 -0
- package/dist/cjs/types.d.cts +37 -0
- package/dist/cjs/types.d.ts +37 -0
- package/dist/cjs/types.js +32 -0
- package/dist/cjs/types.js.map +1 -0
- package/dist/esm/FileEntry.d.ts +12 -0
- package/dist/esm/FileEntry.js +63 -0
- package/dist/esm/FileEntry.js.map +1 -0
- package/dist/esm/SevenZipIterator.d.ts +8 -0
- package/dist/esm/SevenZipIterator.js +116 -0
- package/dist/esm/SevenZipIterator.js.map +1 -0
- package/dist/esm/index.d.ts +4 -0
- package/dist/esm/index.js +3 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/lib/Lock.d.ts +11 -0
- package/dist/esm/lib/Lock.js +41 -0
- package/dist/esm/lib/Lock.js.map +1 -0
- package/dist/esm/lib/streamToSource.d.ts +20 -0
- package/dist/esm/lib/streamToSource.js +100 -0
- package/dist/esm/lib/streamToSource.js.map +1 -0
- package/dist/esm/nextEntry.d.ts +4 -0
- package/dist/esm/nextEntry.js +86 -0
- package/dist/esm/nextEntry.js.map +1 -0
- package/dist/esm/package.json +1 -0
- package/dist/esm/sevenz/NumberCodec.d.ts +58 -0
- package/dist/esm/sevenz/NumberCodec.js +138 -0
- package/dist/esm/sevenz/NumberCodec.js.map +1 -0
- package/dist/esm/sevenz/SevenZipParser.d.ts +96 -0
- package/dist/esm/sevenz/SevenZipParser.js +419 -0
- package/dist/esm/sevenz/SevenZipParser.js.map +1 -0
- package/dist/esm/sevenz/codecs/Aes.d.ts +22 -0
- package/dist/esm/sevenz/codecs/Aes.js +162 -0
- package/dist/esm/sevenz/codecs/Aes.js.map +1 -0
- package/dist/esm/sevenz/codecs/BZip2.d.ts +14 -0
- package/dist/esm/sevenz/codecs/BZip2.js +22 -0
- package/dist/esm/sevenz/codecs/BZip2.js.map +1 -0
- package/dist/esm/sevenz/codecs/Bcj.d.ts +15 -0
- package/dist/esm/sevenz/codecs/Bcj.js +75 -0
- package/dist/esm/sevenz/codecs/Bcj.js.map +1 -0
- package/dist/esm/sevenz/codecs/Copy.d.ts +14 -0
- package/dist/esm/sevenz/codecs/Copy.js +18 -0
- package/dist/esm/sevenz/codecs/Copy.js.map +1 -0
- package/dist/esm/sevenz/codecs/Deflate.d.ts +14 -0
- package/dist/esm/sevenz/codecs/Deflate.js +24 -0
- package/dist/esm/sevenz/codecs/Deflate.js.map +1 -0
- package/dist/esm/sevenz/codecs/Delta.d.ts +15 -0
- package/dist/esm/sevenz/codecs/Delta.js +41 -0
- package/dist/esm/sevenz/codecs/Delta.js.map +1 -0
- package/dist/esm/sevenz/codecs/Lzma.d.ts +14 -0
- package/dist/esm/sevenz/codecs/Lzma.js +38 -0
- package/dist/esm/sevenz/codecs/Lzma.js.map +1 -0
- package/dist/esm/sevenz/codecs/Lzma2.d.ts +14 -0
- package/dist/esm/sevenz/codecs/Lzma2.js +145 -0
- package/dist/esm/sevenz/codecs/Lzma2.js.map +1 -0
- package/dist/esm/sevenz/codecs/createBufferingDecoder.d.ts +7 -0
- package/dist/esm/sevenz/codecs/createBufferingDecoder.js +25 -0
- package/dist/esm/sevenz/codecs/createBufferingDecoder.js.map +1 -0
- package/dist/esm/sevenz/codecs/index.d.ts +24 -0
- package/dist/esm/sevenz/codecs/index.js +108 -0
- package/dist/esm/sevenz/codecs/index.js.map +1 -0
- package/dist/esm/sevenz/codecs/streams.d.ts +18 -0
- package/dist/esm/sevenz/codecs/streams.js +66 -0
- package/dist/esm/sevenz/codecs/streams.js.map +1 -0
- package/dist/esm/sevenz/constants.d.ts +86 -0
- package/dist/esm/sevenz/constants.js +131 -0
- package/dist/esm/sevenz/constants.js.map +1 -0
- package/dist/esm/sevenz/headers.d.ts +70 -0
- package/dist/esm/sevenz/headers.js +646 -0
- package/dist/esm/sevenz/headers.js.map +1 -0
- package/dist/esm/sevenz/index.d.ts +4 -0
- package/dist/esm/sevenz/index.js +5 -0
- package/dist/esm/sevenz/index.js.map +1 -0
- package/dist/esm/types.d.ts +37 -0
- package/dist/esm/types.js +2 -0
- package/dist/esm/types.js.map +1 -0
- package/package.json +77 -0
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
// Hybrid stream handling: buffers in memory up to threshold, then switches to temp file
|
|
2
|
+
import once from 'call-once-fn';
|
|
3
|
+
import { bufferFrom } from 'extract-base-iterator';
|
|
4
|
+
import fs from 'fs';
|
|
5
|
+
import mkdirp from 'mkdirp-classic';
|
|
6
|
+
import oo from 'on-one';
|
|
7
|
+
import path from 'path';
|
|
8
|
+
import { BufferSource, FileSource } from '../sevenz/SevenZipParser.js';
|
|
9
|
+
// Default memory threshold: 100 MB
|
|
10
|
+
var DEFAULT_MEMORY_THRESHOLD = 100 * 1024 * 1024;
|
|
11
|
+
/**
|
|
12
|
+
* Convert a stream to an ArchiveSource (BufferSource for small files, FileSource for large)
|
|
13
|
+
*
|
|
14
|
+
* Algorithm:
|
|
15
|
+
* 1. Buffer stream data in memory up to memoryThreshold
|
|
16
|
+
* 2. If threshold exceeded, write all buffered data to temp file and continue streaming
|
|
17
|
+
* 3. When done, return BufferSource for memory buffer or FileSource for temp file
|
|
18
|
+
*/ export default function streamToSource(stream, options, callback) {
|
|
19
|
+
var threshold = options.memoryThreshold !== undefined ? options.memoryThreshold : DEFAULT_MEMORY_THRESHOLD;
|
|
20
|
+
var tempPath = options.tempPath;
|
|
21
|
+
var chunks = [];
|
|
22
|
+
var totalSize = 0;
|
|
23
|
+
var writeStream = null;
|
|
24
|
+
var useTempFile = false;
|
|
25
|
+
var end = once(callback);
|
|
26
|
+
function onData(chunk) {
|
|
27
|
+
// Convert string chunks to Buffer
|
|
28
|
+
var buf = typeof chunk === 'string' ? bufferFrom(chunk) : chunk;
|
|
29
|
+
totalSize += buf.length;
|
|
30
|
+
if (!useTempFile && totalSize <= threshold) {
|
|
31
|
+
// Still under threshold - buffer in memory
|
|
32
|
+
chunks.push(buf);
|
|
33
|
+
} else if (!useTempFile) {
|
|
34
|
+
// Just exceeded threshold - switch to temp file
|
|
35
|
+
useTempFile = true;
|
|
36
|
+
if (!tempPath) {
|
|
37
|
+
end(new Error('memoryThreshold exceeded but no tempPath provided'));
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
mkdirp.sync(path.dirname(tempPath));
|
|
41
|
+
writeStream = fs.createWriteStream(tempPath);
|
|
42
|
+
// Write all buffered chunks to temp file
|
|
43
|
+
for(var i = 0; i < chunks.length; i++){
|
|
44
|
+
writeStream.write(chunks[i]);
|
|
45
|
+
}
|
|
46
|
+
chunks = []; // Allow GC
|
|
47
|
+
// Write current chunk
|
|
48
|
+
writeStream.write(buf);
|
|
49
|
+
} else {
|
|
50
|
+
// Already using temp file - write directly
|
|
51
|
+
if (writeStream) {
|
|
52
|
+
writeStream.write(buf);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function onEnd() {
|
|
57
|
+
if (useTempFile && writeStream && tempPath) {
|
|
58
|
+
// Close write stream, then open for reading
|
|
59
|
+
var filePath = tempPath; // Capture for closure
|
|
60
|
+
writeStream.end(()=>{
|
|
61
|
+
fs.open(filePath, 'r', (err, fd)=>{
|
|
62
|
+
if (err) return end(err);
|
|
63
|
+
fs.stat(filePath, (statErr, stats)=>{
|
|
64
|
+
if (statErr) {
|
|
65
|
+
fs.closeSync(fd);
|
|
66
|
+
return end(statErr);
|
|
67
|
+
}
|
|
68
|
+
end(null, {
|
|
69
|
+
source: new FileSource(fd, stats.size),
|
|
70
|
+
fd: fd,
|
|
71
|
+
tempPath: filePath
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
} else {
|
|
77
|
+
// Use memory buffer
|
|
78
|
+
var fullBuffer = Buffer.concat(chunks);
|
|
79
|
+
end(null, {
|
|
80
|
+
source: new BufferSource(fullBuffer)
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
function onError(err) {
|
|
85
|
+
// Clean up if we created a temp file
|
|
86
|
+
if (writeStream) {
|
|
87
|
+
writeStream.end();
|
|
88
|
+
}
|
|
89
|
+
end(err);
|
|
90
|
+
}
|
|
91
|
+
stream.on('data', onData);
|
|
92
|
+
oo(stream, [
|
|
93
|
+
'error'
|
|
94
|
+
], onError);
|
|
95
|
+
oo(stream, [
|
|
96
|
+
'end',
|
|
97
|
+
'close',
|
|
98
|
+
'finish'
|
|
99
|
+
], onEnd);
|
|
100
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/iterators/7z-iterator/src/lib/streamToSource.ts"],"sourcesContent":["// Hybrid stream handling: buffers in memory up to threshold, then switches to temp file\nimport once from 'call-once-fn';\nimport { bufferFrom } from 'extract-base-iterator';\nimport fs from 'fs';\nimport mkdirp from 'mkdirp-classic';\nimport oo from 'on-one';\nimport path from 'path';\nimport { BufferSource, FileSource } from '../sevenz/SevenZipParser.ts';\n\n// Default memory threshold: 100 MB\nvar DEFAULT_MEMORY_THRESHOLD = 100 * 1024 * 1024;\n\nexport interface StreamToSourceOptions {\n memoryThreshold?: number;\n tempPath?: string;\n}\n\nexport interface SourceResult {\n source: BufferSource | FileSource;\n fd?: number; // Set if FileSource was used (caller must close)\n tempPath?: string; // Set if temp file was created (caller must clean up)\n}\n\nexport type Callback = (error?: Error, result?: SourceResult) => void;\n\n/**\n * Convert a stream to an ArchiveSource (BufferSource for small files, FileSource for large)\n *\n * Algorithm:\n * 1. Buffer stream data in memory up to memoryThreshold\n * 2. If threshold exceeded, write all buffered data to temp file and continue streaming\n * 3. When done, return BufferSource for memory buffer or FileSource for temp file\n */\nexport default function streamToSource(stream: NodeJS.ReadableStream, options: StreamToSourceOptions, callback: Callback): void {\n var threshold = options.memoryThreshold !== undefined ? options.memoryThreshold : DEFAULT_MEMORY_THRESHOLD;\n var tempPath = options.tempPath;\n\n var chunks: Buffer[] = [];\n var totalSize = 0;\n var writeStream: fs.WriteStream | null = null;\n var useTempFile = false;\n\n var end = once(callback);\n\n function onData(chunk: Buffer | string): void {\n // Convert string chunks to Buffer\n var buf = typeof chunk === 'string' ? bufferFrom(chunk) : chunk;\n totalSize += buf.length;\n\n if (!useTempFile && totalSize <= threshold) {\n // Still under threshold - buffer in memory\n chunks.push(buf);\n } else if (!useTempFile) {\n // Just exceeded threshold - switch to temp file\n useTempFile = true;\n\n if (!tempPath) {\n end(new Error('memoryThreshold exceeded but no tempPath provided'));\n return;\n }\n\n mkdirp.sync(path.dirname(tempPath));\n writeStream = fs.createWriteStream(tempPath);\n\n // Write all buffered chunks to temp file\n for (var i = 0; i < chunks.length; i++) {\n writeStream.write(chunks[i]);\n }\n chunks = []; // Allow GC\n\n // Write current chunk\n writeStream.write(buf);\n } else {\n // Already using temp file - write directly\n if (writeStream) {\n writeStream.write(buf);\n }\n }\n }\n\n function onEnd(): void {\n if (useTempFile && writeStream && tempPath) {\n // Close write stream, then open for reading\n var filePath = tempPath; // Capture for closure\n writeStream.end(() => {\n fs.open(filePath, 'r', (err, fd) => {\n if (err) return end(err);\n fs.stat(filePath, (statErr, stats) => {\n if (statErr) {\n fs.closeSync(fd);\n return end(statErr);\n }\n end(null, {\n source: new FileSource(fd, stats.size),\n fd: fd,\n tempPath: filePath,\n });\n });\n });\n });\n } else {\n // Use memory buffer\n var fullBuffer = Buffer.concat(chunks);\n end(null, {\n source: new BufferSource(fullBuffer),\n });\n }\n }\n\n function onError(err: Error): void {\n // Clean up if we created a temp file\n if (writeStream) {\n writeStream.end();\n }\n end(err);\n }\n\n stream.on('data', onData);\n oo(stream, ['error'], onError);\n oo(stream, ['end', 'close', 'finish'], onEnd);\n}\n"],"names":["once","bufferFrom","fs","mkdirp","oo","path","BufferSource","FileSource","DEFAULT_MEMORY_THRESHOLD","streamToSource","stream","options","callback","threshold","memoryThreshold","undefined","tempPath","chunks","totalSize","writeStream","useTempFile","end","onData","chunk","buf","length","push","Error","sync","dirname","createWriteStream","i","write","onEnd","filePath","open","err","fd","stat","statErr","stats","closeSync","source","size","fullBuffer","Buffer","concat","onError","on"],"mappings":"AAAA,wFAAwF;AACxF,OAAOA,UAAU,eAAe;AAChC,SAASC,UAAU,QAAQ,wBAAwB;AACnD,OAAOC,QAAQ,KAAK;AACpB,OAAOC,YAAY,iBAAiB;AACpC,OAAOC,QAAQ,SAAS;AACxB,OAAOC,UAAU,OAAO;AACxB,SAASC,YAAY,EAAEC,UAAU,QAAQ,8BAA8B;AAEvE,mCAAmC;AACnC,IAAIC,2BAA2B,MAAM,OAAO;AAe5C;;;;;;;CAOC,GACD,eAAe,SAASC,eAAeC,MAA6B,EAAEC,OAA8B,EAAEC,QAAkB;IACtH,IAAIC,YAAYF,QAAQG,eAAe,KAAKC,YAAYJ,QAAQG,eAAe,GAAGN;IAClF,IAAIQ,WAAWL,QAAQK,QAAQ;IAE/B,IAAIC,SAAmB,EAAE;IACzB,IAAIC,YAAY;IAChB,IAAIC,cAAqC;IACzC,IAAIC,cAAc;IAElB,IAAIC,MAAMrB,KAAKY;IAEf,SAASU,OAAOC,KAAsB;QACpC,kCAAkC;QAClC,IAAIC,MAAM,OAAOD,UAAU,WAAWtB,WAAWsB,SAASA;QAC1DL,aAAaM,IAAIC,MAAM;QAEvB,IAAI,CAACL,eAAeF,aAAaL,WAAW;YAC1C,2CAA2C;YAC3CI,OAAOS,IAAI,CAACF;QACd,OAAO,IAAI,CAACJ,aAAa;YACvB,gDAAgD;YAChDA,cAAc;YAEd,IAAI,CAACJ,UAAU;gBACbK,IAAI,IAAIM,MAAM;gBACd;YACF;YAEAxB,OAAOyB,IAAI,CAACvB,KAAKwB,OAAO,CAACb;YACzBG,cAAcjB,GAAG4B,iBAAiB,CAACd;YAEnC,yCAAyC;YACzC,IAAK,IAAIe,IAAI,GAAGA,IAAId,OAAOQ,MAAM,EAAEM,IAAK;gBACtCZ,YAAYa,KAAK,CAACf,MAAM,CAACc,EAAE;YAC7B;YACAd,SAAS,EAAE,EAAE,WAAW;YAExB,sBAAsB;YACtBE,YAAYa,KAAK,CAACR;QACpB,OAAO;YACL,2CAA2C;YAC3C,IAAIL,aAAa;gBACfA,YAAYa,KAAK,CAACR;YACpB;QACF;IACF;IAEA,SAASS;QACP,IAAIb,eAAeD,eAAeH,UAAU;YAC1C,4CAA4C;YAC5C,IAAIkB,WAAWlB,UAAU,sBAAsB;YAC/CG,YAAYE,GAAG,CAAC;gBACdnB,GAAGiC,IAAI,CAACD,UAAU,KAAK,CAACE,KAAKC;oBAC3B,IAAID,KAAK,OAAOf,IAAIe;oBACpBlC,GAAGoC,IAAI,CAACJ,UAAU,CAACK,SAASC;wBAC1B,IAAID,SAAS;4BACXrC,GAAGuC,SAAS,CAACJ;4BACb,OAAOhB,IAAIkB;wBACb;wBACAlB,IAAI,MAAM;4BACRqB,QAAQ,IAAInC,WAAW8B,IAAIG,MAAMG,IAAI;4BACrCN,IAAIA;4BACJrB,UAAUkB;wBACZ;oBACF;gBACF;YACF;QACF,OAAO;YACL,oBAAoB;YACpB,IAAIU,aAAaC,OAAOC,MAAM,CAAC7B;YAC/BI,IAAI,MAAM;gBACRqB,QAAQ,IAAIpC,aAAasC;YAC3B;QACF;IACF;IAEA,SAASG,QAAQX,GAAU;QACzB,qCAAqC;QACrC,IAAIjB,aAAa;YACfA,YAAYE,GAAG;QACjB;QACAA,IAAIe;IACN;IAEA1B,OAAOsC,EAAE,CAAC,QAAQ1B;IAClBlB,GAAGM,QAAQ;QAAC;KAAQ,EAAEqC;IACtB3C,GAAGM,QAAQ;QAAC;QAAO;QAAS;KAAS,EAAEuB;AACzC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type SevenZipIterator from './SevenZipIterator.js';
|
|
2
|
+
import type { Entry, EntryCallback } from './types.js';
|
|
3
|
+
export type NextCallback = (error?: Error, entry?: Entry) => undefined;
|
|
4
|
+
export default function nextEntry<_T>(iterator: SevenZipIterator, callback: EntryCallback): undefined;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import once from 'call-once-fn';
|
|
2
|
+
import { DirectoryEntry, SymbolicLinkEntry } from 'extract-base-iterator';
|
|
3
|
+
import compact from 'lodash.compact';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import FileEntry from './FileEntry.js';
|
|
6
|
+
export default function nextEntry(iterator, callback) {
|
|
7
|
+
if (!iterator.iterator) {
|
|
8
|
+
callback(new Error('iterator missing'));
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
var entry = null;
|
|
12
|
+
entry = iterator.iterator.next();
|
|
13
|
+
var nextCallback = once((err, entry)=>{
|
|
14
|
+
// keep processing
|
|
15
|
+
if (entry) iterator.push(nextEntry);
|
|
16
|
+
err ? callback(err) : callback(null, entry ? {
|
|
17
|
+
done: false,
|
|
18
|
+
value: entry
|
|
19
|
+
} : {
|
|
20
|
+
done: true,
|
|
21
|
+
value: null
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
// done: signal iteration is complete
|
|
25
|
+
if (iterator.isDone() || !entry) return callback(null, {
|
|
26
|
+
done: true,
|
|
27
|
+
value: null
|
|
28
|
+
});
|
|
29
|
+
// Skip anti-files (these mark files to delete in delta archives)
|
|
30
|
+
if (entry.isAntiFile) {
|
|
31
|
+
iterator.push(nextEntry);
|
|
32
|
+
return callback(null, null);
|
|
33
|
+
}
|
|
34
|
+
// Determine type from entry
|
|
35
|
+
var type = entry.type;
|
|
36
|
+
// Default modes (decimal values for Node 0.8 compatibility)
|
|
37
|
+
// 0o755 = 493, 0o644 = 420
|
|
38
|
+
var defaultMode = type === 'directory' ? 493 : 420;
|
|
39
|
+
// Build attributes from 7z entry
|
|
40
|
+
// mtime must be timestamp (number) for FileAttributes compatibility
|
|
41
|
+
var mtimeDate = entry.mtime || new Date();
|
|
42
|
+
var attributes = {
|
|
43
|
+
path: compact(entry.path.split(path.sep)).join(path.sep),
|
|
44
|
+
basename: entry.name,
|
|
45
|
+
mtime: mtimeDate.getTime(),
|
|
46
|
+
mode: entry.mode !== undefined ? entry.mode : defaultMode
|
|
47
|
+
};
|
|
48
|
+
switch(type){
|
|
49
|
+
case 'directory':
|
|
50
|
+
attributes.type = 'directory';
|
|
51
|
+
return nextCallback(null, new DirectoryEntry(attributes));
|
|
52
|
+
case 'link':
|
|
53
|
+
{
|
|
54
|
+
// For symlinks, the file content IS the symlink target path
|
|
55
|
+
// Read the content to get the linkpath for SymbolicLinkEntry
|
|
56
|
+
var parser = iterator.iterator.getParser();
|
|
57
|
+
var stream = parser.getEntryStream(entry);
|
|
58
|
+
var chunks = [];
|
|
59
|
+
stream.on('data', (chunk)=>{
|
|
60
|
+
chunks.push(chunk);
|
|
61
|
+
});
|
|
62
|
+
stream.on('end', ()=>{
|
|
63
|
+
var linkpath = Buffer.concat(chunks).toString('utf8');
|
|
64
|
+
var linkAttributes = {
|
|
65
|
+
path: attributes.path,
|
|
66
|
+
mtime: attributes.mtime,
|
|
67
|
+
mode: attributes.mode,
|
|
68
|
+
linkpath: linkpath
|
|
69
|
+
};
|
|
70
|
+
nextCallback(null, new SymbolicLinkEntry(linkAttributes));
|
|
71
|
+
});
|
|
72
|
+
stream.on('error', (err)=>{
|
|
73
|
+
nextCallback(err);
|
|
74
|
+
});
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
case 'file':
|
|
78
|
+
{
|
|
79
|
+
attributes.type = 'file';
|
|
80
|
+
attributes.size = entry.size;
|
|
81
|
+
var parser2 = iterator.iterator.getParser();
|
|
82
|
+
return nextCallback(null, new FileEntry(attributes, entry, parser2, iterator.lock));
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return callback(new Error(`Unrecognized entry type: ${type}`));
|
|
86
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/iterators/7z-iterator/src/nextEntry.ts"],"sourcesContent":["import once from 'call-once-fn';\nimport { type DirectoryAttributes, DirectoryEntry, type FileAttributes, type LinkAttributes, SymbolicLinkEntry } from 'extract-base-iterator';\nimport compact from 'lodash.compact';\nimport path from 'path';\nimport FileEntry from './FileEntry.ts';\nimport type SevenZipIterator from './SevenZipIterator.ts';\nimport type { SevenZipEntry } from './sevenz/SevenZipParser.ts';\nimport type { Entry, EntryCallback } from './types.ts';\n\nexport type NextCallback = (error?: Error, entry?: Entry) => undefined;\n\n// Entry attributes object that gets mutated in switch - union of possible shapes\n// mtime is number for FileAttributes compatibility (timestamp in ms)\ntype EntryAttributesBuilder = {\n path: string;\n basename: string;\n mtime: number;\n mode: number;\n type?: 'file' | 'directory';\n size?: number;\n};\n\nexport default function nextEntry<_T>(iterator: SevenZipIterator, callback: EntryCallback): undefined {\n if (!iterator.iterator) {\n callback(new Error('iterator missing'));\n return;\n }\n\n var entry: SevenZipEntry | null = null;\n entry = iterator.iterator.next();\n\n var nextCallback = once((err?: Error, entry?: Entry) => {\n // keep processing\n if (entry) iterator.push(nextEntry);\n err ? callback(err) : callback(null, entry ? { done: false, value: entry } : { done: true, value: null });\n }) as NextCallback;\n\n // done: signal iteration is complete\n if (iterator.isDone() || !entry) return callback(null, { done: true, value: null });\n\n // Skip anti-files (these mark files to delete in delta archives)\n if (entry.isAntiFile) {\n iterator.push(nextEntry);\n return callback(null, null);\n }\n\n // Determine type from entry\n var type = entry.type;\n\n // Default modes (decimal values for Node 0.8 compatibility)\n // 0o755 = 493, 0o644 = 420\n var defaultMode = type === 'directory' ? 493 : 420;\n\n // Build attributes from 7z entry\n // mtime must be timestamp (number) for FileAttributes compatibility\n var mtimeDate = entry.mtime || new Date();\n var attributes: EntryAttributesBuilder = {\n path: compact(entry.path.split(path.sep)).join(path.sep),\n basename: entry.name,\n mtime: mtimeDate.getTime(),\n mode: entry.mode !== undefined ? entry.mode : defaultMode,\n };\n\n switch (type) {\n case 'directory':\n attributes.type = 'directory';\n return nextCallback(null, new DirectoryEntry(attributes as DirectoryAttributes));\n\n case 'link': {\n // For symlinks, the file content IS the symlink target path\n // Read the content to get the linkpath for SymbolicLinkEntry\n var parser = iterator.iterator.getParser();\n var stream = parser.getEntryStream(entry);\n var chunks: Buffer[] = [];\n\n stream.on('data', (chunk: Buffer) => {\n chunks.push(chunk);\n });\n stream.on('end', () => {\n var linkpath = Buffer.concat(chunks).toString('utf8');\n\n var linkAttributes: LinkAttributes = {\n path: attributes.path,\n mtime: attributes.mtime,\n mode: attributes.mode,\n linkpath: linkpath,\n };\n\n nextCallback(null, new SymbolicLinkEntry(linkAttributes));\n });\n stream.on('error', (err: Error) => {\n nextCallback(err);\n });\n return;\n }\n\n case 'file': {\n attributes.type = 'file';\n attributes.size = entry.size;\n var parser2 = iterator.iterator.getParser();\n return nextCallback(null, new FileEntry(attributes as FileAttributes, entry, parser2, iterator.lock));\n }\n }\n\n return callback(new Error(`Unrecognized entry type: ${type}`));\n}\n"],"names":["once","DirectoryEntry","SymbolicLinkEntry","compact","path","FileEntry","nextEntry","iterator","callback","Error","entry","next","nextCallback","err","push","done","value","isDone","isAntiFile","type","defaultMode","mtimeDate","mtime","Date","attributes","split","sep","join","basename","name","getTime","mode","undefined","parser","getParser","stream","getEntryStream","chunks","on","chunk","linkpath","Buffer","concat","toString","linkAttributes","size","parser2","lock"],"mappings":"AAAA,OAAOA,UAAU,eAAe;AAChC,SAAmCC,cAAc,EAA4CC,iBAAiB,QAAQ,wBAAwB;AAC9I,OAAOC,aAAa,iBAAiB;AACrC,OAAOC,UAAU,OAAO;AACxB,OAAOC,eAAe,iBAAiB;AAkBvC,eAAe,SAASC,UAAcC,QAA0B,EAAEC,QAAuB;IACvF,IAAI,CAACD,SAASA,QAAQ,EAAE;QACtBC,SAAS,IAAIC,MAAM;QACnB;IACF;IAEA,IAAIC,QAA8B;IAClCA,QAAQH,SAASA,QAAQ,CAACI,IAAI;IAE9B,IAAIC,eAAeZ,KAAK,CAACa,KAAaH;QACpC,kBAAkB;QAClB,IAAIA,OAAOH,SAASO,IAAI,CAACR;QACzBO,MAAML,SAASK,OAAOL,SAAS,MAAME,QAAQ;YAAEK,MAAM;YAAOC,OAAON;QAAM,IAAI;YAAEK,MAAM;YAAMC,OAAO;QAAK;IACzG;IAEA,qCAAqC;IACrC,IAAIT,SAASU,MAAM,MAAM,CAACP,OAAO,OAAOF,SAAS,MAAM;QAAEO,MAAM;QAAMC,OAAO;IAAK;IAEjF,iEAAiE;IACjE,IAAIN,MAAMQ,UAAU,EAAE;QACpBX,SAASO,IAAI,CAACR;QACd,OAAOE,SAAS,MAAM;IACxB;IAEA,4BAA4B;IAC5B,IAAIW,OAAOT,MAAMS,IAAI;IAErB,4DAA4D;IAC5D,2BAA2B;IAC3B,IAAIC,cAAcD,SAAS,cAAc,MAAM;IAE/C,iCAAiC;IACjC,oEAAoE;IACpE,IAAIE,YAAYX,MAAMY,KAAK,IAAI,IAAIC;IACnC,IAAIC,aAAqC;QACvCpB,MAAMD,QAAQO,MAAMN,IAAI,CAACqB,KAAK,CAACrB,KAAKsB,GAAG,GAAGC,IAAI,CAACvB,KAAKsB,GAAG;QACvDE,UAAUlB,MAAMmB,IAAI;QACpBP,OAAOD,UAAUS,OAAO;QACxBC,MAAMrB,MAAMqB,IAAI,KAAKC,YAAYtB,MAAMqB,IAAI,GAAGX;IAChD;IAEA,OAAQD;QACN,KAAK;YACHK,WAAWL,IAAI,GAAG;YAClB,OAAOP,aAAa,MAAM,IAAIX,eAAeuB;QAE/C,KAAK;YAAQ;gBACX,4DAA4D;gBAC5D,6DAA6D;gBAC7D,IAAIS,SAAS1B,SAASA,QAAQ,CAAC2B,SAAS;gBACxC,IAAIC,SAASF,OAAOG,cAAc,CAAC1B;gBACnC,IAAI2B,SAAmB,EAAE;gBAEzBF,OAAOG,EAAE,CAAC,QAAQ,CAACC;oBACjBF,OAAOvB,IAAI,CAACyB;gBACd;gBACAJ,OAAOG,EAAE,CAAC,OAAO;oBACf,IAAIE,WAAWC,OAAOC,MAAM,CAACL,QAAQM,QAAQ,CAAC;oBAE9C,IAAIC,iBAAiC;wBACnCxC,MAAMoB,WAAWpB,IAAI;wBACrBkB,OAAOE,WAAWF,KAAK;wBACvBS,MAAMP,WAAWO,IAAI;wBACrBS,UAAUA;oBACZ;oBAEA5B,aAAa,MAAM,IAAIV,kBAAkB0C;gBAC3C;gBACAT,OAAOG,EAAE,CAAC,SAAS,CAACzB;oBAClBD,aAAaC;gBACf;gBACA;YACF;QAEA,KAAK;YAAQ;gBACXW,WAAWL,IAAI,GAAG;gBAClBK,WAAWqB,IAAI,GAAGnC,MAAMmC,IAAI;gBAC5B,IAAIC,UAAUvC,SAASA,QAAQ,CAAC2B,SAAS;gBACzC,OAAOtB,aAAa,MAAM,IAAIP,UAAUmB,YAA8Bd,OAAOoC,SAASvC,SAASwC,IAAI;YACrG;IACF;IAEA,OAAOvC,SAAS,IAAIC,MAAM,CAAC,yBAAyB,EAAEU,MAAM;AAC9D"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{ "type": "module" }
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
export interface NumberReadResult {
|
|
2
|
+
value: number;
|
|
3
|
+
bytesRead: number;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Read a variable-length encoded number from a buffer
|
|
7
|
+
* @param buf - Buffer containing encoded number
|
|
8
|
+
* @param offset - Offset to start reading from
|
|
9
|
+
* @returns Object with value and number of bytes consumed
|
|
10
|
+
*/
|
|
11
|
+
export declare function readNumber(buf: Buffer, offset: number): NumberReadResult;
|
|
12
|
+
/**
|
|
13
|
+
* Read a raw 64-bit little-endian number (used in some fixed-size fields)
|
|
14
|
+
* @param buf - Buffer containing the number
|
|
15
|
+
* @param offset - Offset to start reading from
|
|
16
|
+
* @returns The number value
|
|
17
|
+
*/
|
|
18
|
+
export declare function readRawNumber(buf: Buffer, offset: number): number;
|
|
19
|
+
/**
|
|
20
|
+
* Calculate the encoded size of a number
|
|
21
|
+
* @param value - The number to encode
|
|
22
|
+
* @returns Number of bytes needed to encode the value
|
|
23
|
+
*/
|
|
24
|
+
export declare function encodedSize(value: number): number;
|
|
25
|
+
/**
|
|
26
|
+
* Read a boolean encoded as a single byte
|
|
27
|
+
* @param buf - Buffer to read from
|
|
28
|
+
* @param offset - Offset to read from
|
|
29
|
+
* @returns true if byte is non-zero
|
|
30
|
+
*/
|
|
31
|
+
export declare function readBoolean(buf: Buffer, offset: number): boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Read a "defined" bitmask for an array of items.
|
|
34
|
+
* Used when some items in a list have optional values.
|
|
35
|
+
*
|
|
36
|
+
* Format: If "allDefined" byte is 0, a bitmask follows indicating which items have values.
|
|
37
|
+
* If "allDefined" byte is non-zero, all items are defined.
|
|
38
|
+
*
|
|
39
|
+
* @param buf - Buffer to read from
|
|
40
|
+
* @param offset - Offset to start reading
|
|
41
|
+
* @param count - Number of items
|
|
42
|
+
* @returns Object with defined array and bytes consumed
|
|
43
|
+
*/
|
|
44
|
+
export declare function readDefinedVector(buf: Buffer, offset: number, count: number): {
|
|
45
|
+
defined: boolean[];
|
|
46
|
+
bytesRead: number;
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Read an array of variable-length numbers
|
|
50
|
+
* @param buf - Buffer to read from
|
|
51
|
+
* @param offset - Offset to start reading
|
|
52
|
+
* @param count - Number of items to read
|
|
53
|
+
* @returns Object with values array and bytes consumed
|
|
54
|
+
*/
|
|
55
|
+
export declare function readNumberArray(buf: Buffer, offset: number, count: number): {
|
|
56
|
+
values: number[];
|
|
57
|
+
bytesRead: number;
|
|
58
|
+
};
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
// Variable-length integer encoding for 7z format
|
|
2
|
+
// Reference: https://py7zr.readthedocs.io/en/latest/archive_format.html
|
|
3
|
+
//
|
|
4
|
+
// 7z uses a space-efficient encoding where the first byte determines length:
|
|
5
|
+
// 0xxxxxxx -> 1 byte (0-127)
|
|
6
|
+
// 10xxxxxx xxxxxxxx -> 2 bytes (0-16383)
|
|
7
|
+
// 110xxxxx + 2 bytes -> 3 bytes
|
|
8
|
+
// 1110xxxx + 3 bytes -> 4 bytes
|
|
9
|
+
// 11110xxx + 4 bytes -> 5 bytes
|
|
10
|
+
// 111110xx + 5 bytes -> 6 bytes
|
|
11
|
+
// 1111110x + 6 bytes -> 7 bytes
|
|
12
|
+
// 11111110 + 7 bytes -> 8 bytes
|
|
13
|
+
// 11111111 + 8 bytes -> 9 bytes (full 64-bit)
|
|
14
|
+
//
|
|
15
|
+
// NOTE: Returns JavaScript number which is accurate up to 2^53 - 1 (~9 PB).
|
|
16
|
+
// This covers all practical file sizes.
|
|
17
|
+
import { readUInt64LE } from 'extract-base-iterator';
|
|
18
|
+
/**
|
|
19
|
+
* Read a variable-length encoded number from a buffer
|
|
20
|
+
* @param buf - Buffer containing encoded number
|
|
21
|
+
* @param offset - Offset to start reading from
|
|
22
|
+
* @returns Object with value and number of bytes consumed
|
|
23
|
+
*/ export function readNumber(buf, offset) {
|
|
24
|
+
var firstByte = buf[offset];
|
|
25
|
+
// Count leading 1 bits to determine extra bytes
|
|
26
|
+
var mask = 0x80;
|
|
27
|
+
var extraBytes = 0;
|
|
28
|
+
while((firstByte & mask) !== 0 && extraBytes < 8){
|
|
29
|
+
extraBytes++;
|
|
30
|
+
mask = mask >>> 1;
|
|
31
|
+
}
|
|
32
|
+
// Special case: all 8 bits set means 8 extra bytes
|
|
33
|
+
if (extraBytes === 8) {
|
|
34
|
+
// Full 64-bit value follows
|
|
35
|
+
return {
|
|
36
|
+
value: readUInt64LE(buf, offset + 1),
|
|
37
|
+
bytesRead: 9
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
// Mask off the length bits from first byte
|
|
41
|
+
var value = firstByte & (mask - 1 | mask);
|
|
42
|
+
// Add remaining bytes (big-endian order)
|
|
43
|
+
for(var i = 0; i < extraBytes; i++){
|
|
44
|
+
value = value * 256 + buf[offset + 1 + i];
|
|
45
|
+
}
|
|
46
|
+
return {
|
|
47
|
+
value: value,
|
|
48
|
+
bytesRead: 1 + extraBytes
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Read a raw 64-bit little-endian number (used in some fixed-size fields)
|
|
53
|
+
* @param buf - Buffer containing the number
|
|
54
|
+
* @param offset - Offset to start reading from
|
|
55
|
+
* @returns The number value
|
|
56
|
+
*/ export function readRawNumber(buf, offset) {
|
|
57
|
+
return readUInt64LE(buf, offset);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Calculate the encoded size of a number
|
|
61
|
+
* @param value - The number to encode
|
|
62
|
+
* @returns Number of bytes needed to encode the value
|
|
63
|
+
*/ export function encodedSize(value) {
|
|
64
|
+
if (value < 0x80) return 1; // 7 bits
|
|
65
|
+
if (value < 0x4000) return 2; // 14 bits
|
|
66
|
+
if (value < 0x200000) return 3; // 21 bits
|
|
67
|
+
if (value < 0x10000000) return 4; // 28 bits
|
|
68
|
+
if (value < 0x800000000) return 5; // 35 bits
|
|
69
|
+
if (value < 0x40000000000) return 6; // 42 bits
|
|
70
|
+
if (value < 0x2000000000000) return 7; // 49 bits
|
|
71
|
+
// 2^56 = 72057594037927936 (use calculated value to avoid precision loss)
|
|
72
|
+
if (value < 72057594037927936) return 8; // 56 bits
|
|
73
|
+
return 9; // 64 bits
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Read a boolean encoded as a single byte
|
|
77
|
+
* @param buf - Buffer to read from
|
|
78
|
+
* @param offset - Offset to read from
|
|
79
|
+
* @returns true if byte is non-zero
|
|
80
|
+
*/ export function readBoolean(buf, offset) {
|
|
81
|
+
return buf[offset] !== 0;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Read a "defined" bitmask for an array of items.
|
|
85
|
+
* Used when some items in a list have optional values.
|
|
86
|
+
*
|
|
87
|
+
* Format: If "allDefined" byte is 0, a bitmask follows indicating which items have values.
|
|
88
|
+
* If "allDefined" byte is non-zero, all items are defined.
|
|
89
|
+
*
|
|
90
|
+
* @param buf - Buffer to read from
|
|
91
|
+
* @param offset - Offset to start reading
|
|
92
|
+
* @param count - Number of items
|
|
93
|
+
* @returns Object with defined array and bytes consumed
|
|
94
|
+
*/ export function readDefinedVector(buf, offset, count) {
|
|
95
|
+
var allDefined = buf[offset] !== 0;
|
|
96
|
+
var bytesRead = 1;
|
|
97
|
+
var defined = [];
|
|
98
|
+
if (allDefined) {
|
|
99
|
+
// All items are defined
|
|
100
|
+
for(var i = 0; i < count; i++){
|
|
101
|
+
defined.push(true);
|
|
102
|
+
}
|
|
103
|
+
} else {
|
|
104
|
+
// Read bitmask
|
|
105
|
+
var bitsNeeded = count;
|
|
106
|
+
var bytesNeeded = Math.ceil(bitsNeeded / 8);
|
|
107
|
+
for(var byteIdx = 0; byteIdx < bytesNeeded; byteIdx++){
|
|
108
|
+
var byte = buf[offset + 1 + byteIdx];
|
|
109
|
+
for(var bit = 7; bit >= 0 && defined.length < count; bit--){
|
|
110
|
+
defined.push((byte & 1 << bit) !== 0);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
bytesRead += bytesNeeded;
|
|
114
|
+
}
|
|
115
|
+
return {
|
|
116
|
+
defined: defined,
|
|
117
|
+
bytesRead: bytesRead
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Read an array of variable-length numbers
|
|
122
|
+
* @param buf - Buffer to read from
|
|
123
|
+
* @param offset - Offset to start reading
|
|
124
|
+
* @param count - Number of items to read
|
|
125
|
+
* @returns Object with values array and bytes consumed
|
|
126
|
+
*/ export function readNumberArray(buf, offset, count) {
|
|
127
|
+
var values = [];
|
|
128
|
+
var totalBytesRead = 0;
|
|
129
|
+
for(var i = 0; i < count; i++){
|
|
130
|
+
var result = readNumber(buf, offset + totalBytesRead);
|
|
131
|
+
values.push(result.value);
|
|
132
|
+
totalBytesRead += result.bytesRead;
|
|
133
|
+
}
|
|
134
|
+
return {
|
|
135
|
+
values: values,
|
|
136
|
+
bytesRead: totalBytesRead
|
|
137
|
+
};
|
|
138
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/iterators/7z-iterator/src/sevenz/NumberCodec.ts"],"sourcesContent":["// Variable-length integer encoding for 7z format\n// Reference: https://py7zr.readthedocs.io/en/latest/archive_format.html\n//\n// 7z uses a space-efficient encoding where the first byte determines length:\n// 0xxxxxxx -> 1 byte (0-127)\n// 10xxxxxx xxxxxxxx -> 2 bytes (0-16383)\n// 110xxxxx + 2 bytes -> 3 bytes\n// 1110xxxx + 3 bytes -> 4 bytes\n// 11110xxx + 4 bytes -> 5 bytes\n// 111110xx + 5 bytes -> 6 bytes\n// 1111110x + 6 bytes -> 7 bytes\n// 11111110 + 7 bytes -> 8 bytes\n// 11111111 + 8 bytes -> 9 bytes (full 64-bit)\n//\n// NOTE: Returns JavaScript number which is accurate up to 2^53 - 1 (~9 PB).\n// This covers all practical file sizes.\n\nimport { readUInt64LE } from 'extract-base-iterator';\n\nexport interface NumberReadResult {\n value: number;\n bytesRead: number;\n}\n\n/**\n * Read a variable-length encoded number from a buffer\n * @param buf - Buffer containing encoded number\n * @param offset - Offset to start reading from\n * @returns Object with value and number of bytes consumed\n */\nexport function readNumber(buf: Buffer, offset: number): NumberReadResult {\n var firstByte = buf[offset];\n\n // Count leading 1 bits to determine extra bytes\n var mask = 0x80;\n var extraBytes = 0;\n\n while ((firstByte & mask) !== 0 && extraBytes < 8) {\n extraBytes++;\n mask = mask >>> 1;\n }\n\n // Special case: all 8 bits set means 8 extra bytes\n if (extraBytes === 8) {\n // Full 64-bit value follows\n return {\n value: readUInt64LE(buf, offset + 1),\n bytesRead: 9,\n };\n }\n\n // Mask off the length bits from first byte\n var value = firstByte & ((mask - 1) | mask);\n\n // Add remaining bytes (big-endian order)\n for (var i = 0; i < extraBytes; i++) {\n value = value * 256 + buf[offset + 1 + i];\n }\n\n return {\n value: value,\n bytesRead: 1 + extraBytes,\n };\n}\n\n/**\n * Read a raw 64-bit little-endian number (used in some fixed-size fields)\n * @param buf - Buffer containing the number\n * @param offset - Offset to start reading from\n * @returns The number value\n */\nexport function readRawNumber(buf: Buffer, offset: number): number {\n return readUInt64LE(buf, offset);\n}\n\n/**\n * Calculate the encoded size of a number\n * @param value - The number to encode\n * @returns Number of bytes needed to encode the value\n */\nexport function encodedSize(value: number): number {\n if (value < 0x80) return 1; // 7 bits\n if (value < 0x4000) return 2; // 14 bits\n if (value < 0x200000) return 3; // 21 bits\n if (value < 0x10000000) return 4; // 28 bits\n if (value < 0x800000000) return 5; // 35 bits\n if (value < 0x40000000000) return 6; // 42 bits\n if (value < 0x2000000000000) return 7; // 49 bits\n // 2^56 = 72057594037927936 (use calculated value to avoid precision loss)\n if (value < 72057594037927936) return 8; // 56 bits\n return 9; // 64 bits\n}\n\n/**\n * Read a boolean encoded as a single byte\n * @param buf - Buffer to read from\n * @param offset - Offset to read from\n * @returns true if byte is non-zero\n */\nexport function readBoolean(buf: Buffer, offset: number): boolean {\n return buf[offset] !== 0;\n}\n\n/**\n * Read a \"defined\" bitmask for an array of items.\n * Used when some items in a list have optional values.\n *\n * Format: If \"allDefined\" byte is 0, a bitmask follows indicating which items have values.\n * If \"allDefined\" byte is non-zero, all items are defined.\n *\n * @param buf - Buffer to read from\n * @param offset - Offset to start reading\n * @param count - Number of items\n * @returns Object with defined array and bytes consumed\n */\nexport function readDefinedVector(buf: Buffer, offset: number, count: number): { defined: boolean[]; bytesRead: number } {\n var allDefined = buf[offset] !== 0;\n var bytesRead = 1;\n var defined: boolean[] = [];\n\n if (allDefined) {\n // All items are defined\n for (var i = 0; i < count; i++) {\n defined.push(true);\n }\n } else {\n // Read bitmask\n var bitsNeeded = count;\n var bytesNeeded = Math.ceil(bitsNeeded / 8);\n\n for (var byteIdx = 0; byteIdx < bytesNeeded; byteIdx++) {\n var byte = buf[offset + 1 + byteIdx];\n for (var bit = 7; bit >= 0 && defined.length < count; bit--) {\n defined.push((byte & (1 << bit)) !== 0);\n }\n }\n bytesRead += bytesNeeded;\n }\n\n return { defined: defined, bytesRead: bytesRead };\n}\n\n/**\n * Read an array of variable-length numbers\n * @param buf - Buffer to read from\n * @param offset - Offset to start reading\n * @param count - Number of items to read\n * @returns Object with values array and bytes consumed\n */\nexport function readNumberArray(buf: Buffer, offset: number, count: number): { values: number[]; bytesRead: number } {\n var values: number[] = [];\n var totalBytesRead = 0;\n\n for (var i = 0; i < count; i++) {\n var result = readNumber(buf, offset + totalBytesRead);\n values.push(result.value);\n totalBytesRead += result.bytesRead;\n }\n\n return { values: values, bytesRead: totalBytesRead };\n}\n"],"names":["readUInt64LE","readNumber","buf","offset","firstByte","mask","extraBytes","value","bytesRead","i","readRawNumber","encodedSize","readBoolean","readDefinedVector","count","allDefined","defined","push","bitsNeeded","bytesNeeded","Math","ceil","byteIdx","byte","bit","length","readNumberArray","values","totalBytesRead","result"],"mappings":"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"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { type Readable } from 'readable-stream';
|
|
2
|
+
export interface SevenZipEntry {
|
|
3
|
+
name: string;
|
|
4
|
+
path: string;
|
|
5
|
+
type: 'file' | 'directory' | 'link';
|
|
6
|
+
size: number;
|
|
7
|
+
mtime?: Date;
|
|
8
|
+
atime?: Date;
|
|
9
|
+
ctime?: Date;
|
|
10
|
+
mode?: number;
|
|
11
|
+
isAntiFile: boolean;
|
|
12
|
+
_folderIndex: number;
|
|
13
|
+
_streamIndex: number;
|
|
14
|
+
_streamIndexInFolder: number;
|
|
15
|
+
_hasStream: boolean;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Archive source abstraction - allows reading from file descriptor or buffer
|
|
19
|
+
*/
|
|
20
|
+
export interface ArchiveSource {
|
|
21
|
+
read(position: number, length: number): Buffer;
|
|
22
|
+
getSize(): number;
|
|
23
|
+
close(): void;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Buffer-based archive source
|
|
27
|
+
*/
|
|
28
|
+
export declare class BufferSource implements ArchiveSource {
|
|
29
|
+
private buffer;
|
|
30
|
+
constructor(buffer: Buffer);
|
|
31
|
+
read(position: number, length: number): Buffer;
|
|
32
|
+
getSize(): number;
|
|
33
|
+
close(): void;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* File descriptor based archive source
|
|
37
|
+
*/
|
|
38
|
+
export declare class FileSource implements ArchiveSource {
|
|
39
|
+
private fd;
|
|
40
|
+
private size;
|
|
41
|
+
constructor(fd: number, size: number);
|
|
42
|
+
read(position: number, length: number): Buffer;
|
|
43
|
+
getSize(): number;
|
|
44
|
+
close(): void;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* SevenZipParser - parses 7z archives and provides entry iteration
|
|
48
|
+
*/
|
|
49
|
+
export declare class SevenZipParser {
|
|
50
|
+
private source;
|
|
51
|
+
private signature;
|
|
52
|
+
private streamsInfo;
|
|
53
|
+
private filesInfo;
|
|
54
|
+
private entries;
|
|
55
|
+
private parsed;
|
|
56
|
+
private decompressedCache;
|
|
57
|
+
constructor(source: ArchiveSource);
|
|
58
|
+
/**
|
|
59
|
+
* Parse the archive structure
|
|
60
|
+
* Must be called before iterating entries
|
|
61
|
+
*/
|
|
62
|
+
parse(): void;
|
|
63
|
+
/**
|
|
64
|
+
* Handle compressed header (kEncodedHeader)
|
|
65
|
+
*/
|
|
66
|
+
private handleCompressedHeader;
|
|
67
|
+
/**
|
|
68
|
+
* Parse streams info from encoded header block
|
|
69
|
+
* This is a simplified parser for the header's own compression info
|
|
70
|
+
*/
|
|
71
|
+
private parseEncodedHeaderStreams;
|
|
72
|
+
/**
|
|
73
|
+
* Build the entries list from parsed file info
|
|
74
|
+
*/
|
|
75
|
+
private buildEntries;
|
|
76
|
+
/**
|
|
77
|
+
* Create an entry from file info
|
|
78
|
+
*/
|
|
79
|
+
private createEntry;
|
|
80
|
+
/**
|
|
81
|
+
* Get the list of entries
|
|
82
|
+
*/
|
|
83
|
+
getEntries(): SevenZipEntry[];
|
|
84
|
+
/**
|
|
85
|
+
* Get a readable stream for an entry's content
|
|
86
|
+
*/
|
|
87
|
+
getEntryStream(entry: SevenZipEntry): Readable;
|
|
88
|
+
/**
|
|
89
|
+
* Get decompressed data for a folder, with caching for solid archives
|
|
90
|
+
*/
|
|
91
|
+
private getDecompressedFolder;
|
|
92
|
+
/**
|
|
93
|
+
* Close the parser and release resources
|
|
94
|
+
*/
|
|
95
|
+
close(): void;
|
|
96
|
+
}
|