xz-compat 1.1.4 → 1.2.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/dist/cjs/lzma/lib/Lzma2ChunkParser.d.cts +4 -3
- package/dist/cjs/lzma/lib/Lzma2ChunkParser.d.ts +4 -3
- package/dist/cjs/lzma/lib/Lzma2ChunkParser.js +24 -14
- package/dist/cjs/lzma/lib/Lzma2ChunkParser.js.map +1 -1
- package/dist/cjs/lzma/sync/Lzma2Decoder.d.cts +1 -2
- package/dist/cjs/lzma/sync/Lzma2Decoder.d.ts +1 -2
- package/dist/cjs/lzma/sync/Lzma2Decoder.js +74 -74
- package/dist/cjs/lzma/sync/Lzma2Decoder.js.map +1 -1
- package/dist/cjs/sevenz.d.cts +5 -4
- package/dist/cjs/sevenz.d.ts +5 -4
- package/dist/cjs/sevenz.js +6 -2
- package/dist/cjs/sevenz.js.map +1 -1
- package/dist/esm/lzma/lib/Lzma2ChunkParser.d.ts +4 -3
- package/dist/esm/lzma/lib/Lzma2ChunkParser.js +25 -15
- package/dist/esm/lzma/lib/Lzma2ChunkParser.js.map +1 -1
- package/dist/esm/lzma/sync/Lzma2Decoder.d.ts +1 -2
- package/dist/esm/lzma/sync/Lzma2Decoder.js +72 -72
- package/dist/esm/lzma/sync/Lzma2Decoder.js.map +1 -1
- package/dist/esm/sevenz.d.ts +5 -4
- package/dist/esm/sevenz.js +6 -2
- package/dist/esm/sevenz.js.map +1 -1
- package/package.json +2 -2
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
* 0xC0-0xDF = LZMA chunk, reset state + new properties
|
|
14
14
|
* 0xE0-0xFF = LZMA chunk, reset dictionary + state + new properties
|
|
15
15
|
*/
|
|
16
|
+
import type { BufferLike } from 'extract-base-iterator';
|
|
16
17
|
/**
|
|
17
18
|
* LZMA properties extracted from chunk header
|
|
18
19
|
*/
|
|
@@ -53,11 +54,11 @@ export type ParseResult = {
|
|
|
53
54
|
/**
|
|
54
55
|
* Parse an LZMA2 chunk header
|
|
55
56
|
*
|
|
56
|
-
* @param input - Input buffer
|
|
57
|
+
* @param input - Input buffer or BufferList
|
|
57
58
|
* @param offset - Offset to start parsing
|
|
58
59
|
* @returns Parsed chunk info or number of bytes needed
|
|
59
60
|
*/
|
|
60
|
-
export declare function parseLzma2ChunkHeader(input:
|
|
61
|
+
export declare function parseLzma2ChunkHeader(input: BufferLike, offset: number): ParseResult;
|
|
61
62
|
/** Result type for hasCompleteChunk with totalSize included on success */
|
|
62
63
|
export type CompleteChunkResult = {
|
|
63
64
|
success: true;
|
|
@@ -70,4 +71,4 @@ export type CompleteChunkResult = {
|
|
|
70
71
|
/**
|
|
71
72
|
* Check if we have enough data for the complete chunk (header + data)
|
|
72
73
|
*/
|
|
73
|
-
export declare function hasCompleteChunk(input:
|
|
74
|
+
export declare function hasCompleteChunk(input: BufferLike, offset: number): CompleteChunkResult;
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
* 0xC0-0xDF = LZMA chunk, reset state + new properties
|
|
14
14
|
* 0xE0-0xFF = LZMA chunk, reset dictionary + state + new properties
|
|
15
15
|
*/
|
|
16
|
+
import type { BufferLike } from 'extract-base-iterator';
|
|
16
17
|
/**
|
|
17
18
|
* LZMA properties extracted from chunk header
|
|
18
19
|
*/
|
|
@@ -53,11 +54,11 @@ export type ParseResult = {
|
|
|
53
54
|
/**
|
|
54
55
|
* Parse an LZMA2 chunk header
|
|
55
56
|
*
|
|
56
|
-
* @param input - Input buffer
|
|
57
|
+
* @param input - Input buffer or BufferList
|
|
57
58
|
* @param offset - Offset to start parsing
|
|
58
59
|
* @returns Parsed chunk info or number of bytes needed
|
|
59
60
|
*/
|
|
60
|
-
export declare function parseLzma2ChunkHeader(input:
|
|
61
|
+
export declare function parseLzma2ChunkHeader(input: BufferLike, offset: number): ParseResult;
|
|
61
62
|
/** Result type for hasCompleteChunk with totalSize included on success */
|
|
62
63
|
export type CompleteChunkResult = {
|
|
63
64
|
success: true;
|
|
@@ -70,4 +71,4 @@ export type CompleteChunkResult = {
|
|
|
70
71
|
/**
|
|
71
72
|
* Check if we have enough data for the complete chunk (header + data)
|
|
72
73
|
*/
|
|
73
|
-
export declare function hasCompleteChunk(input:
|
|
74
|
+
export declare function hasCompleteChunk(input: BufferLike, offset: number): CompleteChunkResult;
|
|
@@ -12,8 +12,6 @@
|
|
|
12
12
|
* 0xA0-0xBF = LZMA chunk, reset state (probabilities)
|
|
13
13
|
* 0xC0-0xDF = LZMA chunk, reset state + new properties
|
|
14
14
|
* 0xE0-0xFF = LZMA chunk, reset dictionary + state + new properties
|
|
15
|
-
*/ /**
|
|
16
|
-
* LZMA properties extracted from chunk header
|
|
17
15
|
*/ "use strict";
|
|
18
16
|
Object.defineProperty(exports, "__esModule", {
|
|
19
17
|
value: true
|
|
@@ -32,14 +30,25 @@ _export(exports, {
|
|
|
32
30
|
return parseLzma2ChunkHeader;
|
|
33
31
|
}
|
|
34
32
|
});
|
|
33
|
+
/**
|
|
34
|
+
* Read a byte from BufferLike at offset
|
|
35
|
+
*/ function readByte(input, offset) {
|
|
36
|
+
return Buffer.isBuffer(input) ? input[offset] : input.readByte(offset);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Get length of BufferLike
|
|
40
|
+
*/ function getLength(input) {
|
|
41
|
+
return Buffer.isBuffer(input) ? input.length : input.length;
|
|
42
|
+
}
|
|
35
43
|
function parseLzma2ChunkHeader(input, offset) {
|
|
36
|
-
|
|
44
|
+
var len = getLength(input);
|
|
45
|
+
if (offset >= len) {
|
|
37
46
|
return {
|
|
38
47
|
success: false,
|
|
39
48
|
needBytes: 1
|
|
40
49
|
};
|
|
41
50
|
}
|
|
42
|
-
var control = input
|
|
51
|
+
var control = readByte(input, offset);
|
|
43
52
|
// End of stream
|
|
44
53
|
if (control === 0x00) {
|
|
45
54
|
return {
|
|
@@ -58,13 +67,13 @@ function parseLzma2ChunkHeader(input, offset) {
|
|
|
58
67
|
// Uncompressed chunk
|
|
59
68
|
if (control === 0x01 || control === 0x02) {
|
|
60
69
|
// Need 3 bytes: control + 2 size bytes
|
|
61
|
-
if (offset + 3 >
|
|
70
|
+
if (offset + 3 > len) {
|
|
62
71
|
return {
|
|
63
72
|
success: false,
|
|
64
|
-
needBytes: 3 - (
|
|
73
|
+
needBytes: 3 - (len - offset)
|
|
65
74
|
};
|
|
66
75
|
}
|
|
67
|
-
var uncompSize = (input
|
|
76
|
+
var uncompSize = (readByte(input, offset + 1) << 8 | readByte(input, offset + 2)) + 1;
|
|
68
77
|
return {
|
|
69
78
|
success: true,
|
|
70
79
|
chunk: {
|
|
@@ -82,20 +91,20 @@ function parseLzma2ChunkHeader(input, offset) {
|
|
|
82
91
|
if (control >= 0x80) {
|
|
83
92
|
var hasNewProps = control >= 0xc0;
|
|
84
93
|
var minHeaderSize = hasNewProps ? 6 : 5; // control + 2 uncomp + 2 comp + (1 props)
|
|
85
|
-
if (offset + minHeaderSize >
|
|
94
|
+
if (offset + minHeaderSize > len) {
|
|
86
95
|
return {
|
|
87
96
|
success: false,
|
|
88
|
-
needBytes: minHeaderSize - (
|
|
97
|
+
needBytes: minHeaderSize - (len - offset)
|
|
89
98
|
};
|
|
90
99
|
}
|
|
91
100
|
// Parse sizes
|
|
92
101
|
var uncompHigh = control & 0x1f;
|
|
93
|
-
var uncompSize1 = (uncompHigh << 16 | input
|
|
94
|
-
var compSize = (input
|
|
102
|
+
var uncompSize1 = (uncompHigh << 16 | readByte(input, offset + 1) << 8 | readByte(input, offset + 2)) + 1;
|
|
103
|
+
var compSize = (readByte(input, offset + 3) << 8 | readByte(input, offset + 4)) + 1;
|
|
95
104
|
// Parse properties if present
|
|
96
105
|
var newProps = null;
|
|
97
106
|
if (hasNewProps) {
|
|
98
|
-
var propsByte = input
|
|
107
|
+
var propsByte = readByte(input, offset + 5);
|
|
99
108
|
var lc = propsByte % 9;
|
|
100
109
|
var remainder = ~~(propsByte / 9);
|
|
101
110
|
var lp = remainder % 5;
|
|
@@ -133,10 +142,11 @@ function hasCompleteChunk(input, offset) {
|
|
|
133
142
|
var chunk = result.chunk;
|
|
134
143
|
var dataSize = chunk.type === 'uncompressed' ? chunk.uncompSize : chunk.compSize;
|
|
135
144
|
var totalSize = chunk.headerSize + dataSize;
|
|
136
|
-
|
|
145
|
+
var len = getLength(input);
|
|
146
|
+
if (offset + totalSize > len) {
|
|
137
147
|
return {
|
|
138
148
|
success: false,
|
|
139
|
-
needBytes: totalSize - (
|
|
149
|
+
needBytes: totalSize - (len - offset)
|
|
140
150
|
};
|
|
141
151
|
}
|
|
142
152
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/iterators/xz-compat/src/lzma/lib/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:
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/iterators/xz-compat/src/lzma/lib/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\nimport type { BufferLike } from 'extract-base-iterator';\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 * Read a byte from BufferLike at offset\n */\nfunction readByte(input: BufferLike, offset: number): number {\n return Buffer.isBuffer(input) ? input[offset] : input.readByte(offset);\n}\n\n/**\n * Get length of BufferLike\n */\nfunction getLength(input: BufferLike): number {\n return Buffer.isBuffer(input) ? input.length : input.length;\n}\n\n/**\n * Parse an LZMA2 chunk header\n *\n * @param input - Input buffer or BufferList\n * @param offset - Offset to start parsing\n * @returns Parsed chunk info or number of bytes needed\n */\nexport function parseLzma2ChunkHeader(input: BufferLike, offset: number): ParseResult {\n const len = getLength(input);\n if (offset >= len) {\n return { success: false, needBytes: 1 };\n }\n\n const control = readByte(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 > len) {\n return { success: false, needBytes: 3 - (len - offset) };\n }\n\n const uncompSize = ((readByte(input, offset + 1) << 8) | readByte(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 > len) {\n return { success: false, needBytes: minHeaderSize - (len - offset) };\n }\n\n // Parse sizes\n const uncompHigh = control & 0x1f;\n const uncompSize = ((uncompHigh << 16) | (readByte(input, offset + 1) << 8) | readByte(input, offset + 2)) + 1;\n const compSize = ((readByte(input, offset + 3) << 8) | readByte(input, offset + 4)) + 1;\n\n // Parse properties if present\n let newProps: LzmaChunkProps | null = null;\n if (hasNewProps) {\n const propsByte = readByte(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: BufferLike, 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 const len = getLength(input);\n\n if (offset + totalSize > len) {\n return { success: false, needBytes: totalSize - (len - offset) };\n }\n\n return { success: true, chunk, totalSize };\n}\n"],"names":["hasCompleteChunk","parseLzma2ChunkHeader","readByte","input","offset","Buffer","isBuffer","getLength","length","len","success","needBytes","control","chunk","type","headerSize","dictReset","stateReset","newProps","uncompSize","compSize","hasNewProps","minHeaderSize","uncompHigh","propsByte","lc","remainder","lp","pb","Error","toString","result","dataSize","totalSize"],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Synchronous LZMA2 Decoder
|
|
3
3
|
*
|
|
4
4
|
* LZMA2 is a container format that wraps LZMA chunks with framing.
|
|
5
|
-
* Decodes LZMA2 data from a buffer.
|
|
5
|
+
* Decodes LZMA2 data from a buffer or BufferList.
|
|
6
6
|
*/
|
|
7
7
|
import { type BufferLike } from 'extract-base-iterator';
|
|
8
8
|
import { type OutputSink } from '../types.js';
|
|
@@ -12,7 +12,6 @@ import { type OutputSink } from '../types.js';
|
|
|
12
12
|
export declare class Lzma2Decoder {
|
|
13
13
|
private lzmaDecoder;
|
|
14
14
|
private dictionarySize;
|
|
15
|
-
private propsSet;
|
|
16
15
|
constructor(properties: Buffer | Uint8Array, outputSink?: OutputSink);
|
|
17
16
|
/**
|
|
18
17
|
* Reset the dictionary (for stream boundaries)
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Synchronous LZMA2 Decoder
|
|
3
3
|
*
|
|
4
4
|
* LZMA2 is a container format that wraps LZMA chunks with framing.
|
|
5
|
-
* Decodes LZMA2 data from a buffer.
|
|
5
|
+
* Decodes LZMA2 data from a buffer or BufferList.
|
|
6
6
|
*/
|
|
7
7
|
import { type BufferLike } from 'extract-base-iterator';
|
|
8
8
|
import { type OutputSink } from '../types.js';
|
|
@@ -12,7 +12,6 @@ import { type OutputSink } from '../types.js';
|
|
|
12
12
|
export declare class Lzma2Decoder {
|
|
13
13
|
private lzmaDecoder;
|
|
14
14
|
private dictionarySize;
|
|
15
|
-
private propsSet;
|
|
16
15
|
constructor(properties: Buffer | Uint8Array, outputSink?: OutputSink);
|
|
17
16
|
/**
|
|
18
17
|
* Reset the dictionary (for stream boundaries)
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Synchronous LZMA2 Decoder
|
|
3
3
|
*
|
|
4
4
|
* LZMA2 is a container format that wraps LZMA chunks with framing.
|
|
5
|
-
* Decodes LZMA2 data from a buffer.
|
|
5
|
+
* Decodes LZMA2 data from a buffer or BufferList.
|
|
6
6
|
*/ "use strict";
|
|
7
7
|
Object.defineProperty(exports, "__esModule", {
|
|
8
8
|
value: true
|
|
@@ -30,6 +30,19 @@ function _class_call_check(instance, Constructor) {
|
|
|
30
30
|
throw new TypeError("Cannot call a class as a function");
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* Read multiple bytes from BufferLike into a Buffer
|
|
35
|
+
*/ function readBytes(input, offset, length) {
|
|
36
|
+
if (Buffer.isBuffer(input)) {
|
|
37
|
+
return input.slice(offset, offset + length);
|
|
38
|
+
}
|
|
39
|
+
// For BufferList, create a new Buffer with the data
|
|
40
|
+
var buf = (0, _extractbaseiterator.bufferFrom)(new Array(length));
|
|
41
|
+
for(var i = 0; i < length; i++){
|
|
42
|
+
buf[i] = input.readByte(offset + i);
|
|
43
|
+
}
|
|
44
|
+
return buf;
|
|
45
|
+
}
|
|
33
46
|
var Lzma2Decoder = /*#__PURE__*/ function() {
|
|
34
47
|
"use strict";
|
|
35
48
|
function Lzma2Decoder(properties, outputSink) {
|
|
@@ -40,7 +53,6 @@ var Lzma2Decoder = /*#__PURE__*/ function() {
|
|
|
40
53
|
this.dictionarySize = (0, _typests.parseLzma2DictionarySize)(properties[0]);
|
|
41
54
|
this.lzmaDecoder = new _LzmaDecoderts.LzmaDecoder(outputSink);
|
|
42
55
|
this.lzmaDecoder.setDictionarySize(this.dictionarySize);
|
|
43
|
-
this.propsSet = false;
|
|
44
56
|
}
|
|
45
57
|
var _proto = Lzma2Decoder.prototype;
|
|
46
58
|
/**
|
|
@@ -79,12 +91,10 @@ var Lzma2Decoder = /*#__PURE__*/ function() {
|
|
|
79
91
|
* @param input - LZMA2 compressed data (Buffer or BufferList)
|
|
80
92
|
* @returns Total number of bytes written to sink
|
|
81
93
|
*/ _proto.decodeWithSink = function decodeWithSink(input) {
|
|
82
|
-
// Convert BufferList to Buffer for low-level parsing
|
|
83
|
-
var buf = Buffer.isBuffer(input) ? input : input.toBuffer();
|
|
84
94
|
var totalBytes = 0;
|
|
85
95
|
var offset = 0;
|
|
86
|
-
while(
|
|
87
|
-
var result = (0, _Lzma2ChunkParserts.parseLzma2ChunkHeader)(
|
|
96
|
+
while(true){
|
|
97
|
+
var result = (0, _Lzma2ChunkParserts.parseLzma2ChunkHeader)(input, offset);
|
|
88
98
|
if (!result.success) {
|
|
89
99
|
throw new Error('Truncated LZMA2 chunk header');
|
|
90
100
|
}
|
|
@@ -92,45 +102,31 @@ var Lzma2Decoder = /*#__PURE__*/ function() {
|
|
|
92
102
|
if (chunk.type === 'end') {
|
|
93
103
|
break;
|
|
94
104
|
}
|
|
95
|
-
// Validate we have enough data for the chunk
|
|
96
|
-
var dataSize = chunk.type === 'uncompressed' ? chunk.uncompSize : chunk.compSize;
|
|
97
|
-
if (offset + chunk.headerSize + dataSize > buf.length) {
|
|
98
|
-
throw new Error("Truncated LZMA2 ".concat(chunk.type, " data"));
|
|
99
|
-
}
|
|
100
105
|
// Handle dictionary reset
|
|
101
106
|
if (chunk.dictReset) {
|
|
102
107
|
this.lzmaDecoder.resetDictionary();
|
|
103
108
|
}
|
|
109
|
+
// Handle state reset
|
|
110
|
+
if (chunk.stateReset) {
|
|
111
|
+
this.lzmaDecoder.resetProbabilities();
|
|
112
|
+
}
|
|
113
|
+
// Apply new properties if present
|
|
114
|
+
if (chunk.newProps) {
|
|
115
|
+
var _chunk_newProps = chunk.newProps, lc = _chunk_newProps.lc, lp = _chunk_newProps.lp, pb = _chunk_newProps.pb;
|
|
116
|
+
this.lzmaDecoder.setLcLpPb(lc, lp, pb);
|
|
117
|
+
}
|
|
104
118
|
var dataOffset = offset + chunk.headerSize;
|
|
119
|
+
var useSolid = !chunk.stateReset || chunk.stateReset && !chunk.dictReset;
|
|
105
120
|
if (chunk.type === 'uncompressed') {
|
|
106
|
-
|
|
121
|
+
// Read uncompressed data directly
|
|
122
|
+
var uncompData = readBytes(input, dataOffset, chunk.uncompSize);
|
|
107
123
|
// Feed uncompressed data to dictionary so subsequent LZMA chunks can reference it
|
|
108
124
|
this.lzmaDecoder.feedUncompressed(uncompData);
|
|
109
125
|
totalBytes += uncompData.length;
|
|
110
126
|
offset = dataOffset + chunk.uncompSize;
|
|
111
127
|
} else {
|
|
112
|
-
// LZMA compressed chunk
|
|
113
|
-
|
|
114
|
-
if (chunk.newProps) {
|
|
115
|
-
var _chunk_newProps = chunk.newProps, lc = _chunk_newProps.lc, lp = _chunk_newProps.lp, pb = _chunk_newProps.pb;
|
|
116
|
-
if (!this.lzmaDecoder.setLcLpPb(lc, lp, pb)) {
|
|
117
|
-
throw new Error("Invalid LZMA properties: lc=".concat(lc, " lp=").concat(lp, " pb=").concat(pb));
|
|
118
|
-
}
|
|
119
|
-
this.propsSet = true;
|
|
120
|
-
} else {
|
|
121
|
-
// No new properties, check if we already have them
|
|
122
|
-
if (!this.propsSet) {
|
|
123
|
-
throw new Error('LZMA chunk without properties');
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
// Reset probabilities if state reset
|
|
127
|
-
if (chunk.stateReset) {
|
|
128
|
-
this.lzmaDecoder.resetProbabilities();
|
|
129
|
-
}
|
|
130
|
-
// Determine solid mode
|
|
131
|
-
var useSolid = !chunk.stateReset || chunk.stateReset && !chunk.dictReset;
|
|
132
|
-
// Decode LZMA chunk directly to sink
|
|
133
|
-
totalBytes += this.lzmaDecoder.decodeWithSink(buf, dataOffset, chunk.uncompSize, useSolid);
|
|
128
|
+
// LZMA compressed chunk - decode directly from BufferLike
|
|
129
|
+
totalBytes += this.lzmaDecoder.decodeWithSink(input, dataOffset, chunk.uncompSize, useSolid);
|
|
134
130
|
offset = dataOffset + chunk.compSize;
|
|
135
131
|
}
|
|
136
132
|
}
|
|
@@ -144,18 +140,19 @@ var Lzma2Decoder = /*#__PURE__*/ function() {
|
|
|
144
140
|
* @param unpackSize - Expected output size (optional, for pre-allocation)
|
|
145
141
|
* @returns Decompressed data
|
|
146
142
|
*/ _proto.decode = function decode(input, unpackSize) {
|
|
147
|
-
//
|
|
148
|
-
var buf = Buffer.isBuffer(input) ? input : input.toBuffer();
|
|
149
|
-
// Pre-allocate output buffer if size is known
|
|
143
|
+
// Pre-allocate output buffer if size is known and safe for this Node version
|
|
150
144
|
var outputBuffer = null;
|
|
151
145
|
var outputPos = 0;
|
|
152
146
|
var outputChunks = [];
|
|
153
|
-
|
|
147
|
+
// Use canAllocateBufferSize to dynamically check if pre-allocation is safe
|
|
148
|
+
var canPreAllocate = unpackSize && unpackSize > 0 && (0, _extractbaseiterator.canAllocateBufferSize)(unpackSize);
|
|
149
|
+
if (canPreAllocate) {
|
|
154
150
|
outputBuffer = (0, _extractbaseiterator.allocBufferUnsafe)(unpackSize);
|
|
155
151
|
}
|
|
156
152
|
var offset = 0;
|
|
157
|
-
|
|
158
|
-
|
|
153
|
+
// Parse and decode LZMA2 chunks one at a time
|
|
154
|
+
while(true){
|
|
155
|
+
var result = (0, _Lzma2ChunkParserts.parseLzma2ChunkHeader)(input, offset);
|
|
159
156
|
if (!result.success) {
|
|
160
157
|
throw new Error('Truncated LZMA2 chunk header');
|
|
161
158
|
}
|
|
@@ -163,18 +160,25 @@ var Lzma2Decoder = /*#__PURE__*/ function() {
|
|
|
163
160
|
if (chunk.type === 'end') {
|
|
164
161
|
break;
|
|
165
162
|
}
|
|
166
|
-
|
|
167
|
-
var dataSize = chunk.type === 'uncompressed' ? chunk.uncompSize : chunk.compSize;
|
|
168
|
-
if (offset + chunk.headerSize + dataSize > buf.length) {
|
|
169
|
-
throw new Error("Truncated LZMA2 ".concat(chunk.type, " data"));
|
|
170
|
-
}
|
|
163
|
+
var dataOffset = offset + chunk.headerSize;
|
|
171
164
|
// Handle dictionary reset
|
|
172
165
|
if (chunk.dictReset) {
|
|
173
166
|
this.lzmaDecoder.resetDictionary();
|
|
174
167
|
}
|
|
175
|
-
|
|
168
|
+
// Handle state reset
|
|
169
|
+
if (chunk.stateReset) {
|
|
170
|
+
this.lzmaDecoder.resetProbabilities();
|
|
171
|
+
}
|
|
172
|
+
// Apply new properties if present
|
|
173
|
+
if (chunk.newProps) {
|
|
174
|
+
var _chunk_newProps = chunk.newProps, lc = _chunk_newProps.lc, lp = _chunk_newProps.lp, pb = _chunk_newProps.pb;
|
|
175
|
+
this.lzmaDecoder.setLcLpPb(lc, lp, pb);
|
|
176
|
+
}
|
|
177
|
+
// Determine solid mode
|
|
178
|
+
var useSolid = !chunk.stateReset || chunk.stateReset && !chunk.dictReset;
|
|
176
179
|
if (chunk.type === 'uncompressed') {
|
|
177
|
-
|
|
180
|
+
// Read uncompressed data
|
|
181
|
+
var uncompData = readBytes(input, dataOffset, chunk.uncompSize);
|
|
178
182
|
// Copy to output
|
|
179
183
|
if (outputBuffer) {
|
|
180
184
|
uncompData.copy(outputBuffer, outputPos);
|
|
@@ -186,34 +190,14 @@ var Lzma2Decoder = /*#__PURE__*/ function() {
|
|
|
186
190
|
this.lzmaDecoder.feedUncompressed(uncompData);
|
|
187
191
|
offset = dataOffset + chunk.uncompSize;
|
|
188
192
|
} else {
|
|
189
|
-
// LZMA compressed chunk
|
|
190
|
-
// Apply new properties if present
|
|
191
|
-
if (chunk.newProps) {
|
|
192
|
-
var _chunk_newProps = chunk.newProps, lc = _chunk_newProps.lc, lp = _chunk_newProps.lp, pb = _chunk_newProps.pb;
|
|
193
|
-
if (!this.lzmaDecoder.setLcLpPb(lc, lp, pb)) {
|
|
194
|
-
throw new Error("Invalid LZMA properties: lc=".concat(lc, " lp=").concat(lp, " pb=").concat(pb));
|
|
195
|
-
}
|
|
196
|
-
this.propsSet = true;
|
|
197
|
-
} else {
|
|
198
|
-
// No new properties, check if we already have them
|
|
199
|
-
if (!this.propsSet) {
|
|
200
|
-
throw new Error('LZMA chunk without properties');
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
// Reset probabilities if state reset
|
|
204
|
-
if (chunk.stateReset) {
|
|
205
|
-
this.lzmaDecoder.resetProbabilities();
|
|
206
|
-
}
|
|
207
|
-
// Determine solid mode - preserve dictionary if not resetting state or if only resetting state (not dict)
|
|
208
|
-
var useSolid = !chunk.stateReset || chunk.stateReset && !chunk.dictReset;
|
|
209
|
-
// Decode LZMA chunk - use zero-copy when we have pre-allocated buffer
|
|
193
|
+
// LZMA compressed chunk - decode directly from BufferLike
|
|
210
194
|
if (outputBuffer) {
|
|
211
195
|
// Zero-copy: decode directly into caller's buffer
|
|
212
|
-
var bytesWritten = this.lzmaDecoder.decodeToBuffer(
|
|
196
|
+
var bytesWritten = this.lzmaDecoder.decodeToBuffer(input, dataOffset, chunk.uncompSize, outputBuffer, outputPos, useSolid);
|
|
213
197
|
outputPos += bytesWritten;
|
|
214
198
|
} else {
|
|
215
199
|
// No pre-allocation: decode to new buffer and collect chunks
|
|
216
|
-
var chunkData =
|
|
200
|
+
var chunkData = readBytes(input, dataOffset, chunk.compSize);
|
|
217
201
|
var decoded = this.lzmaDecoder.decode(chunkData, 0, chunk.uncompSize, useSolid);
|
|
218
202
|
outputChunks.push(decoded);
|
|
219
203
|
}
|
|
@@ -224,17 +208,33 @@ var Lzma2Decoder = /*#__PURE__*/ function() {
|
|
|
224
208
|
if (outputBuffer) {
|
|
225
209
|
return outputPos < outputBuffer.length ? outputBuffer.slice(0, outputPos) : outputBuffer;
|
|
226
210
|
}
|
|
227
|
-
|
|
211
|
+
// Use bufferConcat which handles large buffers safely via pairwise combination
|
|
212
|
+
return (0, _extractbaseiterator.bufferConcat)(outputChunks);
|
|
228
213
|
};
|
|
229
214
|
return Lzma2Decoder;
|
|
230
215
|
}();
|
|
231
216
|
function decodeLzma2(input, properties, unpackSize, outputSink) {
|
|
232
|
-
|
|
217
|
+
// For very large outputs on old Node versions, we cannot return a single Buffer
|
|
218
|
+
// Use streaming mode internally to handle large outputs on modern Node
|
|
219
|
+
if (!outputSink && unpackSize && unpackSize > 0 && !(0, _extractbaseiterator.canAllocateBufferSize)(unpackSize)) {
|
|
220
|
+
// Large output - use streaming mode with internal chunking
|
|
221
|
+
var chunks = [];
|
|
222
|
+
var sink = {
|
|
223
|
+
write: function write(buffer) {
|
|
224
|
+
chunks.push(buffer);
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
var decoder = new Lzma2Decoder(properties, sink);
|
|
228
|
+
decoder.decodeWithSink(input);
|
|
229
|
+
// Combine chunks at the end - use bufferConcat for safe combination
|
|
230
|
+
return (0, _extractbaseiterator.bufferConcat)(chunks);
|
|
231
|
+
}
|
|
232
|
+
var decoder1 = new Lzma2Decoder(properties, outputSink);
|
|
233
233
|
if (outputSink) {
|
|
234
234
|
// Zero-copy mode: write to sink during decode
|
|
235
|
-
return
|
|
235
|
+
return decoder1.decodeWithSink(input);
|
|
236
236
|
}
|
|
237
237
|
// Buffering mode: returns Buffer (zero-copy)
|
|
238
|
-
return
|
|
238
|
+
return decoder1.decode(input, unpackSize);
|
|
239
239
|
}
|
|
240
240
|
/* 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 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/iterators/xz-compat/src/lzma/sync/Lzma2Decoder.ts"],"sourcesContent":["/**\n * Synchronous LZMA2 Decoder\n *\n * LZMA2 is a container format that wraps LZMA chunks with framing.\n * Decodes LZMA2 data from a buffer.\n */\n\nimport { allocBufferUnsafe, type BufferLike } from 'extract-base-iterator';\nimport { parseLzma2ChunkHeader } from '../lib/Lzma2ChunkParser.ts';\nimport { type OutputSink, parseLzma2DictionarySize } from '../types.ts';\nimport { LzmaDecoder } from './LzmaDecoder.ts';\n\n/**\n * Synchronous LZMA2 decoder\n */\nexport class Lzma2Decoder {\n private lzmaDecoder: LzmaDecoder;\n private dictionarySize: number;\n private propsSet: boolean;\n\n constructor(properties: Buffer | Uint8Array, outputSink?: OutputSink) {\n if (!properties || properties.length < 1) {\n throw new Error('LZMA2 requires properties byte');\n }\n\n this.dictionarySize = parseLzma2DictionarySize(properties[0]);\n this.lzmaDecoder = new LzmaDecoder(outputSink);\n this.lzmaDecoder.setDictionarySize(this.dictionarySize);\n this.propsSet = false;\n }\n\n /**\n * Reset the dictionary (for stream boundaries)\n */\n resetDictionary(): void {\n this.lzmaDecoder.resetDictionary();\n }\n\n /**\n * Reset all probability models (for stream boundaries)\n */\n resetProbabilities(): void {\n this.lzmaDecoder.resetProbabilities();\n }\n\n /**\n * Set LZMA properties\n */\n setLcLpPb(lc: number, lp: number, pb: number): boolean {\n return this.lzmaDecoder.setLcLpPb(lc, lp, pb);\n }\n\n /**\n * Feed uncompressed data to the dictionary (for subsequent LZMA chunks)\n */\n feedUncompressed(data: Buffer): void {\n this.lzmaDecoder.feedUncompressed(data);\n }\n\n /**\n * Decode raw LZMA data (used internally for LZMA2 chunks)\n * @param input - LZMA compressed data\n * @param offset - Input offset\n * @param outSize - Expected output size\n * @param solid - Use solid mode\n * @returns Decompressed data\n */\n decodeLzmaData(input: Buffer, offset: number, outSize: number, solid = false): Buffer {\n return this.lzmaDecoder.decode(input, offset, outSize, solid);\n }\n\n /**\n * Decode LZMA2 data with streaming output\n * @param input - LZMA2 compressed data (Buffer or BufferList)\n * @returns Total number of bytes written to sink\n */\n decodeWithSink(input: BufferLike): number {\n // Convert BufferList to Buffer for low-level parsing\n const buf = Buffer.isBuffer(input) ? input : input.toBuffer();\n let totalBytes = 0;\n let offset = 0;\n\n while (offset < buf.length) {\n const result = parseLzma2ChunkHeader(buf, offset);\n\n if (!result.success) {\n throw new Error('Truncated LZMA2 chunk header');\n }\n\n const chunk = result.chunk;\n\n if (chunk.type === 'end') {\n break;\n }\n\n // Validate we have enough data for the chunk\n const dataSize = chunk.type === 'uncompressed' ? chunk.uncompSize : chunk.compSize;\n if (offset + chunk.headerSize + dataSize > buf.length) {\n throw new Error(`Truncated LZMA2 ${chunk.type} data`);\n }\n\n // Handle dictionary reset\n if (chunk.dictReset) {\n this.lzmaDecoder.resetDictionary();\n }\n\n const dataOffset = offset + chunk.headerSize;\n\n if (chunk.type === 'uncompressed') {\n const uncompData = buf.slice(dataOffset, dataOffset + chunk.uncompSize);\n\n // Feed uncompressed data to dictionary so subsequent LZMA chunks can reference it\n this.lzmaDecoder.feedUncompressed(uncompData);\n\n totalBytes += uncompData.length;\n offset = dataOffset + chunk.uncompSize;\n } else {\n // LZMA compressed chunk\n\n // Apply new properties if present\n if (chunk.newProps) {\n const { lc, lp, pb } = chunk.newProps;\n if (!this.lzmaDecoder.setLcLpPb(lc, lp, pb)) {\n throw new Error(`Invalid LZMA properties: lc=${lc} lp=${lp} pb=${pb}`);\n }\n this.propsSet = true;\n } else {\n // No new properties, check if we already have them\n if (!this.propsSet) {\n throw new Error('LZMA chunk without properties');\n }\n }\n\n // Reset probabilities if state reset\n if (chunk.stateReset) {\n this.lzmaDecoder.resetProbabilities();\n }\n\n // Determine solid mode\n const useSolid = !chunk.stateReset || (chunk.stateReset && !chunk.dictReset);\n\n // Decode LZMA chunk directly to sink\n totalBytes += this.lzmaDecoder.decodeWithSink(buf, dataOffset, chunk.uncompSize, useSolid);\n\n offset = dataOffset + chunk.compSize;\n }\n }\n\n // Flush any remaining data in the OutWindow\n this.lzmaDecoder.flushOutWindow();\n\n return totalBytes;\n }\n\n /**\n * Decode LZMA2 data\n * @param input - LZMA2 compressed data (Buffer or BufferList)\n * @param unpackSize - Expected output size (optional, for pre-allocation)\n * @returns Decompressed data\n */\n decode(input: BufferLike, unpackSize?: number): Buffer {\n // Convert BufferList to Buffer for low-level parsing\n const buf = Buffer.isBuffer(input) ? input : input.toBuffer();\n\n // Pre-allocate output buffer if size is known\n let outputBuffer: Buffer | null = null;\n let outputPos = 0;\n const outputChunks: Buffer[] = [];\n\n if (unpackSize && unpackSize > 0) {\n outputBuffer = allocBufferUnsafe(unpackSize);\n }\n\n let offset = 0;\n\n while (offset < buf.length) {\n const result = parseLzma2ChunkHeader(buf, offset);\n\n if (!result.success) {\n throw new Error('Truncated LZMA2 chunk header');\n }\n\n const chunk = result.chunk;\n\n if (chunk.type === 'end') {\n break;\n }\n\n // Validate we have enough data for the chunk\n const dataSize = chunk.type === 'uncompressed' ? chunk.uncompSize : chunk.compSize;\n if (offset + chunk.headerSize + dataSize > buf.length) {\n throw new Error(`Truncated LZMA2 ${chunk.type} data`);\n }\n\n // Handle dictionary reset\n if (chunk.dictReset) {\n this.lzmaDecoder.resetDictionary();\n }\n\n const dataOffset = offset + chunk.headerSize;\n\n if (chunk.type === 'uncompressed') {\n const uncompData = buf.slice(dataOffset, dataOffset + chunk.uncompSize);\n\n // Copy to output\n if (outputBuffer) {\n uncompData.copy(outputBuffer, outputPos);\n outputPos += uncompData.length;\n } else {\n outputChunks.push(uncompData);\n }\n\n // Feed uncompressed data to dictionary so subsequent LZMA chunks can reference it\n this.lzmaDecoder.feedUncompressed(uncompData);\n\n offset = dataOffset + chunk.uncompSize;\n } else {\n // LZMA compressed chunk\n\n // Apply new properties if present\n if (chunk.newProps) {\n const { lc, lp, pb } = chunk.newProps;\n if (!this.lzmaDecoder.setLcLpPb(lc, lp, pb)) {\n throw new Error(`Invalid LZMA properties: lc=${lc} lp=${lp} pb=${pb}`);\n }\n this.propsSet = true;\n } else {\n // No new properties, check if we already have them\n if (!this.propsSet) {\n throw new Error('LZMA chunk without properties');\n }\n }\n\n // Reset probabilities if state reset\n if (chunk.stateReset) {\n this.lzmaDecoder.resetProbabilities();\n }\n\n // Determine solid mode - preserve dictionary if not resetting state or if only resetting state (not dict)\n const useSolid = !chunk.stateReset || (chunk.stateReset && !chunk.dictReset);\n\n // Decode LZMA chunk - use zero-copy when we have pre-allocated buffer\n if (outputBuffer) {\n // Zero-copy: decode directly into caller's buffer\n const bytesWritten = this.lzmaDecoder.decodeToBuffer(buf, dataOffset, chunk.uncompSize, outputBuffer, outputPos, useSolid);\n outputPos += bytesWritten;\n } else {\n // No pre-allocation: decode to new buffer and collect chunks\n const chunkData = buf.slice(dataOffset, dataOffset + chunk.compSize);\n const decoded = this.lzmaDecoder.decode(chunkData, 0, chunk.uncompSize, useSolid);\n outputChunks.push(decoded);\n }\n\n offset = dataOffset + chunk.compSize;\n }\n }\n\n // Return pre-allocated buffer or concatenated chunks\n if (outputBuffer) {\n return outputPos < outputBuffer.length ? outputBuffer.slice(0, outputPos) : outputBuffer;\n }\n return Buffer.concat(outputChunks);\n }\n}\n\n/**\n * Decode LZMA2 data synchronously\n * @param input - LZMA2 compressed data (Buffer or BufferList)\n * @param properties - 1-byte properties (dictionary size)\n * @param unpackSize - Expected output size (optional, autodetects if not provided)\n * @param outputSink - Optional output sink with write callback for streaming (returns bytes written)\n * @returns Decompressed data (or bytes written if outputSink provided)\n */\nexport function decodeLzma2(input: BufferLike, properties: Buffer | Uint8Array, unpackSize?: number, outputSink?: { write(buffer: Buffer): void }): Buffer | number {\n const decoder = new Lzma2Decoder(properties, outputSink as OutputSink);\n if (outputSink) {\n // Zero-copy mode: write to sink during decode\n return decoder.decodeWithSink(input);\n }\n // Buffering mode: returns Buffer (zero-copy)\n return decoder.decode(input, unpackSize);\n}\n"],"names":["Lzma2Decoder","decodeLzma2","properties","outputSink","length","Error","dictionarySize","parseLzma2DictionarySize","lzmaDecoder","LzmaDecoder","setDictionarySize","propsSet","resetDictionary","resetProbabilities","setLcLpPb","lc","lp","pb","feedUncompressed","data","decodeLzmaData","input","offset","outSize","solid","decode","decodeWithSink","buf","Buffer","isBuffer","toBuffer","totalBytes","result","parseLzma2ChunkHeader","success","chunk","type","dataSize","uncompSize","compSize","headerSize","dictReset","dataOffset","uncompData","slice","newProps","stateReset","useSolid","flushOutWindow","unpackSize","outputBuffer","outputPos","outputChunks","allocBufferUnsafe","copy","push","bytesWritten","decodeToBuffer","chunkData","decoded","concat","decoder"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/iterators/xz-compat/src/lzma/sync/Lzma2Decoder.ts"],"sourcesContent":["/**\n * Synchronous LZMA2 Decoder\n *\n * LZMA2 is a container format that wraps LZMA chunks with framing.\n * Decodes LZMA2 data from a buffer or BufferList.\n */\n\nimport { allocBufferUnsafe, type BufferLike, bufferConcat, bufferFrom, canAllocateBufferSize } from 'extract-base-iterator';\nimport { parseLzma2ChunkHeader } from '../lib/Lzma2ChunkParser.ts';\nimport { type OutputSink, parseLzma2DictionarySize } from '../types.ts';\nimport { LzmaDecoder } from './LzmaDecoder.ts';\n\n/**\n * Read multiple bytes from BufferLike into a Buffer\n */\nfunction readBytes(input: BufferLike, offset: number, length: number): Buffer {\n if (Buffer.isBuffer(input)) {\n return input.slice(offset, offset + length);\n }\n // For BufferList, create a new Buffer with the data\n const buf = bufferFrom(new Array(length));\n for (let i = 0; i < length; i++) {\n buf[i] = input.readByte(offset + i);\n }\n return buf;\n}\n\n/**\n * Synchronous LZMA2 decoder\n */\nexport class Lzma2Decoder {\n private lzmaDecoder: LzmaDecoder;\n private dictionarySize: number;\n\n constructor(properties: Buffer | Uint8Array, outputSink?: OutputSink) {\n if (!properties || properties.length < 1) {\n throw new Error('LZMA2 requires properties byte');\n }\n\n this.dictionarySize = parseLzma2DictionarySize(properties[0]);\n this.lzmaDecoder = new LzmaDecoder(outputSink);\n this.lzmaDecoder.setDictionarySize(this.dictionarySize);\n }\n\n /**\n * Reset the dictionary (for stream boundaries)\n */\n resetDictionary(): void {\n this.lzmaDecoder.resetDictionary();\n }\n\n /**\n * Reset all probability models (for stream boundaries)\n */\n resetProbabilities(): void {\n this.lzmaDecoder.resetProbabilities();\n }\n\n /**\n * Set LZMA properties\n */\n setLcLpPb(lc: number, lp: number, pb: number): boolean {\n return this.lzmaDecoder.setLcLpPb(lc, lp, pb);\n }\n\n /**\n * Feed uncompressed data to the dictionary (for subsequent LZMA chunks)\n */\n feedUncompressed(data: Buffer): void {\n this.lzmaDecoder.feedUncompressed(data);\n }\n\n /**\n * Decode raw LZMA data (used internally for LZMA2 chunks)\n * @param input - LZMA compressed data\n * @param offset - Input offset\n * @param outSize - Expected output size\n * @param solid - Use solid mode\n * @returns Decompressed data\n */\n decodeLzmaData(input: Buffer, offset: number, outSize: number, solid = false): Buffer {\n return this.lzmaDecoder.decode(input, offset, outSize, solid);\n }\n\n /**\n * Decode LZMA2 data with streaming output\n * @param input - LZMA2 compressed data (Buffer or BufferList)\n * @returns Total number of bytes written to sink\n */\n decodeWithSink(input: BufferLike): number {\n let totalBytes = 0;\n let offset = 0;\n\n while (true) {\n const result = parseLzma2ChunkHeader(input, offset);\n\n if (!result.success) {\n throw new Error('Truncated LZMA2 chunk header');\n }\n\n const chunk = result.chunk;\n\n if (chunk.type === 'end') {\n break;\n }\n\n // Handle dictionary reset\n if (chunk.dictReset) {\n this.lzmaDecoder.resetDictionary();\n }\n\n // Handle state reset\n if (chunk.stateReset) {\n this.lzmaDecoder.resetProbabilities();\n }\n\n // Apply new properties if present\n if (chunk.newProps) {\n const { lc, lp, pb } = chunk.newProps;\n this.lzmaDecoder.setLcLpPb(lc, lp, pb);\n }\n\n const dataOffset = offset + chunk.headerSize;\n const useSolid = !chunk.stateReset || (chunk.stateReset && !chunk.dictReset);\n\n if (chunk.type === 'uncompressed') {\n // Read uncompressed data directly\n const uncompData = readBytes(input, dataOffset, chunk.uncompSize);\n\n // Feed uncompressed data to dictionary so subsequent LZMA chunks can reference it\n this.lzmaDecoder.feedUncompressed(uncompData);\n\n totalBytes += uncompData.length;\n offset = dataOffset + chunk.uncompSize;\n } else {\n // LZMA compressed chunk - decode directly from BufferLike\n totalBytes += this.lzmaDecoder.decodeWithSink(input, dataOffset, chunk.uncompSize, useSolid);\n\n offset = dataOffset + chunk.compSize;\n }\n }\n\n // Flush any remaining data in the OutWindow\n this.lzmaDecoder.flushOutWindow();\n\n return totalBytes;\n }\n\n /**\n * Decode LZMA2 data\n * @param input - LZMA2 compressed data (Buffer or BufferList)\n * @param unpackSize - Expected output size (optional, for pre-allocation)\n * @returns Decompressed data\n */\n decode(input: BufferLike, unpackSize?: number): Buffer {\n // Pre-allocate output buffer if size is known and safe for this Node version\n let outputBuffer: Buffer | null = null;\n let outputPos = 0;\n const outputChunks: Buffer[] = [];\n\n // Use canAllocateBufferSize to dynamically check if pre-allocation is safe\n const canPreAllocate = unpackSize && unpackSize > 0 && canAllocateBufferSize(unpackSize);\n if (canPreAllocate) {\n outputBuffer = allocBufferUnsafe(unpackSize);\n }\n\n let offset = 0;\n\n // Parse and decode LZMA2 chunks one at a time\n while (true) {\n const result = parseLzma2ChunkHeader(input, offset);\n\n if (!result.success) {\n throw new Error('Truncated LZMA2 chunk header');\n }\n\n const chunk = result.chunk;\n\n if (chunk.type === 'end') {\n break;\n }\n\n const dataOffset = offset + chunk.headerSize;\n\n // Handle dictionary reset\n if (chunk.dictReset) {\n this.lzmaDecoder.resetDictionary();\n }\n\n // Handle state reset\n if (chunk.stateReset) {\n this.lzmaDecoder.resetProbabilities();\n }\n\n // Apply new properties if present\n if (chunk.newProps) {\n const { lc, lp, pb } = chunk.newProps;\n this.lzmaDecoder.setLcLpPb(lc, lp, pb);\n }\n\n // Determine solid mode\n const useSolid = !chunk.stateReset || (chunk.stateReset && !chunk.dictReset);\n\n if (chunk.type === 'uncompressed') {\n // Read uncompressed data\n const uncompData = readBytes(input, dataOffset, chunk.uncompSize);\n\n // Copy to output\n if (outputBuffer) {\n uncompData.copy(outputBuffer, outputPos);\n outputPos += uncompData.length;\n } else {\n outputChunks.push(uncompData);\n }\n\n // Feed uncompressed data to dictionary so subsequent LZMA chunks can reference it\n this.lzmaDecoder.feedUncompressed(uncompData);\n\n offset = dataOffset + chunk.uncompSize;\n } else {\n // LZMA compressed chunk - decode directly from BufferLike\n if (outputBuffer) {\n // Zero-copy: decode directly into caller's buffer\n const bytesWritten = this.lzmaDecoder.decodeToBuffer(input, dataOffset, chunk.uncompSize, outputBuffer, outputPos, useSolid);\n outputPos += bytesWritten;\n } else {\n // No pre-allocation: decode to new buffer and collect chunks\n const chunkData = readBytes(input, dataOffset, chunk.compSize);\n const decoded = this.lzmaDecoder.decode(chunkData, 0, chunk.uncompSize, useSolid);\n outputChunks.push(decoded);\n }\n\n offset = dataOffset + chunk.compSize;\n }\n }\n\n // Return pre-allocated buffer or concatenated chunks\n if (outputBuffer) {\n return outputPos < outputBuffer.length ? outputBuffer.slice(0, outputPos) : outputBuffer;\n }\n // Use bufferConcat which handles large buffers safely via pairwise combination\n return bufferConcat(outputChunks);\n }\n}\n\n/**\n * Decode LZMA2 data synchronously\n * @param input - LZMA2 compressed data (Buffer or BufferList)\n * @param properties - 1-byte properties (dictionary size)\n * @param unpackSize - Expected output size (optional, autodetects if not provided)\n * @param outputSink - Optional output sink with write callback for streaming (returns bytes written)\n * @returns Decompressed data (or bytes written if outputSink provided)\n */\nexport function decodeLzma2(input: BufferLike, properties: Buffer | Uint8Array, unpackSize?: number, outputSink?: { write(buffer: Buffer): void }): Buffer | number {\n // For very large outputs on old Node versions, we cannot return a single Buffer\n // Use streaming mode internally to handle large outputs on modern Node\n if (!outputSink && unpackSize && unpackSize > 0 && !canAllocateBufferSize(unpackSize)) {\n // Large output - use streaming mode with internal chunking\n const chunks: Buffer[] = [];\n const sink: OutputSink = {\n write(buffer: Buffer): void {\n chunks.push(buffer);\n },\n };\n\n const decoder = new Lzma2Decoder(properties, sink);\n decoder.decodeWithSink(input);\n\n // Combine chunks at the end - use bufferConcat for safe combination\n return bufferConcat(chunks);\n }\n\n const decoder = new Lzma2Decoder(properties, outputSink as OutputSink);\n if (outputSink) {\n // Zero-copy mode: write to sink during decode\n return decoder.decodeWithSink(input);\n }\n // Buffering mode: returns Buffer (zero-copy)\n return decoder.decode(input, unpackSize);\n}\n"],"names":["Lzma2Decoder","decodeLzma2","readBytes","input","offset","length","Buffer","isBuffer","slice","buf","bufferFrom","Array","i","readByte","properties","outputSink","Error","dictionarySize","parseLzma2DictionarySize","lzmaDecoder","LzmaDecoder","setDictionarySize","resetDictionary","resetProbabilities","setLcLpPb","lc","lp","pb","feedUncompressed","data","decodeLzmaData","outSize","solid","decode","decodeWithSink","totalBytes","result","parseLzma2ChunkHeader","success","chunk","type","dictReset","stateReset","newProps","dataOffset","headerSize","useSolid","uncompData","uncompSize","compSize","flushOutWindow","unpackSize","outputBuffer","outputPos","outputChunks","canPreAllocate","canAllocateBufferSize","allocBufferUnsafe","copy","push","bytesWritten","decodeToBuffer","chunkData","decoded","bufferConcat","chunks","sink","write","buffer","decoder"],"mappings":"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"}
|
package/dist/cjs/sevenz.d.cts
CHANGED
|
@@ -27,14 +27,15 @@
|
|
|
27
27
|
* and writes directly to it. Wrapping with an OutputSink that buffers to an
|
|
28
28
|
* array defeats this optimization by creating unnecessary intermediate copies.
|
|
29
29
|
*/
|
|
30
|
+
import type { BufferLike } from 'extract-base-iterator';
|
|
30
31
|
/** Callback for async decode operations: (error, result) => void */
|
|
31
32
|
export type DecodeCallback<T = Buffer> = (error: Error | null, result?: T) => void;
|
|
32
33
|
/** Callback invoked when an async 7z decode completes */
|
|
33
34
|
export type SevenZDecodeCallback = DecodeCallback<Buffer>;
|
|
34
|
-
export declare function decode7zLzma(data:
|
|
35
|
-
export declare function decode7zLzma(data:
|
|
35
|
+
export declare function decode7zLzma(data: BufferLike, properties: Buffer, unpackSize: number, callback: SevenZDecodeCallback): void;
|
|
36
|
+
export declare function decode7zLzma(data: BufferLike, properties: Buffer, unpackSize: number): Promise<Buffer>;
|
|
36
37
|
/**
|
|
37
38
|
* Decode LZMA2-compressed data from a 7z file
|
|
38
39
|
*/
|
|
39
|
-
export declare function decode7zLzma2(data:
|
|
40
|
-
export declare function decode7zLzma2(data:
|
|
40
|
+
export declare function decode7zLzma2(data: BufferLike, properties: Buffer, unpackSize: number | undefined, callback: SevenZDecodeCallback): void;
|
|
41
|
+
export declare function decode7zLzma2(data: BufferLike, properties: Buffer, unpackSize?: number): Promise<Buffer>;
|
package/dist/cjs/sevenz.d.ts
CHANGED
|
@@ -27,14 +27,15 @@
|
|
|
27
27
|
* and writes directly to it. Wrapping with an OutputSink that buffers to an
|
|
28
28
|
* array defeats this optimization by creating unnecessary intermediate copies.
|
|
29
29
|
*/
|
|
30
|
+
import type { BufferLike } from 'extract-base-iterator';
|
|
30
31
|
/** Callback for async decode operations: (error, result) => void */
|
|
31
32
|
export type DecodeCallback<T = Buffer> = (error: Error | null, result?: T) => void;
|
|
32
33
|
/** Callback invoked when an async 7z decode completes */
|
|
33
34
|
export type SevenZDecodeCallback = DecodeCallback<Buffer>;
|
|
34
|
-
export declare function decode7zLzma(data:
|
|
35
|
-
export declare function decode7zLzma(data:
|
|
35
|
+
export declare function decode7zLzma(data: BufferLike, properties: Buffer, unpackSize: number, callback: SevenZDecodeCallback): void;
|
|
36
|
+
export declare function decode7zLzma(data: BufferLike, properties: Buffer, unpackSize: number): Promise<Buffer>;
|
|
36
37
|
/**
|
|
37
38
|
* Decode LZMA2-compressed data from a 7z file
|
|
38
39
|
*/
|
|
39
|
-
export declare function decode7zLzma2(data:
|
|
40
|
-
export declare function decode7zLzma2(data:
|
|
40
|
+
export declare function decode7zLzma2(data: BufferLike, properties: Buffer, unpackSize: number | undefined, callback: SevenZDecodeCallback): void;
|
|
41
|
+
export declare function decode7zLzma2(data: BufferLike, properties: Buffer, unpackSize?: number): Promise<Buffer>;
|
package/dist/cjs/sevenz.js
CHANGED
|
@@ -64,7 +64,9 @@ function decode7zLzma(data, properties, unpackSize, callback) {
|
|
|
64
64
|
var native = (0, _nativets.tryLoadNative)();
|
|
65
65
|
if (native === null || native === void 0 ? void 0 : native.lzma) {
|
|
66
66
|
try {
|
|
67
|
-
|
|
67
|
+
// Native lzma-native expects Buffer, convert if needed
|
|
68
|
+
var buf = Buffer.isBuffer(data) ? data : data.toBuffer();
|
|
69
|
+
var promise = native.lzma(buf, properties, unpackSize);
|
|
68
70
|
if (promise && typeof promise.then === 'function') {
|
|
69
71
|
promise.then(function(value) {
|
|
70
72
|
return cb(null, value);
|
|
@@ -98,7 +100,9 @@ function decode7zLzma2(data, properties, unpackSize, callback) {
|
|
|
98
100
|
var native = (0, _nativets.tryLoadNative)();
|
|
99
101
|
if (native === null || native === void 0 ? void 0 : native.lzma2) {
|
|
100
102
|
try {
|
|
101
|
-
|
|
103
|
+
// Native lzma-native expects Buffer, convert if needed
|
|
104
|
+
var buf = Buffer.isBuffer(data) ? data : data.toBuffer();
|
|
105
|
+
var promise = native.lzma2(buf, properties, unpackSize);
|
|
102
106
|
if (promise && typeof promise.then === 'function') {
|
|
103
107
|
promise.then(function(value) {
|
|
104
108
|
return cb(null, value);
|