xz-compat 1.1.3 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/dist/cjs/lzma/lib/Lzma2ChunkParser.d.cts +4 -3
  2. package/dist/cjs/lzma/lib/Lzma2ChunkParser.d.ts +4 -3
  3. package/dist/cjs/lzma/lib/Lzma2ChunkParser.js +24 -14
  4. package/dist/cjs/lzma/lib/Lzma2ChunkParser.js.map +1 -1
  5. package/dist/cjs/lzma/sync/Lzma2Decoder.d.cts +1 -2
  6. package/dist/cjs/lzma/sync/Lzma2Decoder.d.ts +1 -2
  7. package/dist/cjs/lzma/sync/Lzma2Decoder.js +61 -71
  8. package/dist/cjs/lzma/sync/Lzma2Decoder.js.map +1 -1
  9. package/dist/cjs/lzma/sync/LzmaDecoder.d.cts +9 -8
  10. package/dist/cjs/lzma/sync/LzmaDecoder.d.ts +9 -8
  11. package/dist/cjs/lzma/sync/LzmaDecoder.js +3 -3
  12. package/dist/cjs/lzma/sync/LzmaDecoder.js.map +1 -1
  13. package/dist/cjs/lzma/sync/RangeDecoder.d.cts +3 -2
  14. package/dist/cjs/lzma/sync/RangeDecoder.d.ts +3 -2
  15. package/dist/cjs/lzma/sync/RangeDecoder.js +11 -5
  16. package/dist/cjs/lzma/sync/RangeDecoder.js.map +1 -1
  17. package/dist/cjs/sevenz.d.cts +5 -4
  18. package/dist/cjs/sevenz.d.ts +5 -4
  19. package/dist/cjs/sevenz.js +6 -2
  20. package/dist/cjs/sevenz.js.map +1 -1
  21. package/dist/esm/lzma/lib/Lzma2ChunkParser.d.ts +4 -3
  22. package/dist/esm/lzma/lib/Lzma2ChunkParser.js +25 -15
  23. package/dist/esm/lzma/lib/Lzma2ChunkParser.js.map +1 -1
  24. package/dist/esm/lzma/sync/Lzma2Decoder.d.ts +1 -2
  25. package/dist/esm/lzma/sync/Lzma2Decoder.js +62 -72
  26. package/dist/esm/lzma/sync/Lzma2Decoder.js.map +1 -1
  27. package/dist/esm/lzma/sync/LzmaDecoder.d.ts +9 -8
  28. package/dist/esm/lzma/sync/LzmaDecoder.js +4 -4
  29. package/dist/esm/lzma/sync/LzmaDecoder.js.map +1 -1
  30. package/dist/esm/lzma/sync/RangeDecoder.d.ts +3 -2
  31. package/dist/esm/lzma/sync/RangeDecoder.js +6 -6
  32. package/dist/esm/lzma/sync/RangeDecoder.js.map +1 -1
  33. package/dist/esm/sevenz.d.ts +5 -4
  34. package/dist/esm/sevenz.js +6 -2
  35. package/dist/esm/sevenz.js.map +1 -1
  36. package/package.json +1 -1
@@ -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: Buffer, offset: number): ParseResult;
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: Buffer, offset: number): CompleteChunkResult;
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: Buffer, offset: number): ParseResult;
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: Buffer, offset: number): CompleteChunkResult;
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
- if (offset >= input.length) {
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[offset];
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 > input.length) {
70
+ if (offset + 3 > len) {
62
71
  return {
63
72
  success: false,
64
- needBytes: 3 - (input.length - offset)
73
+ needBytes: 3 - (len - offset)
65
74
  };
66
75
  }
67
- var uncompSize = (input[offset + 1] << 8 | input[offset + 2]) + 1;
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 > input.length) {
94
+ if (offset + minHeaderSize > len) {
86
95
  return {
87
96
  success: false,
88
- needBytes: minHeaderSize - (input.length - offset)
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[offset + 1] << 8 | input[offset + 2]) + 1;
94
- var compSize = (input[offset + 3] << 8 | input[offset + 4]) + 1;
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[offset + 5];
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
- if (offset + totalSize > input.length) {
145
+ var len = getLength(input);
146
+ if (offset + totalSize > len) {
137
147
  return {
138
148
  success: false,
139
- needBytes: totalSize - (input.length - offset)
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: 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":["hasCompleteChunk","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","result","dataSize","totalSize"],"mappings":"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"}
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(offset < buf.length){
87
- var result = (0, _Lzma2ChunkParserts.parseLzma2ChunkHeader)(buf, offset);
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
- var uncompData = buf.slice(dataOffset, dataOffset + chunk.uncompSize);
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
- // 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
- 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,18 @@ 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
- // Convert BufferList to Buffer for low-level parsing
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
- if (unpackSize && unpackSize > 0) {
147
+ var MAX_SAFE_SIZE = 256 * 1024 * 1024; // 256MB
148
+ if (unpackSize && unpackSize > 0 && unpackSize <= MAX_SAFE_SIZE) {
154
149
  outputBuffer = (0, _extractbaseiterator.allocBufferUnsafe)(unpackSize);
155
150
  }
156
151
  var offset = 0;
157
- while(offset < buf.length){
158
- var result = (0, _Lzma2ChunkParserts.parseLzma2ChunkHeader)(buf, offset);
152
+ // Parse and decode LZMA2 chunks one at a time
153
+ while(true){
154
+ var result = (0, _Lzma2ChunkParserts.parseLzma2ChunkHeader)(input, offset);
159
155
  if (!result.success) {
160
156
  throw new Error('Truncated LZMA2 chunk header');
161
157
  }
@@ -163,18 +159,25 @@ var Lzma2Decoder = /*#__PURE__*/ function() {
163
159
  if (chunk.type === 'end') {
164
160
  break;
165
161
  }
166
- // Validate we have enough data for the chunk
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
- }
162
+ var dataOffset = offset + chunk.headerSize;
171
163
  // Handle dictionary reset
172
164
  if (chunk.dictReset) {
173
165
  this.lzmaDecoder.resetDictionary();
174
166
  }
175
- var dataOffset = offset + chunk.headerSize;
167
+ // Handle state reset
168
+ if (chunk.stateReset) {
169
+ this.lzmaDecoder.resetProbabilities();
170
+ }
171
+ // Apply new properties if present
172
+ if (chunk.newProps) {
173
+ var _chunk_newProps = chunk.newProps, lc = _chunk_newProps.lc, lp = _chunk_newProps.lp, pb = _chunk_newProps.pb;
174
+ this.lzmaDecoder.setLcLpPb(lc, lp, pb);
175
+ }
176
+ // Determine solid mode
177
+ var useSolid = !chunk.stateReset || chunk.stateReset && !chunk.dictReset;
176
178
  if (chunk.type === 'uncompressed') {
177
- var uncompData = buf.slice(dataOffset, dataOffset + chunk.uncompSize);
179
+ // Read uncompressed data
180
+ var uncompData = readBytes(input, dataOffset, chunk.uncompSize);
178
181
  // Copy to output
179
182
  if (outputBuffer) {
180
183
  uncompData.copy(outputBuffer, outputPos);
@@ -186,34 +189,14 @@ var Lzma2Decoder = /*#__PURE__*/ function() {
186
189
  this.lzmaDecoder.feedUncompressed(uncompData);
187
190
  offset = dataOffset + chunk.uncompSize;
188
191
  } 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
192
+ // LZMA compressed chunk - decode directly from BufferLike
210
193
  if (outputBuffer) {
211
194
  // Zero-copy: decode directly into caller's buffer
212
- var bytesWritten = this.lzmaDecoder.decodeToBuffer(buf, dataOffset, chunk.uncompSize, outputBuffer, outputPos, useSolid);
195
+ var bytesWritten = this.lzmaDecoder.decodeToBuffer(input, dataOffset, chunk.uncompSize, outputBuffer, outputPos, useSolid);
213
196
  outputPos += bytesWritten;
214
197
  } else {
215
198
  // No pre-allocation: decode to new buffer and collect chunks
216
- var chunkData = buf.slice(dataOffset, dataOffset + chunk.compSize);
199
+ var chunkData = readBytes(input, dataOffset, chunk.compSize);
217
200
  var decoded = this.lzmaDecoder.decode(chunkData, 0, chunk.uncompSize, useSolid);
218
201
  outputChunks.push(decoded);
219
202
  }
@@ -224,11 +207,18 @@ var Lzma2Decoder = /*#__PURE__*/ function() {
224
207
  if (outputBuffer) {
225
208
  return outputPos < outputBuffer.length ? outputBuffer.slice(0, outputPos) : outputBuffer;
226
209
  }
227
- return Buffer.concat(outputChunks);
210
+ // Use bufferConcat which handles large buffers safely via pairwise combination
211
+ return (0, _extractbaseiterator.bufferConcat)(outputChunks);
228
212
  };
229
213
  return Lzma2Decoder;
230
214
  }();
231
215
  function decodeLzma2(input, properties, unpackSize, outputSink) {
216
+ // For very large outputs on old Node versions, we cannot return a single Buffer
217
+ // Check if output would exceed safe buffer limits
218
+ var MAX_SAFE_SIZE = 256 * 1024 * 1024; // 256MB
219
+ if (!outputSink && unpackSize && unpackSize > 0 && unpackSize > MAX_SAFE_SIZE) {
220
+ throw new Error("Cannot combine buffers: total size (".concat(unpackSize, " bytes) exceeds Node.js buffer limit. LZMA2 archives with folders larger than ").concat(Math.floor(MAX_SAFE_SIZE / (1024 * 1024)), "MB cannot be fully buffered on this Node version. Use streaming mode with an output sink instead."));
221
+ }
232
222
  var decoder = new Lzma2Decoder(properties, outputSink);
233
223
  if (outputSink) {
234
224
  // Zero-copy mode: write to sink during decode
@@ -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 } 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 const MAX_SAFE_SIZE = 256 * 1024 * 1024; // 256MB\n if (unpackSize && unpackSize > 0 && unpackSize <= MAX_SAFE_SIZE) {\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 // Check if output would exceed safe buffer limits\n const MAX_SAFE_SIZE = 256 * 1024 * 1024; // 256MB\n if (!outputSink && unpackSize && unpackSize > 0 && unpackSize > MAX_SAFE_SIZE) {\n throw new Error(`Cannot combine buffers: total size (${unpackSize} bytes) exceeds Node.js buffer limit. LZMA2 archives with folders larger than ${Math.floor(MAX_SAFE_SIZE / (1024 * 1024))}MB cannot be fully buffered on this Node version. Use streaming mode with an output sink instead.`);\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","MAX_SAFE_SIZE","allocBufferUnsafe","copy","push","bytesWritten","decodeToBuffer","chunkData","decoded","bufferConcat","Math","floor","decoder"],"mappings":"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"}
@@ -4,6 +4,7 @@
4
4
  * Decodes LZMA1 compressed data from a buffer.
5
5
  * All operations are synchronous.
6
6
  */
7
+ import { type BufferLike } from 'extract-base-iterator';
7
8
  import { type OutputSink } from '../types.js';
8
9
  /**
9
10
  * Synchronous LZMA1 decoder
@@ -69,16 +70,16 @@ export declare class LzmaDecoder {
69
70
  flushOutWindow(): void;
70
71
  /**
71
72
  * Decode LZMA data with streaming output (no buffer accumulation)
72
- * @param input - Compressed input buffer
73
+ * @param input - Compressed input buffer or BufferList
73
74
  * @param inputOffset - Offset into input buffer
74
75
  * @param outSize - Expected output size
75
76
  * @param solid - If true, preserve state from previous decode
76
77
  * @returns Number of bytes written to sink
77
78
  */
78
- decodeWithSink(input: Buffer, inputOffset: number, outSize: number, solid?: boolean): number;
79
+ decodeWithSink(input: BufferLike, inputOffset: number, outSize: number, solid?: boolean): number;
79
80
  /**
80
81
  * Decode LZMA data directly into caller's buffer (zero-copy)
81
- * @param input - Compressed input buffer
82
+ * @param input - Compressed input buffer or BufferList
82
83
  * @param inputOffset - Offset into input buffer
83
84
  * @param outSize - Expected output size
84
85
  * @param output - Pre-allocated output buffer to write to
@@ -86,16 +87,16 @@ export declare class LzmaDecoder {
86
87
  * @param solid - If true, preserve state from previous decode
87
88
  * @returns Number of bytes written
88
89
  */
89
- decodeToBuffer(input: Buffer, inputOffset: number, outSize: number, output: Buffer, outputOffset: number, solid?: boolean): number;
90
+ decodeToBuffer(input: BufferLike, inputOffset: number, outSize: number, output: Buffer, outputOffset: number, solid?: boolean): number;
90
91
  /**
91
92
  * Decode LZMA data
92
- * @param input - Compressed input buffer
93
+ * @param input - Compressed input buffer or BufferList
93
94
  * @param inputOffset - Offset into input buffer
94
95
  * @param outSize - Expected output size
95
96
  * @param solid - If true, preserve state from previous decode
96
97
  * @returns Decompressed data
97
98
  */
98
- decode(input: Buffer, inputOffset: number, outSize: number, solid?: boolean): Buffer;
99
+ decode(input: BufferLike, inputOffset: number, outSize: number, solid?: boolean): Buffer;
99
100
  }
100
101
  /**
101
102
  * Decode LZMA1 data synchronously
@@ -104,12 +105,12 @@ export declare class LzmaDecoder {
104
105
  * self-describing data (like XZ), but here we accept raw LZMA with properties
105
106
  * specified separately. Pure JS implementation is used for LZMA1.
106
107
  *
107
- * @param input - Compressed data (without 5-byte properties header)
108
+ * @param input - Compressed data (without 5-byte properties header) or BufferList
108
109
  * @param properties - 5-byte LZMA properties
109
110
  * @param outSize - Expected output size
110
111
  * @param outputSink - Optional output sink with write callback for streaming (returns bytes written)
111
112
  * @returns Decompressed data (or bytes written if outputSink provided)
112
113
  */
113
- export declare function decodeLzma(input: Buffer, properties: Buffer | Uint8Array, outSize: number, outputSink?: {
114
+ export declare function decodeLzma(input: BufferLike, properties: Buffer | Uint8Array, outSize: number, outputSink?: {
114
115
  write(buffer: Buffer): void;
115
116
  }): Buffer | number;