7z-iterator 1.4.0 → 2.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.d.cts +3 -3
- package/dist/cjs/index.d.ts +3 -3
- package/dist/cjs/index.js +7 -38
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/nextEntry.js +1 -2
- package/dist/cjs/nextEntry.js.map +1 -1
- package/dist/cjs/sevenz/ArchiveSource.d.cts +1 -0
- package/dist/cjs/sevenz/ArchiveSource.d.ts +1 -0
- package/dist/cjs/sevenz/ArchiveSource.js +23 -0
- package/dist/cjs/sevenz/ArchiveSource.js.map +1 -1
- package/dist/cjs/sevenz/SevenZipParser.js +22 -3
- package/dist/cjs/sevenz/SevenZipParser.js.map +1 -1
- package/dist/cjs/sevenz/codecs/index.js +52 -30
- package/dist/cjs/sevenz/codecs/index.js.map +1 -1
- package/dist/cjs/sevenz/constants.d.cts +1 -0
- package/dist/cjs/sevenz/constants.d.ts +1 -0
- package/dist/cjs/sevenz/constants.js +1 -0
- package/dist/cjs/sevenz/constants.js.map +1 -1
- package/dist/esm/index.d.ts +3 -3
- package/dist/esm/index.js +4 -3
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/nextEntry.js +1 -2
- package/dist/esm/nextEntry.js.map +1 -1
- package/dist/esm/sevenz/ArchiveSource.d.ts +1 -0
- package/dist/esm/sevenz/ArchiveSource.js +23 -0
- package/dist/esm/sevenz/ArchiveSource.js.map +1 -1
- package/dist/esm/sevenz/SevenZipParser.js +22 -3
- package/dist/esm/sevenz/SevenZipParser.js.map +1 -1
- package/dist/esm/sevenz/codecs/index.js +32 -10
- package/dist/esm/sevenz/codecs/index.js.map +1 -1
- package/dist/esm/sevenz/constants.d.ts +1 -0
- package/dist/esm/sevenz/constants.js +1 -0
- package/dist/esm/sevenz/constants.js.map +1 -1
- package/package.json +3 -3
- package/dist/cjs/lzma/Lzma2ChunkParser.d.cts +0 -73
- package/dist/cjs/lzma/Lzma2ChunkParser.d.ts +0 -73
- package/dist/cjs/lzma/Lzma2ChunkParser.js +0 -148
- package/dist/cjs/lzma/Lzma2ChunkParser.js.map +0 -1
- package/dist/cjs/lzma/index.d.cts +0 -31
- package/dist/cjs/lzma/index.d.ts +0 -31
- package/dist/cjs/lzma/index.js +0 -83
- package/dist/cjs/lzma/index.js.map +0 -1
- package/dist/cjs/lzma/stream/transforms.d.cts +0 -46
- package/dist/cjs/lzma/stream/transforms.d.ts +0 -46
- package/dist/cjs/lzma/stream/transforms.js +0 -209
- package/dist/cjs/lzma/stream/transforms.js.map +0 -1
- package/dist/cjs/lzma/sync/Lzma2Decoder.d.cts +0 -63
- package/dist/cjs/lzma/sync/Lzma2Decoder.d.ts +0 -63
- package/dist/cjs/lzma/sync/Lzma2Decoder.js +0 -231
- package/dist/cjs/lzma/sync/Lzma2Decoder.js.map +0 -1
- package/dist/cjs/lzma/sync/LzmaDecoder.d.cts +0 -97
- package/dist/cjs/lzma/sync/LzmaDecoder.d.ts +0 -97
- package/dist/cjs/lzma/sync/LzmaDecoder.js +0 -580
- package/dist/cjs/lzma/sync/LzmaDecoder.js.map +0 -1
- package/dist/cjs/lzma/sync/RangeDecoder.d.cts +0 -69
- package/dist/cjs/lzma/sync/RangeDecoder.d.ts +0 -69
- package/dist/cjs/lzma/sync/RangeDecoder.js +0 -162
- package/dist/cjs/lzma/sync/RangeDecoder.js.map +0 -1
- package/dist/cjs/lzma/types.d.cts +0 -117
- package/dist/cjs/lzma/types.d.ts +0 -117
- package/dist/cjs/lzma/types.js +0 -264
- package/dist/cjs/lzma/types.js.map +0 -1
- package/dist/cjs/sevenz/codecs/Bcj.d.cts +0 -16
- package/dist/cjs/sevenz/codecs/Bcj.d.ts +0 -16
- package/dist/cjs/sevenz/codecs/Bcj.js +0 -183
- package/dist/cjs/sevenz/codecs/Bcj.js.map +0 -1
- package/dist/cjs/sevenz/codecs/BcjArm.d.cts +0 -21
- package/dist/cjs/sevenz/codecs/BcjArm.d.ts +0 -21
- package/dist/cjs/sevenz/codecs/BcjArm.js +0 -104
- package/dist/cjs/sevenz/codecs/BcjArm.js.map +0 -1
- package/dist/cjs/sevenz/codecs/BcjArm64.d.cts +0 -21
- package/dist/cjs/sevenz/codecs/BcjArm64.d.ts +0 -21
- package/dist/cjs/sevenz/codecs/BcjArm64.js +0 -65
- package/dist/cjs/sevenz/codecs/BcjArm64.js.map +0 -1
- package/dist/cjs/sevenz/codecs/BcjArmt.d.cts +0 -19
- package/dist/cjs/sevenz/codecs/BcjArmt.d.ts +0 -19
- package/dist/cjs/sevenz/codecs/BcjArmt.js +0 -76
- package/dist/cjs/sevenz/codecs/BcjArmt.js.map +0 -1
- package/dist/cjs/sevenz/codecs/BcjIa64.d.cts +0 -15
- package/dist/cjs/sevenz/codecs/BcjIa64.d.ts +0 -15
- package/dist/cjs/sevenz/codecs/BcjIa64.js +0 -141
- package/dist/cjs/sevenz/codecs/BcjIa64.js.map +0 -1
- package/dist/cjs/sevenz/codecs/BcjPpc.d.cts +0 -20
- package/dist/cjs/sevenz/codecs/BcjPpc.d.ts +0 -20
- package/dist/cjs/sevenz/codecs/BcjPpc.js +0 -64
- package/dist/cjs/sevenz/codecs/BcjPpc.js.map +0 -1
- package/dist/cjs/sevenz/codecs/BcjSparc.d.cts +0 -19
- package/dist/cjs/sevenz/codecs/BcjSparc.d.ts +0 -19
- package/dist/cjs/sevenz/codecs/BcjSparc.js +0 -69
- package/dist/cjs/sevenz/codecs/BcjSparc.js.map +0 -1
- package/dist/cjs/sevenz/codecs/Delta.d.cts +0 -16
- package/dist/cjs/sevenz/codecs/Delta.d.ts +0 -16
- package/dist/cjs/sevenz/codecs/Delta.js +0 -74
- package/dist/cjs/sevenz/codecs/Delta.js.map +0 -1
- package/dist/cjs/sevenz/codecs/Lzma.d.cts +0 -17
- package/dist/cjs/sevenz/codecs/Lzma.d.ts +0 -17
- package/dist/cjs/sevenz/codecs/Lzma.js +0 -40
- package/dist/cjs/sevenz/codecs/Lzma.js.map +0 -1
- package/dist/cjs/sevenz/codecs/Lzma2.d.cts +0 -20
- package/dist/cjs/sevenz/codecs/Lzma2.d.ts +0 -20
- package/dist/cjs/sevenz/codecs/Lzma2.js +0 -42
- package/dist/cjs/sevenz/codecs/Lzma2.js.map +0 -1
- package/dist/cjs/xz/Decoder.d.cts +0 -25
- package/dist/cjs/xz/Decoder.d.ts +0 -25
- package/dist/cjs/xz/Decoder.js +0 -194
- package/dist/cjs/xz/Decoder.js.map +0 -1
- package/dist/esm/lzma/Lzma2ChunkParser.d.ts +0 -73
- package/dist/esm/lzma/Lzma2ChunkParser.js +0 -137
- package/dist/esm/lzma/Lzma2ChunkParser.js.map +0 -1
- package/dist/esm/lzma/index.d.ts +0 -31
- package/dist/esm/lzma/index.js +0 -44
- package/dist/esm/lzma/index.js.map +0 -1
- package/dist/esm/lzma/stream/transforms.d.ts +0 -46
- package/dist/esm/lzma/stream/transforms.js +0 -189
- package/dist/esm/lzma/stream/transforms.js.map +0 -1
- package/dist/esm/lzma/sync/Lzma2Decoder.d.ts +0 -63
- package/dist/esm/lzma/sync/Lzma2Decoder.js +0 -211
- package/dist/esm/lzma/sync/Lzma2Decoder.js.map +0 -1
- package/dist/esm/lzma/sync/LzmaDecoder.d.ts +0 -97
- package/dist/esm/lzma/sync/LzmaDecoder.js +0 -543
- package/dist/esm/lzma/sync/LzmaDecoder.js.map +0 -1
- package/dist/esm/lzma/sync/RangeDecoder.d.ts +0 -69
- package/dist/esm/lzma/sync/RangeDecoder.js +0 -132
- package/dist/esm/lzma/sync/RangeDecoder.js.map +0 -1
- package/dist/esm/lzma/types.d.ts +0 -117
- package/dist/esm/lzma/types.js +0 -154
- package/dist/esm/lzma/types.js.map +0 -1
- package/dist/esm/sevenz/codecs/Bcj.d.ts +0 -16
- package/dist/esm/sevenz/codecs/Bcj.js +0 -175
- package/dist/esm/sevenz/codecs/Bcj.js.map +0 -1
- package/dist/esm/sevenz/codecs/BcjArm.d.ts +0 -21
- package/dist/esm/sevenz/codecs/BcjArm.js +0 -101
- package/dist/esm/sevenz/codecs/BcjArm.js.map +0 -1
- package/dist/esm/sevenz/codecs/BcjArm64.d.ts +0 -21
- package/dist/esm/sevenz/codecs/BcjArm64.js +0 -57
- package/dist/esm/sevenz/codecs/BcjArm64.js.map +0 -1
- package/dist/esm/sevenz/codecs/BcjArmt.d.ts +0 -19
- package/dist/esm/sevenz/codecs/BcjArmt.js +0 -66
- package/dist/esm/sevenz/codecs/BcjArmt.js.map +0 -1
- package/dist/esm/sevenz/codecs/BcjIa64.d.ts +0 -15
- package/dist/esm/sevenz/codecs/BcjIa64.js +0 -127
- package/dist/esm/sevenz/codecs/BcjIa64.js.map +0 -1
- package/dist/esm/sevenz/codecs/BcjPpc.d.ts +0 -20
- package/dist/esm/sevenz/codecs/BcjPpc.js +0 -55
- package/dist/esm/sevenz/codecs/BcjPpc.js.map +0 -1
- package/dist/esm/sevenz/codecs/BcjSparc.d.ts +0 -19
- package/dist/esm/sevenz/codecs/BcjSparc.js +0 -59
- package/dist/esm/sevenz/codecs/BcjSparc.js.map +0 -1
- package/dist/esm/sevenz/codecs/Delta.d.ts +0 -16
- package/dist/esm/sevenz/codecs/Delta.js +0 -66
- package/dist/esm/sevenz/codecs/Delta.js.map +0 -1
- package/dist/esm/sevenz/codecs/Lzma.d.ts +0 -17
- package/dist/esm/sevenz/codecs/Lzma.js +0 -33
- package/dist/esm/sevenz/codecs/Lzma.js.map +0 -1
- package/dist/esm/sevenz/codecs/Lzma2.d.ts +0 -20
- package/dist/esm/sevenz/codecs/Lzma2.js +0 -38
- package/dist/esm/sevenz/codecs/Lzma2.js.map +0 -1
- package/dist/esm/xz/Decoder.d.ts +0 -25
- package/dist/esm/xz/Decoder.js +0 -185
- package/dist/esm/xz/Decoder.js.map +0 -1
package/dist/cjs/xz/Decoder.js
DELETED
|
@@ -1,194 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* XZ Decompression Module
|
|
3
|
-
*
|
|
4
|
-
* XZ is a container format that wraps LZMA2 compressed data.
|
|
5
|
-
* This module provides both synchronous and streaming XZ decoders.
|
|
6
|
-
*
|
|
7
|
-
* Pure JavaScript implementation, works on Node.js 0.8+
|
|
8
|
-
*/ "use strict";
|
|
9
|
-
Object.defineProperty(exports, "__esModule", {
|
|
10
|
-
value: true
|
|
11
|
-
});
|
|
12
|
-
function _export(target, all) {
|
|
13
|
-
for(var name in all)Object.defineProperty(target, name, {
|
|
14
|
-
enumerable: true,
|
|
15
|
-
get: Object.getOwnPropertyDescriptor(all, name).get
|
|
16
|
-
});
|
|
17
|
-
}
|
|
18
|
-
_export(exports, {
|
|
19
|
-
get createXZDecoder () {
|
|
20
|
-
return createXZDecoder;
|
|
21
|
-
},
|
|
22
|
-
get decodeXZ () {
|
|
23
|
-
return decodeXZ;
|
|
24
|
-
}
|
|
25
|
-
});
|
|
26
|
-
var _extractbaseiterator = require("extract-base-iterator");
|
|
27
|
-
var _indexts = require("../lzma/index.js");
|
|
28
|
-
// XZ magic bytes
|
|
29
|
-
var XZ_MAGIC = [
|
|
30
|
-
0xfd,
|
|
31
|
-
0x37,
|
|
32
|
-
0x7a,
|
|
33
|
-
0x58,
|
|
34
|
-
0x5a,
|
|
35
|
-
0x00
|
|
36
|
-
];
|
|
37
|
-
var XZ_FOOTER_MAGIC = [
|
|
38
|
-
0x59,
|
|
39
|
-
0x5a
|
|
40
|
-
]; // "YZ"
|
|
41
|
-
// Filter IDs
|
|
42
|
-
var FILTER_LZMA2 = 0x21;
|
|
43
|
-
/**
|
|
44
|
-
* Simple buffer comparison
|
|
45
|
-
*/ function bufferEquals(buf, offset, expected) {
|
|
46
|
-
if (offset + expected.length > buf.length) {
|
|
47
|
-
return false;
|
|
48
|
-
}
|
|
49
|
-
for(var i = 0; i < expected.length; i++){
|
|
50
|
-
if (buf[offset + i] !== expected[i]) {
|
|
51
|
-
return false;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
return true;
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* Decode variable-length integer (XZ multibyte encoding)
|
|
58
|
-
*/ function decodeMultibyte(buf, offset) {
|
|
59
|
-
var value = 0;
|
|
60
|
-
var i = 0;
|
|
61
|
-
var byte;
|
|
62
|
-
do {
|
|
63
|
-
if (offset + i >= buf.length) {
|
|
64
|
-
throw new Error('Truncated multibyte integer');
|
|
65
|
-
}
|
|
66
|
-
byte = buf[offset + i];
|
|
67
|
-
value |= (byte & 0x7f) << i * 7;
|
|
68
|
-
i++;
|
|
69
|
-
if (i > 9) {
|
|
70
|
-
throw new Error('Multibyte integer too large');
|
|
71
|
-
}
|
|
72
|
-
}while (byte & 0x80);
|
|
73
|
-
return {
|
|
74
|
-
value: value,
|
|
75
|
-
bytesRead: i
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
function decodeXZ(input) {
|
|
79
|
-
var _checkSizes_checkType;
|
|
80
|
-
// Verify XZ magic
|
|
81
|
-
if (input.length < 12 || !bufferEquals(input, 0, XZ_MAGIC)) {
|
|
82
|
-
throw new Error('Invalid XZ magic bytes');
|
|
83
|
-
}
|
|
84
|
-
// Stream flags at offset 6-7
|
|
85
|
-
var checkType = input[7] & 0x0f;
|
|
86
|
-
// Check sizes based on check type
|
|
87
|
-
var checkSizes = {
|
|
88
|
-
0: 0,
|
|
89
|
-
1: 4,
|
|
90
|
-
4: 8,
|
|
91
|
-
10: 32
|
|
92
|
-
};
|
|
93
|
-
var checkSize = (_checkSizes_checkType = checkSizes[checkType]) !== null && _checkSizes_checkType !== void 0 ? _checkSizes_checkType : 0;
|
|
94
|
-
// Block starts at offset 12
|
|
95
|
-
var offset = 12;
|
|
96
|
-
// Block header size
|
|
97
|
-
var blockHeaderSizeRaw = input[offset];
|
|
98
|
-
if (blockHeaderSizeRaw === 0) {
|
|
99
|
-
throw new Error('Invalid block header size (index indicator found instead of block)');
|
|
100
|
-
}
|
|
101
|
-
var blockHeaderSize = (blockHeaderSizeRaw + 1) * 4;
|
|
102
|
-
// Parse block header to find LZMA2 properties
|
|
103
|
-
var blockHeaderStart = offset;
|
|
104
|
-
offset++; // skip size byte
|
|
105
|
-
var blockFlags = input[offset++];
|
|
106
|
-
var numFilters = (blockFlags & 0x03) + 1;
|
|
107
|
-
var hasCompressedSize = (blockFlags & 0x40) !== 0;
|
|
108
|
-
var hasUncompressedSize = (blockFlags & 0x80) !== 0;
|
|
109
|
-
// Skip optional sizes
|
|
110
|
-
if (hasCompressedSize) {
|
|
111
|
-
var result = decodeMultibyte(input, offset);
|
|
112
|
-
offset += result.bytesRead;
|
|
113
|
-
}
|
|
114
|
-
var _uncompressedSize;
|
|
115
|
-
if (hasUncompressedSize) {
|
|
116
|
-
var result1 = decodeMultibyte(input, offset);
|
|
117
|
-
_uncompressedSize = result1.value;
|
|
118
|
-
offset += result1.bytesRead;
|
|
119
|
-
}
|
|
120
|
-
// Parse filter (should be LZMA2)
|
|
121
|
-
var lzma2Props = null;
|
|
122
|
-
for(var i = 0; i < numFilters; i++){
|
|
123
|
-
var filterIdResult = decodeMultibyte(input, offset);
|
|
124
|
-
var filterId = filterIdResult.value;
|
|
125
|
-
offset += filterIdResult.bytesRead;
|
|
126
|
-
var propsSizeResult = decodeMultibyte(input, offset);
|
|
127
|
-
offset += propsSizeResult.bytesRead;
|
|
128
|
-
var filterProps = input.slice(offset, offset + propsSizeResult.value);
|
|
129
|
-
offset += propsSizeResult.value;
|
|
130
|
-
if (filterId === FILTER_LZMA2) {
|
|
131
|
-
lzma2Props = filterProps;
|
|
132
|
-
} else if (filterId !== 0x03 && filterId !== 0x04 && filterId !== 0x05 && filterId !== 0x06 && filterId !== 0x07 && filterId !== 0x08 && filterId !== 0x09 && filterId !== 0x0a) {
|
|
133
|
-
// BCJ filters (0x04-0x0a) and Delta (0x03) are preprocessing filters
|
|
134
|
-
// For now, only support LZMA2 alone
|
|
135
|
-
throw new Error("Unsupported filter: 0x".concat(filterId.toString(16)));
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
if (!lzma2Props) {
|
|
139
|
-
throw new Error('No LZMA2 filter found in XZ block');
|
|
140
|
-
}
|
|
141
|
-
// Skip to end of block header (align to 4 bytes + CRC32)
|
|
142
|
-
var blockDataStart = blockHeaderStart + blockHeaderSize;
|
|
143
|
-
// Find the end of compressed data (look for index from the footer)
|
|
144
|
-
// Footer is last 12 bytes: CRC32(4) + Backward Size(4) + Stream Flags(2) + Magic(2)
|
|
145
|
-
if (input.length < 12) {
|
|
146
|
-
throw new Error('XZ file too small');
|
|
147
|
-
}
|
|
148
|
-
// Verify footer magic
|
|
149
|
-
if (!bufferEquals(input, input.length - 2, XZ_FOOTER_MAGIC)) {
|
|
150
|
-
throw new Error('Invalid XZ footer magic');
|
|
151
|
-
}
|
|
152
|
-
// Get backward size (tells us where index starts)
|
|
153
|
-
// Footer: CRC32(4) at -12, Backward Size(4) at -8, Stream Flags(2) at -4, Magic(2) at -2
|
|
154
|
-
var backwardSize = (input.readUInt32LE(input.length - 8) + 1) * 4;
|
|
155
|
-
var indexStart = input.length - 12 - backwardSize;
|
|
156
|
-
// Extract all data between block header end and index start
|
|
157
|
-
var compressedDataEnd = indexStart;
|
|
158
|
-
// Account for check at end of block
|
|
159
|
-
compressedDataEnd -= checkSize;
|
|
160
|
-
// Account for padding (up to 3 bytes of 0x00)
|
|
161
|
-
while(compressedDataEnd > blockDataStart && input[compressedDataEnd - 1] === 0x00){
|
|
162
|
-
compressedDataEnd--;
|
|
163
|
-
}
|
|
164
|
-
// Add back one 0x00 for LZMA2 end marker
|
|
165
|
-
compressedDataEnd++;
|
|
166
|
-
var compressedData = input.slice(blockDataStart, compressedDataEnd);
|
|
167
|
-
// Decompress LZMA2 data using optimized output stream decoder
|
|
168
|
-
var chunks = [];
|
|
169
|
-
(0, _indexts.decodeLzma2)(compressedData, lzma2Props, undefined, {
|
|
170
|
-
write: function(chunk) {
|
|
171
|
-
return chunks.push(chunk);
|
|
172
|
-
}
|
|
173
|
-
});
|
|
174
|
-
return Buffer.concat(chunks);
|
|
175
|
-
}
|
|
176
|
-
function createXZDecoder() {
|
|
177
|
-
var chunks = [];
|
|
178
|
-
return new _extractbaseiterator.Transform({
|
|
179
|
-
transform: function transform(chunk, _encoding, callback) {
|
|
180
|
-
chunks.push(chunk);
|
|
181
|
-
callback();
|
|
182
|
-
},
|
|
183
|
-
flush: function flush(callback) {
|
|
184
|
-
try {
|
|
185
|
-
var input = Buffer.concat(chunks);
|
|
186
|
-
var output = decodeXZ(input);
|
|
187
|
-
callback(null, output);
|
|
188
|
-
} catch (err) {
|
|
189
|
-
callback(err);
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
});
|
|
193
|
-
}
|
|
194
|
-
/* CJS INTEROP */ if (exports.__esModule && exports.default) { try { Object.defineProperty(exports.default, '__esModule', { value: true }); for (var key in exports) { exports.default[key] = exports[key]; } } catch (_) {}; module.exports = exports.default; }
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/iterators/7z-iterator/src/xz/Decoder.ts"],"sourcesContent":["/**\n * XZ Decompression Module\n *\n * XZ is a container format that wraps LZMA2 compressed data.\n * This module provides both synchronous and streaming XZ decoders.\n *\n * Pure JavaScript implementation, works on Node.js 0.8+\n */\n\nimport { Transform } from 'extract-base-iterator';\nimport type { Transform as TransformType } from 'stream';\nimport { decodeLzma2 } from '../lzma/index.ts';\n\n// XZ magic bytes\nconst XZ_MAGIC = [0xfd, 0x37, 0x7a, 0x58, 0x5a, 0x00];\nconst XZ_FOOTER_MAGIC = [0x59, 0x5a]; // \"YZ\"\n\n// Filter IDs\nconst FILTER_LZMA2 = 0x21;\n\n/**\n * Simple buffer comparison\n */\nfunction bufferEquals(buf: Buffer, offset: number, expected: number[]): boolean {\n if (offset + expected.length > buf.length) {\n return false;\n }\n for (let i = 0; i < expected.length; i++) {\n if (buf[offset + i] !== expected[i]) {\n return false;\n }\n }\n return true;\n}\n\n/**\n * Decode variable-length integer (XZ multibyte encoding)\n */\nfunction decodeMultibyte(buf: Buffer, offset: number): { value: number; bytesRead: number } {\n let value = 0;\n let i = 0;\n let byte: number;\n do {\n if (offset + i >= buf.length) {\n throw new Error('Truncated multibyte integer');\n }\n byte = buf[offset + i];\n value |= (byte & 0x7f) << (i * 7);\n i++;\n if (i > 9) {\n throw new Error('Multibyte integer too large');\n }\n } while (byte & 0x80);\n return { value, bytesRead: i };\n}\n\n/**\n * Decompress XZ data synchronously\n * @param input - XZ compressed data\n * @returns Decompressed data\n */\nexport function decodeXZ(input: Buffer): Buffer {\n // Verify XZ magic\n if (input.length < 12 || !bufferEquals(input, 0, XZ_MAGIC)) {\n throw new Error('Invalid XZ magic bytes');\n }\n\n // Stream flags at offset 6-7\n const checkType = input[7] & 0x0f;\n\n // Check sizes based on check type\n const checkSizes: { [key: number]: number } = {\n 0: 0, // None\n 1: 4, // CRC32\n 4: 8, // CRC64\n 10: 32, // SHA-256\n };\n const checkSize = checkSizes[checkType] ?? 0;\n\n // Block starts at offset 12\n let offset = 12;\n\n // Block header size\n const blockHeaderSizeRaw = input[offset];\n if (blockHeaderSizeRaw === 0) {\n throw new Error('Invalid block header size (index indicator found instead of block)');\n }\n const blockHeaderSize = (blockHeaderSizeRaw + 1) * 4;\n\n // Parse block header to find LZMA2 properties\n const blockHeaderStart = offset;\n offset++; // skip size byte\n\n const blockFlags = input[offset++];\n const numFilters = (blockFlags & 0x03) + 1;\n const hasCompressedSize = (blockFlags & 0x40) !== 0;\n const hasUncompressedSize = (blockFlags & 0x80) !== 0;\n\n // Skip optional sizes\n if (hasCompressedSize) {\n const result = decodeMultibyte(input, offset);\n offset += result.bytesRead;\n }\n\n let _uncompressedSize: number | undefined;\n if (hasUncompressedSize) {\n const result = decodeMultibyte(input, offset);\n _uncompressedSize = result.value;\n offset += result.bytesRead;\n }\n\n // Parse filter (should be LZMA2)\n let lzma2Props: Buffer | null = null;\n for (let i = 0; i < numFilters; i++) {\n const filterIdResult = decodeMultibyte(input, offset);\n const filterId = filterIdResult.value;\n offset += filterIdResult.bytesRead;\n\n const propsSizeResult = decodeMultibyte(input, offset);\n offset += propsSizeResult.bytesRead;\n\n const filterProps = input.slice(offset, offset + propsSizeResult.value);\n offset += propsSizeResult.value;\n\n if (filterId === FILTER_LZMA2) {\n lzma2Props = filterProps;\n } else if (filterId !== 0x03 && filterId !== 0x04 && filterId !== 0x05 && filterId !== 0x06 && filterId !== 0x07 && filterId !== 0x08 && filterId !== 0x09 && filterId !== 0x0a) {\n // BCJ filters (0x04-0x0a) and Delta (0x03) are preprocessing filters\n // For now, only support LZMA2 alone\n throw new Error(`Unsupported filter: 0x${filterId.toString(16)}`);\n }\n }\n\n if (!lzma2Props) {\n throw new Error('No LZMA2 filter found in XZ block');\n }\n\n // Skip to end of block header (align to 4 bytes + CRC32)\n const blockDataStart = blockHeaderStart + blockHeaderSize;\n\n // Find the end of compressed data (look for index from the footer)\n // Footer is last 12 bytes: CRC32(4) + Backward Size(4) + Stream Flags(2) + Magic(2)\n if (input.length < 12) {\n throw new Error('XZ file too small');\n }\n\n // Verify footer magic\n if (!bufferEquals(input, input.length - 2, XZ_FOOTER_MAGIC)) {\n throw new Error('Invalid XZ footer magic');\n }\n\n // Get backward size (tells us where index starts)\n // Footer: CRC32(4) at -12, Backward Size(4) at -8, Stream Flags(2) at -4, Magic(2) at -2\n const backwardSize = (input.readUInt32LE(input.length - 8) + 1) * 4;\n const indexStart = input.length - 12 - backwardSize;\n\n // Extract all data between block header end and index start\n let compressedDataEnd = indexStart;\n\n // Account for check at end of block\n compressedDataEnd -= checkSize;\n\n // Account for padding (up to 3 bytes of 0x00)\n while (compressedDataEnd > blockDataStart && input[compressedDataEnd - 1] === 0x00) {\n compressedDataEnd--;\n }\n // Add back one 0x00 for LZMA2 end marker\n compressedDataEnd++;\n\n const compressedData = input.slice(blockDataStart, compressedDataEnd);\n\n // Decompress LZMA2 data using optimized output stream decoder\n const chunks: Buffer[] = [];\n decodeLzma2(compressedData, lzma2Props, undefined, {\n write: (chunk: Buffer) => chunks.push(chunk),\n });\n\n return Buffer.concat(chunks);\n}\n\n/**\n * Create an XZ decompression Transform stream\n *\n * Note: XZ buffers all input before decompressing, as it's a single-frame format.\n * For true streaming with better performance on large files, consider using XZ directly\n * with the sync decodeXZ() function.\n *\n * @returns Transform stream that decompresses XZ data\n */\nexport function createXZDecoder(): TransformType {\n const chunks: Buffer[] = [];\n\n return new Transform({\n transform(chunk: Buffer, _encoding: string, callback: (error?: Error | null, data?: Buffer) => void) {\n chunks.push(chunk);\n callback();\n },\n\n flush(callback: (error?: Error | null, data?: Buffer) => void) {\n try {\n const input = Buffer.concat(chunks);\n const output = decodeXZ(input);\n callback(null, output);\n } catch (err) {\n callback(err as Error);\n }\n },\n });\n}\n"],"names":["createXZDecoder","decodeXZ","XZ_MAGIC","XZ_FOOTER_MAGIC","FILTER_LZMA2","bufferEquals","buf","offset","expected","length","i","decodeMultibyte","value","byte","Error","bytesRead","input","checkSizes","checkType","checkSize","blockHeaderSizeRaw","blockHeaderSize","blockHeaderStart","blockFlags","numFilters","hasCompressedSize","hasUncompressedSize","result","_uncompressedSize","lzma2Props","filterIdResult","filterId","propsSizeResult","filterProps","slice","toString","blockDataStart","backwardSize","readUInt32LE","indexStart","compressedDataEnd","compressedData","chunks","decodeLzma2","undefined","write","chunk","push","Buffer","concat","Transform","transform","_encoding","callback","flush","output","err"],"mappings":"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"}
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* LZMA2 Chunk Parser
|
|
3
|
-
*
|
|
4
|
-
* Shared parsing logic for LZMA2 chunk headers.
|
|
5
|
-
* Used by both synchronous and streaming decoders.
|
|
6
|
-
*
|
|
7
|
-
* LZMA2 control byte ranges:
|
|
8
|
-
* 0x00 = End of stream
|
|
9
|
-
* 0x01 = Uncompressed chunk, dictionary reset
|
|
10
|
-
* 0x02 = Uncompressed chunk, no dictionary reset
|
|
11
|
-
* 0x80-0x9F = LZMA chunk, no reset (solid mode)
|
|
12
|
-
* 0xA0-0xBF = LZMA chunk, reset state (probabilities)
|
|
13
|
-
* 0xC0-0xDF = LZMA chunk, reset state + new properties
|
|
14
|
-
* 0xE0-0xFF = LZMA chunk, reset dictionary + state + new properties
|
|
15
|
-
*/
|
|
16
|
-
/**
|
|
17
|
-
* LZMA properties extracted from chunk header
|
|
18
|
-
*/
|
|
19
|
-
export interface LzmaChunkProps {
|
|
20
|
-
lc: number;
|
|
21
|
-
lp: number;
|
|
22
|
-
pb: number;
|
|
23
|
-
}
|
|
24
|
-
/**
|
|
25
|
-
* Parsed LZMA2 chunk information
|
|
26
|
-
*/
|
|
27
|
-
export interface Lzma2Chunk {
|
|
28
|
-
/** Chunk type */
|
|
29
|
-
type: 'end' | 'uncompressed' | 'lzma';
|
|
30
|
-
/** Total bytes consumed by header (including control byte) */
|
|
31
|
-
headerSize: number;
|
|
32
|
-
/** Whether to reset dictionary */
|
|
33
|
-
dictReset: boolean;
|
|
34
|
-
/** Whether to reset state/probabilities */
|
|
35
|
-
stateReset: boolean;
|
|
36
|
-
/** New LZMA properties (only for control >= 0xC0) */
|
|
37
|
-
newProps: LzmaChunkProps | null;
|
|
38
|
-
/** Uncompressed data size */
|
|
39
|
-
uncompSize: number;
|
|
40
|
-
/** Compressed data size (0 for uncompressed chunks) */
|
|
41
|
-
compSize: number;
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* Result of parsing attempt
|
|
45
|
-
*/
|
|
46
|
-
export type ParseResult = {
|
|
47
|
-
success: true;
|
|
48
|
-
chunk: Lzma2Chunk;
|
|
49
|
-
} | {
|
|
50
|
-
success: false;
|
|
51
|
-
needBytes: number;
|
|
52
|
-
};
|
|
53
|
-
/**
|
|
54
|
-
* Parse an LZMA2 chunk header
|
|
55
|
-
*
|
|
56
|
-
* @param input - Input buffer
|
|
57
|
-
* @param offset - Offset to start parsing
|
|
58
|
-
* @returns Parsed chunk info or number of bytes needed
|
|
59
|
-
*/
|
|
60
|
-
export declare function parseLzma2ChunkHeader(input: Buffer, offset: number): ParseResult;
|
|
61
|
-
/** Result type for hasCompleteChunk with totalSize included on success */
|
|
62
|
-
export type CompleteChunkResult = {
|
|
63
|
-
success: true;
|
|
64
|
-
chunk: Lzma2Chunk;
|
|
65
|
-
totalSize: number;
|
|
66
|
-
} | {
|
|
67
|
-
success: false;
|
|
68
|
-
needBytes: number;
|
|
69
|
-
};
|
|
70
|
-
/**
|
|
71
|
-
* Check if we have enough data for the complete chunk (header + data)
|
|
72
|
-
*/
|
|
73
|
-
export declare function hasCompleteChunk(input: Buffer, offset: number): CompleteChunkResult;
|
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* LZMA2 Chunk Parser
|
|
3
|
-
*
|
|
4
|
-
* Shared parsing logic for LZMA2 chunk headers.
|
|
5
|
-
* Used by both synchronous and streaming decoders.
|
|
6
|
-
*
|
|
7
|
-
* LZMA2 control byte ranges:
|
|
8
|
-
* 0x00 = End of stream
|
|
9
|
-
* 0x01 = Uncompressed chunk, dictionary reset
|
|
10
|
-
* 0x02 = Uncompressed chunk, no dictionary reset
|
|
11
|
-
* 0x80-0x9F = LZMA chunk, no reset (solid mode)
|
|
12
|
-
* 0xA0-0xBF = LZMA chunk, reset state (probabilities)
|
|
13
|
-
* 0xC0-0xDF = LZMA chunk, reset state + new properties
|
|
14
|
-
* 0xE0-0xFF = LZMA chunk, reset dictionary + state + new properties
|
|
15
|
-
*/ /**
|
|
16
|
-
* LZMA properties extracted from chunk header
|
|
17
|
-
*/ /**
|
|
18
|
-
* Parse an LZMA2 chunk header
|
|
19
|
-
*
|
|
20
|
-
* @param input - Input buffer
|
|
21
|
-
* @param offset - Offset to start parsing
|
|
22
|
-
* @returns Parsed chunk info or number of bytes needed
|
|
23
|
-
*/ export function parseLzma2ChunkHeader(input, offset) {
|
|
24
|
-
if (offset >= input.length) {
|
|
25
|
-
return {
|
|
26
|
-
success: false,
|
|
27
|
-
needBytes: 1
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
|
-
const control = input[offset];
|
|
31
|
-
// End of stream
|
|
32
|
-
if (control === 0x00) {
|
|
33
|
-
return {
|
|
34
|
-
success: true,
|
|
35
|
-
chunk: {
|
|
36
|
-
type: 'end',
|
|
37
|
-
headerSize: 1,
|
|
38
|
-
dictReset: false,
|
|
39
|
-
stateReset: false,
|
|
40
|
-
newProps: null,
|
|
41
|
-
uncompSize: 0,
|
|
42
|
-
compSize: 0
|
|
43
|
-
}
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
// Uncompressed chunk
|
|
47
|
-
if (control === 0x01 || control === 0x02) {
|
|
48
|
-
// Need 3 bytes: control + 2 size bytes
|
|
49
|
-
if (offset + 3 > input.length) {
|
|
50
|
-
return {
|
|
51
|
-
success: false,
|
|
52
|
-
needBytes: 3 - (input.length - offset)
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
const uncompSize = (input[offset + 1] << 8 | input[offset + 2]) + 1;
|
|
56
|
-
return {
|
|
57
|
-
success: true,
|
|
58
|
-
chunk: {
|
|
59
|
-
type: 'uncompressed',
|
|
60
|
-
headerSize: 3,
|
|
61
|
-
dictReset: control === 0x01,
|
|
62
|
-
stateReset: false,
|
|
63
|
-
newProps: null,
|
|
64
|
-
uncompSize,
|
|
65
|
-
compSize: 0
|
|
66
|
-
}
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
// LZMA compressed chunk
|
|
70
|
-
if (control >= 0x80) {
|
|
71
|
-
const hasNewProps = control >= 0xc0;
|
|
72
|
-
const minHeaderSize = hasNewProps ? 6 : 5; // control + 2 uncomp + 2 comp + (1 props)
|
|
73
|
-
if (offset + minHeaderSize > input.length) {
|
|
74
|
-
return {
|
|
75
|
-
success: false,
|
|
76
|
-
needBytes: minHeaderSize - (input.length - offset)
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
// Parse sizes
|
|
80
|
-
const uncompHigh = control & 0x1f;
|
|
81
|
-
const uncompSize = (uncompHigh << 16 | input[offset + 1] << 8 | input[offset + 2]) + 1;
|
|
82
|
-
const compSize = (input[offset + 3] << 8 | input[offset + 4]) + 1;
|
|
83
|
-
// Parse properties if present
|
|
84
|
-
let newProps = null;
|
|
85
|
-
if (hasNewProps) {
|
|
86
|
-
const propsByte = input[offset + 5];
|
|
87
|
-
const lc = propsByte % 9;
|
|
88
|
-
const remainder = ~~(propsByte / 9);
|
|
89
|
-
const lp = remainder % 5;
|
|
90
|
-
const pb = ~~(remainder / 5);
|
|
91
|
-
newProps = {
|
|
92
|
-
lc,
|
|
93
|
-
lp,
|
|
94
|
-
pb
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
return {
|
|
98
|
-
success: true,
|
|
99
|
-
chunk: {
|
|
100
|
-
type: 'lzma',
|
|
101
|
-
headerSize: minHeaderSize,
|
|
102
|
-
dictReset: control >= 0xe0,
|
|
103
|
-
stateReset: control >= 0xa0,
|
|
104
|
-
newProps,
|
|
105
|
-
uncompSize,
|
|
106
|
-
compSize
|
|
107
|
-
}
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
// Invalid control byte
|
|
111
|
-
throw new Error(`Invalid LZMA2 control byte: 0x${control.toString(16)}`);
|
|
112
|
-
}
|
|
113
|
-
/**
|
|
114
|
-
* Check if we have enough data for the complete chunk (header + data)
|
|
115
|
-
*/ export function hasCompleteChunk(input, offset) {
|
|
116
|
-
const result = parseLzma2ChunkHeader(input, offset);
|
|
117
|
-
if (result.success === false) {
|
|
118
|
-
return {
|
|
119
|
-
success: false,
|
|
120
|
-
needBytes: result.needBytes
|
|
121
|
-
};
|
|
122
|
-
}
|
|
123
|
-
const { chunk } = result;
|
|
124
|
-
const dataSize = chunk.type === 'uncompressed' ? chunk.uncompSize : chunk.compSize;
|
|
125
|
-
const totalSize = chunk.headerSize + dataSize;
|
|
126
|
-
if (offset + totalSize > input.length) {
|
|
127
|
-
return {
|
|
128
|
-
success: false,
|
|
129
|
-
needBytes: totalSize - (input.length - offset)
|
|
130
|
-
};
|
|
131
|
-
}
|
|
132
|
-
return {
|
|
133
|
-
success: true,
|
|
134
|
-
chunk,
|
|
135
|
-
totalSize
|
|
136
|
-
};
|
|
137
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/iterators/7z-iterator/src/lzma/Lzma2ChunkParser.ts"],"sourcesContent":["/**\n * LZMA2 Chunk Parser\n *\n * Shared parsing logic for LZMA2 chunk headers.\n * Used by both synchronous and streaming decoders.\n *\n * LZMA2 control byte ranges:\n * 0x00 = End of stream\n * 0x01 = Uncompressed chunk, dictionary reset\n * 0x02 = Uncompressed chunk, no dictionary reset\n * 0x80-0x9F = LZMA chunk, no reset (solid mode)\n * 0xA0-0xBF = LZMA chunk, reset state (probabilities)\n * 0xC0-0xDF = LZMA chunk, reset state + new properties\n * 0xE0-0xFF = LZMA chunk, reset dictionary + state + new properties\n */\n\n/**\n * LZMA properties extracted from chunk header\n */\nexport interface LzmaChunkProps {\n lc: number;\n lp: number;\n pb: number;\n}\n\n/**\n * Parsed LZMA2 chunk information\n */\nexport interface Lzma2Chunk {\n /** Chunk type */\n type: 'end' | 'uncompressed' | 'lzma';\n /** Total bytes consumed by header (including control byte) */\n headerSize: number;\n /** Whether to reset dictionary */\n dictReset: boolean;\n /** Whether to reset state/probabilities */\n stateReset: boolean;\n /** New LZMA properties (only for control >= 0xC0) */\n newProps: LzmaChunkProps | null;\n /** Uncompressed data size */\n uncompSize: number;\n /** Compressed data size (0 for uncompressed chunks) */\n compSize: number;\n}\n\n/**\n * Result of parsing attempt\n */\nexport type ParseResult = { success: true; chunk: Lzma2Chunk } | { success: false; needBytes: number };\n\n/**\n * Parse an LZMA2 chunk header\n *\n * @param input - Input buffer\n * @param offset - Offset to start parsing\n * @returns Parsed chunk info or number of bytes needed\n */\nexport function parseLzma2ChunkHeader(input: Buffer, offset: number): ParseResult {\n if (offset >= input.length) {\n return { success: false, needBytes: 1 };\n }\n\n const control = input[offset];\n\n // End of stream\n if (control === 0x00) {\n return {\n success: true,\n chunk: {\n type: 'end',\n headerSize: 1,\n dictReset: false,\n stateReset: false,\n newProps: null,\n uncompSize: 0,\n compSize: 0,\n },\n };\n }\n\n // Uncompressed chunk\n if (control === 0x01 || control === 0x02) {\n // Need 3 bytes: control + 2 size bytes\n if (offset + 3 > input.length) {\n return { success: false, needBytes: 3 - (input.length - offset) };\n }\n\n const uncompSize = ((input[offset + 1] << 8) | input[offset + 2]) + 1;\n\n return {\n success: true,\n chunk: {\n type: 'uncompressed',\n headerSize: 3,\n dictReset: control === 0x01,\n stateReset: false,\n newProps: null,\n uncompSize,\n compSize: 0,\n },\n };\n }\n\n // LZMA compressed chunk\n if (control >= 0x80) {\n const hasNewProps = control >= 0xc0;\n const minHeaderSize = hasNewProps ? 6 : 5; // control + 2 uncomp + 2 comp + (1 props)\n\n if (offset + minHeaderSize > input.length) {\n return { success: false, needBytes: minHeaderSize - (input.length - offset) };\n }\n\n // Parse sizes\n const uncompHigh = control & 0x1f;\n const uncompSize = ((uncompHigh << 16) | (input[offset + 1] << 8) | input[offset + 2]) + 1;\n const compSize = ((input[offset + 3] << 8) | input[offset + 4]) + 1;\n\n // Parse properties if present\n let newProps: LzmaChunkProps | null = null;\n if (hasNewProps) {\n const propsByte = input[offset + 5];\n const lc = propsByte % 9;\n const remainder = ~~(propsByte / 9);\n const lp = remainder % 5;\n const pb = ~~(remainder / 5);\n newProps = { lc, lp, pb };\n }\n\n return {\n success: true,\n chunk: {\n type: 'lzma',\n headerSize: minHeaderSize,\n dictReset: control >= 0xe0,\n stateReset: control >= 0xa0,\n newProps,\n uncompSize,\n compSize,\n },\n };\n }\n\n // Invalid control byte\n throw new Error(`Invalid LZMA2 control byte: 0x${control.toString(16)}`);\n}\n\n/** Result type for hasCompleteChunk with totalSize included on success */\nexport type CompleteChunkResult = { success: true; chunk: Lzma2Chunk; totalSize: number } | { success: false; needBytes: number };\n\n/**\n * Check if we have enough data for the complete chunk (header + data)\n */\nexport function hasCompleteChunk(input: Buffer, offset: number): CompleteChunkResult {\n const result = parseLzma2ChunkHeader(input, offset);\n\n if (result.success === false) {\n return { success: false, needBytes: result.needBytes };\n }\n\n const { chunk } = result;\n const dataSize = chunk.type === 'uncompressed' ? chunk.uncompSize : chunk.compSize;\n const totalSize = chunk.headerSize + dataSize;\n\n if (offset + totalSize > input.length) {\n return { success: false, needBytes: totalSize - (input.length - offset) };\n }\n\n return { success: true, chunk, totalSize };\n}\n"],"names":["parseLzma2ChunkHeader","input","offset","length","success","needBytes","control","chunk","type","headerSize","dictReset","stateReset","newProps","uncompSize","compSize","hasNewProps","minHeaderSize","uncompHigh","propsByte","lc","remainder","lp","pb","Error","toString","hasCompleteChunk","result","dataSize","totalSize"],"mappings":"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"}
|
package/dist/esm/lzma/index.d.ts
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* LZMA Decoder Module
|
|
3
|
-
*
|
|
4
|
-
* Provides both synchronous and streaming LZMA1/LZMA2 decoders.
|
|
5
|
-
*
|
|
6
|
-
* Synchronous API: Use when input is a complete Buffer
|
|
7
|
-
* Streaming API: Use with Transform streams for memory-efficient decompression
|
|
8
|
-
*
|
|
9
|
-
* LZMA1 vs LZMA2:
|
|
10
|
-
* - LZMA2 is chunked and supports true streaming with bounded memory
|
|
11
|
-
* - LZMA1 has no chunk boundaries and requires buffering all input for streaming
|
|
12
|
-
*/
|
|
13
|
-
export { createLzma2Decoder, createLzmaDecoder } from './stream/transforms.js';
|
|
14
|
-
export { decodeLzma2, Lzma2Decoder } from './sync/Lzma2Decoder.js';
|
|
15
|
-
export { decodeLzma, LzmaDecoder } from './sync/LzmaDecoder.js';
|
|
16
|
-
export { BitTreeDecoder, RangeDecoder } from './sync/RangeDecoder.js';
|
|
17
|
-
export * from './types.js';
|
|
18
|
-
/**
|
|
19
|
-
* Detect LZMA format from compressed data
|
|
20
|
-
*
|
|
21
|
-
* LZMA2 uses chunk-based framing with control bytes:
|
|
22
|
-
* - 0x00: End of stream
|
|
23
|
-
* - 0x01-0x02: Uncompressed chunks
|
|
24
|
-
* - 0x80-0xFF: LZMA compressed chunks
|
|
25
|
-
*
|
|
26
|
-
* LZMA1 is raw LZMA-compressed data (no framing)
|
|
27
|
-
*
|
|
28
|
-
* @param data - Compressed data to analyze
|
|
29
|
-
* @returns 'lzma1' for LZMA1, 'lzma2' for LZMA2
|
|
30
|
-
*/
|
|
31
|
-
export declare function detectFormat(data: Buffer): 'lzma1' | 'lzma2';
|
package/dist/esm/lzma/index.js
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* LZMA Decoder Module
|
|
3
|
-
*
|
|
4
|
-
* Provides both synchronous and streaming LZMA1/LZMA2 decoders.
|
|
5
|
-
*
|
|
6
|
-
* Synchronous API: Use when input is a complete Buffer
|
|
7
|
-
* Streaming API: Use with Transform streams for memory-efficient decompression
|
|
8
|
-
*
|
|
9
|
-
* LZMA1 vs LZMA2:
|
|
10
|
-
* - LZMA2 is chunked and supports true streaming with bounded memory
|
|
11
|
-
* - LZMA1 has no chunk boundaries and requires buffering all input for streaming
|
|
12
|
-
*/ // Streaming decoders (Transform streams)
|
|
13
|
-
export { createLzma2Decoder, createLzmaDecoder } from './stream/transforms.js';
|
|
14
|
-
export { decodeLzma2, Lzma2Decoder } from './sync/Lzma2Decoder.js';
|
|
15
|
-
// Synchronous decoders (for Buffer input)
|
|
16
|
-
export { decodeLzma, LzmaDecoder } from './sync/LzmaDecoder.js';
|
|
17
|
-
export { BitTreeDecoder, RangeDecoder } from './sync/RangeDecoder.js';
|
|
18
|
-
// Type exports
|
|
19
|
-
export * from './types.js';
|
|
20
|
-
/**
|
|
21
|
-
* Detect LZMA format from compressed data
|
|
22
|
-
*
|
|
23
|
-
* LZMA2 uses chunk-based framing with control bytes:
|
|
24
|
-
* - 0x00: End of stream
|
|
25
|
-
* - 0x01-0x02: Uncompressed chunks
|
|
26
|
-
* - 0x80-0xFF: LZMA compressed chunks
|
|
27
|
-
*
|
|
28
|
-
* LZMA1 is raw LZMA-compressed data (no framing)
|
|
29
|
-
*
|
|
30
|
-
* @param data - Compressed data to analyze
|
|
31
|
-
* @returns 'lzma1' for LZMA1, 'lzma2' for LZMA2
|
|
32
|
-
*/ export function detectFormat(data) {
|
|
33
|
-
if (data.length === 0) {
|
|
34
|
-
// Default to LZMA2 for empty data (matches LZMA2 decoder behavior)
|
|
35
|
-
return 'lzma2';
|
|
36
|
-
}
|
|
37
|
-
const firstByte = data[0];
|
|
38
|
-
// LZMA2 control bytes: 0x00, 0x01, 0x02, or 0x80-0xFF
|
|
39
|
-
if (firstByte === 0x00 || firstByte === 0x01 || firstByte === 0x02 || firstByte >= 0x80 && firstByte <= 0xff) {
|
|
40
|
-
return 'lzma2';
|
|
41
|
-
}
|
|
42
|
-
// All other values indicate LZMA1 (raw LZMA data)
|
|
43
|
-
return 'lzma1';
|
|
44
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/iterators/7z-iterator/src/lzma/index.ts"],"sourcesContent":["/**\n * LZMA Decoder Module\n *\n * Provides both synchronous and streaming LZMA1/LZMA2 decoders.\n *\n * Synchronous API: Use when input is a complete Buffer\n * Streaming API: Use with Transform streams for memory-efficient decompression\n *\n * LZMA1 vs LZMA2:\n * - LZMA2 is chunked and supports true streaming with bounded memory\n * - LZMA1 has no chunk boundaries and requires buffering all input for streaming\n */\n\n// Streaming decoders (Transform streams)\nexport { createLzma2Decoder, createLzmaDecoder } from './stream/transforms.ts';\nexport { decodeLzma2, Lzma2Decoder } from './sync/Lzma2Decoder.ts';\n// Synchronous decoders (for Buffer input)\nexport { decodeLzma, LzmaDecoder } from './sync/LzmaDecoder.ts';\nexport { BitTreeDecoder, RangeDecoder } from './sync/RangeDecoder.ts';\n// Type exports\nexport * from './types.ts';\n\n/**\n * Detect LZMA format from compressed data\n *\n * LZMA2 uses chunk-based framing with control bytes:\n * - 0x00: End of stream\n * - 0x01-0x02: Uncompressed chunks\n * - 0x80-0xFF: LZMA compressed chunks\n *\n * LZMA1 is raw LZMA-compressed data (no framing)\n *\n * @param data - Compressed data to analyze\n * @returns 'lzma1' for LZMA1, 'lzma2' for LZMA2\n */\nexport function detectFormat(data: Buffer): 'lzma1' | 'lzma2' {\n if (data.length === 0) {\n // Default to LZMA2 for empty data (matches LZMA2 decoder behavior)\n return 'lzma2';\n }\n\n const firstByte = data[0];\n\n // LZMA2 control bytes: 0x00, 0x01, 0x02, or 0x80-0xFF\n if (firstByte === 0x00 || firstByte === 0x01 || firstByte === 0x02 || (firstByte >= 0x80 && firstByte <= 0xff)) {\n return 'lzma2';\n }\n\n // All other values indicate LZMA1 (raw LZMA data)\n return 'lzma1';\n}\n"],"names":["createLzma2Decoder","createLzmaDecoder","decodeLzma2","Lzma2Decoder","decodeLzma","LzmaDecoder","BitTreeDecoder","RangeDecoder","detectFormat","data","length","firstByte"],"mappings":"AAAA;;;;;;;;;;;CAWC,GAED,yCAAyC;AACzC,SAASA,kBAAkB,EAAEC,iBAAiB,QAAQ,yBAAyB;AAC/E,SAASC,WAAW,EAAEC,YAAY,QAAQ,yBAAyB;AACnE,0CAA0C;AAC1C,SAASC,UAAU,EAAEC,WAAW,QAAQ,wBAAwB;AAChE,SAASC,cAAc,EAAEC,YAAY,QAAQ,yBAAyB;AACtE,eAAe;AACf,cAAc,aAAa;AAE3B;;;;;;;;;;;;CAYC,GACD,OAAO,SAASC,aAAaC,IAAY;IACvC,IAAIA,KAAKC,MAAM,KAAK,GAAG;QACrB,mEAAmE;QACnE,OAAO;IACT;IAEA,MAAMC,YAAYF,IAAI,CAAC,EAAE;IAEzB,sDAAsD;IACtD,IAAIE,cAAc,QAAQA,cAAc,QAAQA,cAAc,QAASA,aAAa,QAAQA,aAAa,MAAO;QAC9G,OAAO;IACT;IAEA,kDAAkD;IAClD,OAAO;AACT"}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* LZMA Transform Stream Wrappers
|
|
3
|
-
*
|
|
4
|
-
* Provides Transform streams for LZMA1 and LZMA2 decompression.
|
|
5
|
-
*
|
|
6
|
-
* LZMA2 streaming works by buffering until a complete chunk is available,
|
|
7
|
-
* then decoding synchronously. LZMA2 chunks are bounded in size (~2MB max
|
|
8
|
-
* uncompressed), so memory usage is predictable and bounded.
|
|
9
|
-
*
|
|
10
|
-
* Performance Optimization:
|
|
11
|
-
* - Uses OutputSink pattern for zero-copy output during decode
|
|
12
|
-
* - Each decoded byte written directly to stream (not buffered then copied)
|
|
13
|
-
* - ~4x faster than previous buffering approach
|
|
14
|
-
*
|
|
15
|
-
* True byte-by-byte async LZMA streaming would require rewriting the entire
|
|
16
|
-
* decoder with continuation-passing style, which is complex and not worth
|
|
17
|
-
* the effort given LZMA2's chunked format.
|
|
18
|
-
*/
|
|
19
|
-
import { Transform } from 'extract-base-iterator';
|
|
20
|
-
/**
|
|
21
|
-
* Create an LZMA2 decoder Transform stream
|
|
22
|
-
*
|
|
23
|
-
* This is a streaming decoder that processes LZMA2 chunks incrementally.
|
|
24
|
-
* Memory usage is O(dictionary_size + max_chunk_size) instead of O(folder_size).
|
|
25
|
-
*
|
|
26
|
-
* @param properties - 1-byte LZMA2 properties (dictionary size)
|
|
27
|
-
* @returns Transform stream that decompresses LZMA2 data
|
|
28
|
-
*/
|
|
29
|
-
export declare function createLzma2Decoder(properties: Buffer | Uint8Array): InstanceType<typeof Transform>;
|
|
30
|
-
/**
|
|
31
|
-
* Create an LZMA1 decoder Transform stream
|
|
32
|
-
*
|
|
33
|
-
* Note: LZMA1 has no chunk boundaries, so this requires knowing the
|
|
34
|
-
* uncompressed size upfront. The stream buffers all input, then
|
|
35
|
-
* decompresses when complete.
|
|
36
|
-
*
|
|
37
|
-
* For true streaming, use LZMA2 which has built-in chunking.
|
|
38
|
-
*
|
|
39
|
-
* Optimization: Pre-allocates input buffer and copies chunks once,
|
|
40
|
-
* avoiding the double-buffering of Buffer.concat().
|
|
41
|
-
*
|
|
42
|
-
* @param properties - 5-byte LZMA properties
|
|
43
|
-
* @param unpackSize - Expected uncompressed size
|
|
44
|
-
* @returns Transform stream that decompresses LZMA1 data
|
|
45
|
-
*/
|
|
46
|
-
export declare function createLzmaDecoder(properties: Buffer | Uint8Array, unpackSize: number): InstanceType<typeof Transform>;
|