xz-compat 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +42 -0
- package/README.md +248 -0
- package/dist/cjs/compat.d.cts +1 -0
- package/dist/cjs/compat.d.ts +1 -0
- package/dist/cjs/compat.js +23 -0
- package/dist/cjs/compat.js.map +1 -0
- package/dist/cjs/filters/bcj/Bcj.d.cts +16 -0
- package/dist/cjs/filters/bcj/Bcj.d.ts +16 -0
- package/dist/cjs/filters/bcj/Bcj.js +192 -0
- package/dist/cjs/filters/bcj/Bcj.js.map +1 -0
- package/dist/cjs/filters/bcj/BcjArm.d.cts +16 -0
- package/dist/cjs/filters/bcj/BcjArm.d.ts +16 -0
- package/dist/cjs/filters/bcj/BcjArm.js +122 -0
- package/dist/cjs/filters/bcj/BcjArm.js.map +1 -0
- package/dist/cjs/filters/bcj/BcjArm64.d.cts +21 -0
- package/dist/cjs/filters/bcj/BcjArm64.d.ts +21 -0
- package/dist/cjs/filters/bcj/BcjArm64.js +65 -0
- package/dist/cjs/filters/bcj/BcjArm64.js.map +1 -0
- package/dist/cjs/filters/bcj/BcjArmt.d.cts +19 -0
- package/dist/cjs/filters/bcj/BcjArmt.d.ts +19 -0
- package/dist/cjs/filters/bcj/BcjArmt.js +76 -0
- package/dist/cjs/filters/bcj/BcjArmt.js.map +1 -0
- package/dist/cjs/filters/bcj/BcjIa64.d.cts +15 -0
- package/dist/cjs/filters/bcj/BcjIa64.d.ts +15 -0
- package/dist/cjs/filters/bcj/BcjIa64.js +141 -0
- package/dist/cjs/filters/bcj/BcjIa64.js.map +1 -0
- package/dist/cjs/filters/bcj/BcjPpc.d.cts +20 -0
- package/dist/cjs/filters/bcj/BcjPpc.d.ts +20 -0
- package/dist/cjs/filters/bcj/BcjPpc.js +64 -0
- package/dist/cjs/filters/bcj/BcjPpc.js.map +1 -0
- package/dist/cjs/filters/bcj/BcjSparc.d.cts +19 -0
- package/dist/cjs/filters/bcj/BcjSparc.d.ts +19 -0
- package/dist/cjs/filters/bcj/BcjSparc.js +69 -0
- package/dist/cjs/filters/bcj/BcjSparc.js.map +1 -0
- package/dist/cjs/filters/delta/Delta.d.cts +16 -0
- package/dist/cjs/filters/delta/Delta.d.ts +16 -0
- package/dist/cjs/filters/delta/Delta.js +74 -0
- package/dist/cjs/filters/delta/Delta.js.map +1 -0
- package/dist/cjs/filters/index.d.cts +8 -0
- package/dist/cjs/filters/index.d.ts +8 -0
- package/dist/cjs/filters/index.js +27 -0
- package/dist/cjs/filters/index.js.map +1 -0
- package/dist/cjs/index.d.cts +4 -0
- package/dist/cjs/index.d.ts +4 -0
- package/dist/cjs/index.js +58 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/lzma/Lzma2ChunkParser.d.cts +73 -0
- package/dist/cjs/lzma/Lzma2ChunkParser.d.ts +73 -0
- package/dist/cjs/lzma/Lzma2ChunkParser.js +148 -0
- package/dist/cjs/lzma/Lzma2ChunkParser.js.map +1 -0
- package/dist/cjs/lzma/index.d.cts +31 -0
- package/dist/cjs/lzma/index.d.ts +31 -0
- package/dist/cjs/lzma/index.js +83 -0
- package/dist/cjs/lzma/index.js.map +1 -0
- package/dist/cjs/lzma/stream/transforms.d.cts +46 -0
- package/dist/cjs/lzma/stream/transforms.d.ts +46 -0
- package/dist/cjs/lzma/stream/transforms.js +193 -0
- package/dist/cjs/lzma/stream/transforms.js.map +1 -0
- package/dist/cjs/lzma/sync/Lzma2Decoder.d.cts +63 -0
- package/dist/cjs/lzma/sync/Lzma2Decoder.d.ts +63 -0
- package/dist/cjs/lzma/sync/Lzma2Decoder.js +231 -0
- package/dist/cjs/lzma/sync/Lzma2Decoder.js.map +1 -0
- package/dist/cjs/lzma/sync/LzmaDecoder.d.cts +97 -0
- package/dist/cjs/lzma/sync/LzmaDecoder.d.ts +97 -0
- package/dist/cjs/lzma/sync/LzmaDecoder.js +582 -0
- package/dist/cjs/lzma/sync/LzmaDecoder.js.map +1 -0
- package/dist/cjs/lzma/sync/RangeDecoder.d.cts +69 -0
- package/dist/cjs/lzma/sync/RangeDecoder.d.ts +69 -0
- package/dist/cjs/lzma/sync/RangeDecoder.js +162 -0
- package/dist/cjs/lzma/sync/RangeDecoder.js.map +1 -0
- package/dist/cjs/lzma/types.d.cts +117 -0
- package/dist/cjs/lzma/types.d.ts +117 -0
- package/dist/cjs/lzma/types.js +264 -0
- package/dist/cjs/lzma/types.js.map +1 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/utils/createBufferingDecoder.d.cts +10 -0
- package/dist/cjs/utils/createBufferingDecoder.d.ts +10 -0
- package/dist/cjs/utils/createBufferingDecoder.js +41 -0
- package/dist/cjs/utils/createBufferingDecoder.js.map +1 -0
- package/dist/cjs/xz/Decoder.d.cts +21 -0
- package/dist/cjs/xz/Decoder.d.ts +21 -0
- package/dist/cjs/xz/Decoder.js +325 -0
- package/dist/cjs/xz/Decoder.js.map +1 -0
- package/dist/esm/compat.d.ts +1 -0
- package/dist/esm/compat.js +7 -0
- package/dist/esm/compat.js.map +1 -0
- package/dist/esm/filters/bcj/Bcj.d.ts +16 -0
- package/dist/esm/filters/bcj/Bcj.js +184 -0
- package/dist/esm/filters/bcj/Bcj.js.map +1 -0
- package/dist/esm/filters/bcj/BcjArm.d.ts +16 -0
- package/dist/esm/filters/bcj/BcjArm.js +114 -0
- package/dist/esm/filters/bcj/BcjArm.js.map +1 -0
- package/dist/esm/filters/bcj/BcjArm64.d.ts +21 -0
- package/dist/esm/filters/bcj/BcjArm64.js +57 -0
- package/dist/esm/filters/bcj/BcjArm64.js.map +1 -0
- package/dist/esm/filters/bcj/BcjArmt.d.ts +19 -0
- package/dist/esm/filters/bcj/BcjArmt.js +66 -0
- package/dist/esm/filters/bcj/BcjArmt.js.map +1 -0
- package/dist/esm/filters/bcj/BcjIa64.d.ts +15 -0
- package/dist/esm/filters/bcj/BcjIa64.js +127 -0
- package/dist/esm/filters/bcj/BcjIa64.js.map +1 -0
- package/dist/esm/filters/bcj/BcjPpc.d.ts +20 -0
- package/dist/esm/filters/bcj/BcjPpc.js +55 -0
- package/dist/esm/filters/bcj/BcjPpc.js.map +1 -0
- package/dist/esm/filters/bcj/BcjSparc.d.ts +19 -0
- package/dist/esm/filters/bcj/BcjSparc.js +59 -0
- package/dist/esm/filters/bcj/BcjSparc.js.map +1 -0
- package/dist/esm/filters/delta/Delta.d.ts +16 -0
- package/dist/esm/filters/delta/Delta.js +66 -0
- package/dist/esm/filters/delta/Delta.js.map +1 -0
- package/dist/esm/filters/index.d.ts +8 -0
- package/dist/esm/filters/index.js +9 -0
- package/dist/esm/filters/index.js.map +1 -0
- package/dist/esm/index.d.ts +4 -0
- package/dist/esm/index.js +5 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/lzma/Lzma2ChunkParser.d.ts +73 -0
- package/dist/esm/lzma/Lzma2ChunkParser.js +137 -0
- package/dist/esm/lzma/Lzma2ChunkParser.js.map +1 -0
- package/dist/esm/lzma/index.d.ts +31 -0
- package/dist/esm/lzma/index.js +44 -0
- package/dist/esm/lzma/index.js.map +1 -0
- package/dist/esm/lzma/stream/transforms.d.ts +46 -0
- package/dist/esm/lzma/stream/transforms.js +190 -0
- package/dist/esm/lzma/stream/transforms.js.map +1 -0
- package/dist/esm/lzma/sync/Lzma2Decoder.d.ts +63 -0
- package/dist/esm/lzma/sync/Lzma2Decoder.js +211 -0
- package/dist/esm/lzma/sync/Lzma2Decoder.js.map +1 -0
- package/dist/esm/lzma/sync/LzmaDecoder.d.ts +97 -0
- package/dist/esm/lzma/sync/LzmaDecoder.js +545 -0
- package/dist/esm/lzma/sync/LzmaDecoder.js.map +1 -0
- package/dist/esm/lzma/sync/RangeDecoder.d.ts +69 -0
- package/dist/esm/lzma/sync/RangeDecoder.js +132 -0
- package/dist/esm/lzma/sync/RangeDecoder.js.map +1 -0
- package/dist/esm/lzma/types.d.ts +117 -0
- package/dist/esm/lzma/types.js +154 -0
- package/dist/esm/lzma/types.js.map +1 -0
- package/dist/esm/package.json +1 -0
- package/dist/esm/utils/createBufferingDecoder.d.ts +10 -0
- package/dist/esm/utils/createBufferingDecoder.js +30 -0
- package/dist/esm/utils/createBufferingDecoder.js.map +1 -0
- package/dist/esm/xz/Decoder.d.ts +21 -0
- package/dist/esm/xz/Decoder.js +313 -0
- package/dist/esm/xz/Decoder.js.map +1 -0
- package/package.json +75 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2020 Kevin Malakoff
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
wof this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
|
23
|
+
--------------------zip: https://github.com/kriskowal/zip/blob/master/LICENSE
|
|
24
|
+
|
|
25
|
+
Copyright 2009, 2010 Kristopher Michael Kowal. All rights reserved.
|
|
26
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
27
|
+
of this software and associated documentation files (the "Software"), to
|
|
28
|
+
deal in the Software without restriction, including without limitation the
|
|
29
|
+
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
30
|
+
sell copies of the Software, and to permit persons to whom the Software is
|
|
31
|
+
furnished to do so, subject to the following conditions:
|
|
32
|
+
|
|
33
|
+
The above copyright notice and this permission notice shall be included in
|
|
34
|
+
all copies or substantial portions of the Software.
|
|
35
|
+
|
|
36
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
37
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
38
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
39
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
40
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
41
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
42
|
+
IN THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
# xz-compat
|
|
2
|
+
|
|
3
|
+
**XZ Decompression Library**
|
|
4
|
+
|
|
5
|
+
xz-compat is a complete pure JavaScript implementation of XZ decompression with support for LZMA2 compression, BCJ filters (Branch Conversion for various CPU architectures), and Delta filtering. Compatible with Node.js 0.8+.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- ✅ **XZ Format Support**: Full XZ container format decoding
|
|
10
|
+
- ✅ **LZMA2 Decoder**: Complete LZMA2 decompression implementation
|
|
11
|
+
- ✅ **BCJ Filters**: Branch conversion for improved compression on executables
|
|
12
|
+
- x86 (32-bit)
|
|
13
|
+
- ARM (32-bit)
|
|
14
|
+
- ARM64 / AArch64
|
|
15
|
+
- ARM Thumb
|
|
16
|
+
- PowerPC
|
|
17
|
+
- SPARC
|
|
18
|
+
- IA64 / Itanium
|
|
19
|
+
- ✅ **Delta Filter**: Byte-level delta encoding
|
|
20
|
+
- ✅ **Streaming & Sync**: Both streaming transforms and synchronous decoding
|
|
21
|
+
- ✅ **Node 0.8+**: Works on legacy Node.js versions
|
|
22
|
+
- ✅ **No Native Dependencies**: Pure JavaScript, no compilation required
|
|
23
|
+
|
|
24
|
+
## Installation
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm install xz-compat
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Quick Start
|
|
31
|
+
|
|
32
|
+
### Synchronous XZ Decompression
|
|
33
|
+
|
|
34
|
+
```javascript
|
|
35
|
+
import { readFileSync } from 'fs';
|
|
36
|
+
import { decodeXZ } from 'xz-compat';
|
|
37
|
+
|
|
38
|
+
const compressedData = readFileSync('file.xz');
|
|
39
|
+
const decompressedData = decodeXZ(compressedData);
|
|
40
|
+
console.log('Decompressed:', decompressedData.toString());
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Streaming XZ Decompression
|
|
44
|
+
|
|
45
|
+
```javascript
|
|
46
|
+
import { createReadStream } from 'fs';
|
|
47
|
+
import { createXZDecoder } from 'xz-compat';
|
|
48
|
+
|
|
49
|
+
const input = createReadStream('file.xz');
|
|
50
|
+
const decoder = createXZDecoder();
|
|
51
|
+
|
|
52
|
+
input.pipe(decoder);
|
|
53
|
+
decoder.on('data', (chunk) => {
|
|
54
|
+
console.log('Decompressed chunk:', chunk);
|
|
55
|
+
});
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### LZMA2 Decompression
|
|
59
|
+
|
|
60
|
+
```javascript
|
|
61
|
+
import { decodeLzma2 } from 'xz-compat';
|
|
62
|
+
import { writeFileSync } from 'fs';
|
|
63
|
+
|
|
64
|
+
const lzma2Data = readFileSync('data.lzma2');
|
|
65
|
+
const chunks = [];
|
|
66
|
+
|
|
67
|
+
decodeLzma2(lzma2Data, lzma2Properties, expectedSize, {
|
|
68
|
+
write: (chunk) => {
|
|
69
|
+
chunks.push(chunk);
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
const decompressed = Buffer.concat(chunks);
|
|
74
|
+
writeFileSync('output.bin', decompressed);
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Using BCJ Filters Directly
|
|
78
|
+
|
|
79
|
+
```javascript
|
|
80
|
+
import { decodeBcj, decodeBcjArm } from 'xz-compat';
|
|
81
|
+
|
|
82
|
+
// Decode x86 BCJ filtered data
|
|
83
|
+
const x86Data = readFileSync('filtered-x86.bin');
|
|
84
|
+
const unfiltered = decodeBcj(x86Data);
|
|
85
|
+
|
|
86
|
+
// Decode ARM BCJ filtered data
|
|
87
|
+
const armData = readFileSync('filtered-arm.bin');
|
|
88
|
+
const unfilteredArm = decodeBcjArm(armData);
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## API Reference
|
|
92
|
+
|
|
93
|
+
### XZ Decompression
|
|
94
|
+
|
|
95
|
+
#### `decodeXZ(buffer: Buffer): Buffer`
|
|
96
|
+
Synchronously decompresses XZ format data.
|
|
97
|
+
|
|
98
|
+
#### `createXZDecoder(): Transform`
|
|
99
|
+
Creates a streaming Transform for XZ decompression.
|
|
100
|
+
|
|
101
|
+
### LZMA2 Decompression
|
|
102
|
+
|
|
103
|
+
#### `decodeLzma2(buffer: Buffer, properties: Buffer, unpackSize: number, sink: OutputSink): void`
|
|
104
|
+
Synchronously decodes LZMA2 compressed data.
|
|
105
|
+
|
|
106
|
+
#### `createLzma2Decoder(properties: Buffer, unpackSize: number): Transform`
|
|
107
|
+
Creates a streaming Transform for LZMA2 decompression.
|
|
108
|
+
|
|
109
|
+
### BCJ Filters
|
|
110
|
+
|
|
111
|
+
Branch Conversion (BCJ) filters improve compression of executables by converting relative branch addresses to absolute addresses, creating more repetitive patterns.
|
|
112
|
+
|
|
113
|
+
All BCJ filters follow the same interface:
|
|
114
|
+
- `decodeBcj*(buffer: Buffer, properties?: Buffer, unpackSize?: number): Buffer`
|
|
115
|
+
- `createBcj*Decoder(properties?: Buffer, unpackSize?: number): Transform`
|
|
116
|
+
|
|
117
|
+
Supported BCJ filters:
|
|
118
|
+
- `decodeBcj` / `createBcjDecoder` - x86 (32-bit)
|
|
119
|
+
- `decodeBcjArm` / `createBcjArmDecoder` - ARM (32-bit)
|
|
120
|
+
- `decodeBcjArm64` / `createBcjArm64Decoder` - ARM64 / AArch64
|
|
121
|
+
- `decodeBcjArmt` / `createBcjArmtDecoder` - ARM Thumb
|
|
122
|
+
- `decodeBcjPpc` / `createBcjPpcDecoder` - PowerPC
|
|
123
|
+
- `decodeBcjSparc` / `createBcjSparcDecoder` - SPARC
|
|
124
|
+
- `decodeBcjIa64` / `createBcjIa64Decoder` - IA64 / Itanium
|
|
125
|
+
|
|
126
|
+
### Delta Filter
|
|
127
|
+
|
|
128
|
+
#### `decodeDelta(buffer: Buffer, distance?: Buffer): Buffer`
|
|
129
|
+
Decodes Delta filtered data (inter-byte differences).
|
|
130
|
+
|
|
131
|
+
## Use Cases
|
|
132
|
+
|
|
133
|
+
### 1. Decompressing XZ Archives
|
|
134
|
+
|
|
135
|
+
```javascript
|
|
136
|
+
import { createReadStream } from 'fs';
|
|
137
|
+
import { createXZDecoder } from 'xz-compat';
|
|
138
|
+
import { pipeline } from 'stream/promises';
|
|
139
|
+
|
|
140
|
+
async function decompressXZ(inputPath, outputPath) {
|
|
141
|
+
await pipeline(
|
|
142
|
+
createReadStream(inputPath),
|
|
143
|
+
createXZDecoder(),
|
|
144
|
+
createWriteStream(outputPath)
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### 2. Working with LZMA Compressed Files
|
|
150
|
+
|
|
151
|
+
```javascript
|
|
152
|
+
import { decodeLzma2 } from 'xz-compat';
|
|
153
|
+
|
|
154
|
+
// Decompress raw LZMA2 stream
|
|
155
|
+
const data = readFileSync('data.lzma2');
|
|
156
|
+
const chunks = [];
|
|
157
|
+
|
|
158
|
+
decodeLzma2(data, propertiesBuffer, uncompressedSize, {
|
|
159
|
+
write: (chunk) => chunks.push(chunk)
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
const result = Buffer.concat(chunks);
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### 3. Batch Processing Compressed Files
|
|
166
|
+
|
|
167
|
+
```javascript
|
|
168
|
+
import { decodeXZ } from 'xz-compat';
|
|
169
|
+
|
|
170
|
+
function processXZFiles(filePaths) {
|
|
171
|
+
return filePaths.map(file => {
|
|
172
|
+
const compressed = readFileSync(file);
|
|
173
|
+
const decompressed = decodeXZ(compressed);
|
|
174
|
+
// Process decompressed data
|
|
175
|
+
return processData(decompressed);
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## Technical Details
|
|
181
|
+
|
|
182
|
+
### XZ Format Structure
|
|
183
|
+
|
|
184
|
+
XZ is a container format that wraps LZMA2 compressed data:
|
|
185
|
+
1. Stream Header
|
|
186
|
+
2. One or more Blocks (each with Block Header + Compressed Data)
|
|
187
|
+
3. Index (records block positions)
|
|
188
|
+
4. Stream Footer
|
|
189
|
+
|
|
190
|
+
Each Block can contain:
|
|
191
|
+
- A chain of preprocessing filters (Delta, BCJ)
|
|
192
|
+
- LZMA2 compression
|
|
193
|
+
|
|
194
|
+
### BCJ Filter Algorithm
|
|
195
|
+
|
|
196
|
+
BCJ filters convert branch instructions in executable code:
|
|
197
|
+
|
|
198
|
+
**x86 Example:**
|
|
199
|
+
- Original: `E8 xx xx xx xx` (CALL with relative offset)
|
|
200
|
+
- Converted: `E8 aa aa aa aa` (CALL with absolute address)
|
|
201
|
+
|
|
202
|
+
This creates more repetitive patterns for better LZMA2 compression.
|
|
203
|
+
|
|
204
|
+
### Reference Implementation
|
|
205
|
+
|
|
206
|
+
This implementation is based on the reference XZ Utils (XZ Embedded) codebase:
|
|
207
|
+
- [XZ Utils GitHub](https://github.com/tukaani-project/xz)
|
|
208
|
+
- Filter algorithms match the xz embedded reference implementations
|
|
209
|
+
|
|
210
|
+
## Compatibility
|
|
211
|
+
|
|
212
|
+
- **Node.js**: 0.8 and above
|
|
213
|
+
- **Browser**: Not tested (designed for Node.js)
|
|
214
|
+
- **Dependencies**: None (pure JavaScript)
|
|
215
|
+
|
|
216
|
+
## Differences from Native XZ
|
|
217
|
+
|
|
218
|
+
This is a **decompression-only** implementation focused on compatibility and ease of use:
|
|
219
|
+
- No compression support (only decompression)
|
|
220
|
+
- Simplified streaming interface
|
|
221
|
+
- Pure JavaScript (no native bindings)
|
|
222
|
+
- Optimized for readability and maintainability
|
|
223
|
+
|
|
224
|
+
## Performance
|
|
225
|
+
|
|
226
|
+
Performance characteristics:
|
|
227
|
+
- **Synchronous**: Suitable for small to medium files
|
|
228
|
+
- **Streaming**: Memory-efficient for large files
|
|
229
|
+
- **Trade-off**: Pure JavaScript may be slower than native implementations
|
|
230
|
+
- **BCJ Decoding**: Optimized reference algorithm implementations
|
|
231
|
+
|
|
232
|
+
## License
|
|
233
|
+
|
|
234
|
+
MIT
|
|
235
|
+
|
|
236
|
+
## Contributing
|
|
237
|
+
|
|
238
|
+
Contributions welcome! Please ensure tests pass:
|
|
239
|
+
|
|
240
|
+
```bash
|
|
241
|
+
npm test
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
## References
|
|
245
|
+
|
|
246
|
+
- [XZ Format Specification](https://tukaani.org/xz/xz-file-format.txt)
|
|
247
|
+
- [LZMA SDK](https://www.7-zip.org/sdk.html)
|
|
248
|
+
- [XZ Utils](https://tukaani.org/xz/)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function tmpdir(): string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function tmpdir(): string;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compatibility Layer for Node.js 0.8+
|
|
3
|
+
* Local to this package - contains only needed functions.
|
|
4
|
+
*/ "use strict";
|
|
5
|
+
Object.defineProperty(exports, "__esModule", {
|
|
6
|
+
value: true
|
|
7
|
+
});
|
|
8
|
+
Object.defineProperty(exports, "tmpdir", {
|
|
9
|
+
enumerable: true,
|
|
10
|
+
get: function() {
|
|
11
|
+
return tmpdir;
|
|
12
|
+
}
|
|
13
|
+
});
|
|
14
|
+
var _os = /*#__PURE__*/ _interop_require_default(require("os"));
|
|
15
|
+
function _interop_require_default(obj) {
|
|
16
|
+
return obj && obj.__esModule ? obj : {
|
|
17
|
+
default: obj
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
function tmpdir() {
|
|
21
|
+
return typeof _os.default.tmpdir === 'function' ? _os.default.tmpdir() : require('os-shim').tmpdir();
|
|
22
|
+
}
|
|
23
|
+
/* 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; }
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/iterators/xz-compat/src/compat.ts"],"sourcesContent":["/**\n * Compatibility Layer for Node.js 0.8+\n * Local to this package - contains only needed functions.\n */\nimport os from 'os';\n\nexport function tmpdir(): string {\n return typeof os.tmpdir === 'function' ? os.tmpdir() : require('os-shim').tmpdir();\n}\n"],"names":["tmpdir","os","require"],"mappings":"AAAA;;;CAGC;;;;+BAGeA;;;eAAAA;;;yDAFD;;;;;;AAER,SAASA;IACd,OAAO,OAAOC,WAAE,CAACD,MAAM,KAAK,aAAaC,WAAE,CAACD,MAAM,KAAKE,QAAQ,WAAWF,MAAM;AAClF"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Transform } from 'extract-base-iterator';
|
|
2
|
+
/**
|
|
3
|
+
* Decode BCJ (x86) filtered data (synchronous, for buffered use)
|
|
4
|
+
* Reverses the BCJ transformation by converting absolute addresses back to relative
|
|
5
|
+
*
|
|
6
|
+
* @param input - BCJ filtered data
|
|
7
|
+
* @param _properties - Unused for BCJ
|
|
8
|
+
* @param _unpackSize - Unused for BCJ
|
|
9
|
+
* @returns Unfiltered data
|
|
10
|
+
*/
|
|
11
|
+
export declare function decodeBcj(input: Buffer, _properties?: Buffer, _unpackSize?: number): Buffer;
|
|
12
|
+
/**
|
|
13
|
+
* Create a streaming BCJ decoder Transform.
|
|
14
|
+
* Processes data chunk by chunk, buffering incomplete instructions.
|
|
15
|
+
*/
|
|
16
|
+
export declare function createBcjDecoder(_properties?: Buffer, _unpackSize?: number): InstanceType<typeof Transform>;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Transform } from 'extract-base-iterator';
|
|
2
|
+
/**
|
|
3
|
+
* Decode BCJ (x86) filtered data (synchronous, for buffered use)
|
|
4
|
+
* Reverses the BCJ transformation by converting absolute addresses back to relative
|
|
5
|
+
*
|
|
6
|
+
* @param input - BCJ filtered data
|
|
7
|
+
* @param _properties - Unused for BCJ
|
|
8
|
+
* @param _unpackSize - Unused for BCJ
|
|
9
|
+
* @returns Unfiltered data
|
|
10
|
+
*/
|
|
11
|
+
export declare function decodeBcj(input: Buffer, _properties?: Buffer, _unpackSize?: number): Buffer;
|
|
12
|
+
/**
|
|
13
|
+
* Create a streaming BCJ decoder Transform.
|
|
14
|
+
* Processes data chunk by chunk, buffering incomplete instructions.
|
|
15
|
+
*/
|
|
16
|
+
export declare function createBcjDecoder(_properties?: Buffer, _unpackSize?: number): InstanceType<typeof Transform>;
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
// BCJ (x86) filter codec - converts x86 CALL/JMP relative addresses
|
|
2
|
+
// This is a simple filter that makes executables more compressible by LZMA
|
|
3
|
+
//
|
|
4
|
+
// BCJ transforms relative addresses in x86 CALL (0xE8) and JMP (0xE9) instructions
|
|
5
|
+
// to absolute addresses, which creates more repetitive patterns for compression.
|
|
6
|
+
//
|
|
7
|
+
// Reference: https://github.com/tukaani-project/xz/blob/master/src/liblzma/simple/x86.c
|
|
8
|
+
//
|
|
9
|
+
// This implementation uses true streaming - processes data chunk by chunk
|
|
10
|
+
// while buffering incomplete instructions across chunk boundaries.
|
|
11
|
+
"use strict";
|
|
12
|
+
Object.defineProperty(exports, "__esModule", {
|
|
13
|
+
value: true
|
|
14
|
+
});
|
|
15
|
+
function _export(target, all) {
|
|
16
|
+
for(var name in all)Object.defineProperty(target, name, {
|
|
17
|
+
enumerable: true,
|
|
18
|
+
get: Object.getOwnPropertyDescriptor(all, name).get
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
_export(exports, {
|
|
22
|
+
get createBcjDecoder () {
|
|
23
|
+
return createBcjDecoder;
|
|
24
|
+
},
|
|
25
|
+
get decodeBcj () {
|
|
26
|
+
return decodeBcj;
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
var _extractbaseiterator = require("extract-base-iterator");
|
|
30
|
+
// Test if byte is 0x00 or 0xFF (valid MSB for converted addresses)
|
|
31
|
+
function Test86MSByte(b) {
|
|
32
|
+
return b === 0 || b === 0xff;
|
|
33
|
+
}
|
|
34
|
+
// Lookup table for mask to bit number conversion (used in false positive prevention)
|
|
35
|
+
var MASK_TO_BIT_NUMBER = [
|
|
36
|
+
0,
|
|
37
|
+
1,
|
|
38
|
+
2,
|
|
39
|
+
2,
|
|
40
|
+
3
|
|
41
|
+
];
|
|
42
|
+
/**
|
|
43
|
+
* Core x86 BCJ conversion function (matches reference x86_code)
|
|
44
|
+
* Works for both encoding and decoding based on isEncoder flag
|
|
45
|
+
*
|
|
46
|
+
* @param state - Filter state (prevMask and prevPos)
|
|
47
|
+
* @param nowPos - Current position in the overall stream
|
|
48
|
+
* @param isEncoder - true for encoding, false for decoding
|
|
49
|
+
* @param buffer - Buffer to process (modified in place)
|
|
50
|
+
* @param size - Size of buffer
|
|
51
|
+
* @returns Number of bytes processed
|
|
52
|
+
*/ function x86Code(state, nowPos, isEncoder, buffer, size) {
|
|
53
|
+
var prevMask = state.prevMask;
|
|
54
|
+
var prevPos = state.prevPos;
|
|
55
|
+
if (size < 5) {
|
|
56
|
+
return 0;
|
|
57
|
+
}
|
|
58
|
+
// Decay prev_pos if too far from current position
|
|
59
|
+
if (nowPos - prevPos > 5) {
|
|
60
|
+
prevPos = nowPos - 5;
|
|
61
|
+
}
|
|
62
|
+
var limit = size - 5;
|
|
63
|
+
var bufferPos = 0;
|
|
64
|
+
while(bufferPos <= limit){
|
|
65
|
+
var opcode = buffer[bufferPos];
|
|
66
|
+
// Check for CALL (0xE8) or JMP (0xE9) opcode
|
|
67
|
+
if (opcode !== 0xe8 && opcode !== 0xe9) {
|
|
68
|
+
bufferPos++;
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
// Calculate offset from previous position
|
|
72
|
+
var offset = nowPos + bufferPos - prevPos;
|
|
73
|
+
prevPos = nowPos + bufferPos;
|
|
74
|
+
// Update mask based on offset
|
|
75
|
+
if (offset > 5) {
|
|
76
|
+
prevMask = 0;
|
|
77
|
+
} else {
|
|
78
|
+
for(var i = 0; i < offset; i++){
|
|
79
|
+
prevMask &= 0x77;
|
|
80
|
+
prevMask <<= 1;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
// Get the high byte of the address
|
|
84
|
+
var b = buffer[bufferPos + 4];
|
|
85
|
+
// Check if this looks like a valid address to convert
|
|
86
|
+
if (Test86MSByte(b) && prevMask >> 1 <= 4 && prevMask >> 1 !== 3) {
|
|
87
|
+
// Read 32-bit address (big-endian style: high byte first in src)
|
|
88
|
+
var src = b << 24 | buffer[bufferPos + 3] << 16 | buffer[bufferPos + 2] << 8 | buffer[bufferPos + 1];
|
|
89
|
+
// Make src unsigned 32-bit
|
|
90
|
+
src = src >>> 0;
|
|
91
|
+
var dest = void 0;
|
|
92
|
+
// Conversion loop with false positive correction
|
|
93
|
+
while(true){
|
|
94
|
+
if (isEncoder) {
|
|
95
|
+
dest = src + (nowPos + bufferPos + 5) >>> 0;
|
|
96
|
+
} else {
|
|
97
|
+
dest = src - (nowPos + bufferPos + 5) >>> 0;
|
|
98
|
+
}
|
|
99
|
+
if (prevMask === 0) {
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
var i1 = MASK_TO_BIT_NUMBER[prevMask >> 1];
|
|
103
|
+
b = dest >>> 24 - i1 * 8 & 0xff;
|
|
104
|
+
if (!Test86MSByte(b)) {
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
// XOR correction for false positive prevention
|
|
108
|
+
src = (dest ^ (1 << 32 - i1 * 8) - 1) >>> 0;
|
|
109
|
+
}
|
|
110
|
+
// Write back the converted address
|
|
111
|
+
// High byte: ~(((dest >> 24) & 1) - 1) produces 0x00 or 0xFF
|
|
112
|
+
buffer[bufferPos + 4] = ~((dest >>> 24 & 1) - 1) & 0xff;
|
|
113
|
+
buffer[bufferPos + 3] = dest >>> 16 & 0xff;
|
|
114
|
+
buffer[bufferPos + 2] = dest >>> 8 & 0xff;
|
|
115
|
+
buffer[bufferPos + 1] = dest & 0xff;
|
|
116
|
+
bufferPos += 5;
|
|
117
|
+
prevMask = 0;
|
|
118
|
+
} else {
|
|
119
|
+
bufferPos++;
|
|
120
|
+
prevMask |= 1;
|
|
121
|
+
if (Test86MSByte(b)) {
|
|
122
|
+
prevMask |= 0x10;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
// Save state
|
|
127
|
+
state.prevMask = prevMask;
|
|
128
|
+
state.prevPos = prevPos;
|
|
129
|
+
return bufferPos;
|
|
130
|
+
}
|
|
131
|
+
function decodeBcj(input, _properties, _unpackSize) {
|
|
132
|
+
var output = (0, _extractbaseiterator.bufferFrom)(input); // Copy since we modify in place
|
|
133
|
+
var state = {
|
|
134
|
+
prevMask: 0,
|
|
135
|
+
prevPos: 0xfffffffb
|
|
136
|
+
};
|
|
137
|
+
x86Code(state, 0, false, output, output.length);
|
|
138
|
+
return output;
|
|
139
|
+
}
|
|
140
|
+
function createBcjDecoder(_properties, _unpackSize) {
|
|
141
|
+
// State that persists across chunks
|
|
142
|
+
var state = {
|
|
143
|
+
prevMask: 0,
|
|
144
|
+
prevPos: 0xfffffffb
|
|
145
|
+
};
|
|
146
|
+
var globalPos = 0; // Position in the overall stream
|
|
147
|
+
var pending = null; // Bytes pending from previous chunk
|
|
148
|
+
var transform = new _extractbaseiterator.Transform({
|
|
149
|
+
transform: function(chunk, _encoding, callback) {
|
|
150
|
+
// Combine pending bytes with new chunk
|
|
151
|
+
var data;
|
|
152
|
+
if (pending && pending.length > 0) {
|
|
153
|
+
data = Buffer.concat([
|
|
154
|
+
pending,
|
|
155
|
+
chunk
|
|
156
|
+
]);
|
|
157
|
+
} else {
|
|
158
|
+
data = chunk;
|
|
159
|
+
}
|
|
160
|
+
// We need at least 5 bytes to process an instruction
|
|
161
|
+
if (data.length < 5) {
|
|
162
|
+
pending = data;
|
|
163
|
+
callback(null, (0, _extractbaseiterator.allocBuffer)(0));
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
// Process the buffer
|
|
167
|
+
var output = (0, _extractbaseiterator.bufferFrom)(data);
|
|
168
|
+
var processed = x86Code(state, globalPos, false, output, output.length);
|
|
169
|
+
if (processed === 0) {
|
|
170
|
+
// Not enough data to process
|
|
171
|
+
pending = data;
|
|
172
|
+
callback(null, (0, _extractbaseiterator.allocBuffer)(0));
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
// Output processed bytes, keep unprocessed as pending
|
|
176
|
+
var result = output.slice(0, processed);
|
|
177
|
+
pending = output.slice(processed);
|
|
178
|
+
globalPos += processed;
|
|
179
|
+
callback(null, result);
|
|
180
|
+
},
|
|
181
|
+
flush: function flush(callback) {
|
|
182
|
+
// Output any remaining pending bytes
|
|
183
|
+
if (pending && pending.length > 0) {
|
|
184
|
+
// Process final bytes - can't convert incomplete instructions
|
|
185
|
+
this.push(pending);
|
|
186
|
+
}
|
|
187
|
+
callback(null);
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
return transform;
|
|
191
|
+
}
|
|
192
|
+
/* 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; }
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/iterators/xz-compat/src/filters/bcj/Bcj.ts"],"sourcesContent":["// BCJ (x86) filter codec - converts x86 CALL/JMP relative addresses\n// This is a simple filter that makes executables more compressible by LZMA\n//\n// BCJ transforms relative addresses in x86 CALL (0xE8) and JMP (0xE9) instructions\n// to absolute addresses, which creates more repetitive patterns for compression.\n//\n// Reference: https://github.com/tukaani-project/xz/blob/master/src/liblzma/simple/x86.c\n//\n// This implementation uses true streaming - processes data chunk by chunk\n// while buffering incomplete instructions across chunk boundaries.\n\nimport { allocBuffer, bufferFrom, Transform } from 'extract-base-iterator';\n\n// Test if byte is 0x00 or 0xFF (valid MSB for converted addresses)\nfunction Test86MSByte(b: number): boolean {\n return b === 0 || b === 0xff;\n}\n\n// Lookup table for mask to bit number conversion (used in false positive prevention)\nconst MASK_TO_BIT_NUMBER = [0, 1, 2, 2, 3];\n\n/**\n * BCJ x86 filter state\n */\ninterface BcjX86State {\n prevMask: number;\n prevPos: number;\n}\n\n/**\n * Core x86 BCJ conversion function (matches reference x86_code)\n * Works for both encoding and decoding based on isEncoder flag\n *\n * @param state - Filter state (prevMask and prevPos)\n * @param nowPos - Current position in the overall stream\n * @param isEncoder - true for encoding, false for decoding\n * @param buffer - Buffer to process (modified in place)\n * @param size - Size of buffer\n * @returns Number of bytes processed\n */\nfunction x86Code(state: BcjX86State, nowPos: number, isEncoder: boolean, buffer: Buffer, size: number): number {\n let prevMask = state.prevMask;\n let prevPos = state.prevPos;\n\n if (size < 5) {\n return 0;\n }\n\n // Decay prev_pos if too far from current position\n if (nowPos - prevPos > 5) {\n prevPos = nowPos - 5;\n }\n\n const limit = size - 5;\n let bufferPos = 0;\n\n while (bufferPos <= limit) {\n const opcode = buffer[bufferPos];\n\n // Check for CALL (0xE8) or JMP (0xE9) opcode\n if (opcode !== 0xe8 && opcode !== 0xe9) {\n bufferPos++;\n continue;\n }\n\n // Calculate offset from previous position\n const offset = nowPos + bufferPos - prevPos;\n prevPos = nowPos + bufferPos;\n\n // Update mask based on offset\n if (offset > 5) {\n prevMask = 0;\n } else {\n for (let i = 0; i < offset; i++) {\n prevMask &= 0x77;\n prevMask <<= 1;\n }\n }\n\n // Get the high byte of the address\n let b = buffer[bufferPos + 4];\n\n // Check if this looks like a valid address to convert\n if (Test86MSByte(b) && prevMask >> 1 <= 4 && prevMask >> 1 !== 3) {\n // Read 32-bit address (big-endian style: high byte first in src)\n let src = (b << 24) | (buffer[bufferPos + 3] << 16) | (buffer[bufferPos + 2] << 8) | buffer[bufferPos + 1];\n\n // Make src unsigned 32-bit\n src = src >>> 0;\n\n let dest: number;\n\n // Conversion loop with false positive correction\n while (true) {\n if (isEncoder) {\n dest = (src + (nowPos + bufferPos + 5)) >>> 0;\n } else {\n dest = (src - (nowPos + bufferPos + 5)) >>> 0;\n }\n\n if (prevMask === 0) {\n break;\n }\n\n const i = MASK_TO_BIT_NUMBER[prevMask >> 1];\n b = (dest >>> (24 - i * 8)) & 0xff;\n\n if (!Test86MSByte(b)) {\n break;\n }\n\n // XOR correction for false positive prevention\n src = (dest ^ ((1 << (32 - i * 8)) - 1)) >>> 0;\n }\n\n // Write back the converted address\n // High byte: ~(((dest >> 24) & 1) - 1) produces 0x00 or 0xFF\n buffer[bufferPos + 4] = ~(((dest >>> 24) & 1) - 1) & 0xff;\n buffer[bufferPos + 3] = (dest >>> 16) & 0xff;\n buffer[bufferPos + 2] = (dest >>> 8) & 0xff;\n buffer[bufferPos + 1] = dest & 0xff;\n\n bufferPos += 5;\n prevMask = 0;\n } else {\n bufferPos++;\n prevMask |= 1;\n if (Test86MSByte(b)) {\n prevMask |= 0x10;\n }\n }\n }\n\n // Save state\n state.prevMask = prevMask;\n state.prevPos = prevPos;\n\n return bufferPos;\n}\n\n/**\n * Decode BCJ (x86) filtered data (synchronous, for buffered use)\n * Reverses the BCJ transformation by converting absolute addresses back to relative\n *\n * @param input - BCJ filtered data\n * @param _properties - Unused for BCJ\n * @param _unpackSize - Unused for BCJ\n * @returns Unfiltered data\n */\nexport function decodeBcj(input: Buffer, _properties?: Buffer, _unpackSize?: number): Buffer {\n const output = bufferFrom(input); // Copy since we modify in place\n\n const state: BcjX86State = {\n prevMask: 0,\n prevPos: 0xfffffffb, // (uint32_t)(-5) in C\n };\n\n x86Code(state, 0, false, output, output.length);\n\n return output;\n}\n\n/**\n * Create a streaming BCJ decoder Transform.\n * Processes data chunk by chunk, buffering incomplete instructions.\n */\nexport function createBcjDecoder(_properties?: Buffer, _unpackSize?: number): InstanceType<typeof Transform> {\n // State that persists across chunks\n const state: BcjX86State = {\n prevMask: 0,\n prevPos: 0xfffffffb, // (uint32_t)(-5) in C\n };\n let globalPos = 0; // Position in the overall stream\n let pending: Buffer | null = null; // Bytes pending from previous chunk\n\n const transform = new Transform({\n transform: (chunk: Buffer, _encoding: string, callback: (err?: Error | null, data?: Buffer) => void) => {\n // Combine pending bytes with new chunk\n let data: Buffer;\n if (pending && pending.length > 0) {\n data = Buffer.concat([pending, chunk]);\n } else {\n data = chunk;\n }\n\n // We need at least 5 bytes to process an instruction\n if (data.length < 5) {\n pending = data;\n callback(null, allocBuffer(0));\n return;\n }\n\n // Process the buffer\n const output = bufferFrom(data);\n const processed = x86Code(state, globalPos, false, output, output.length);\n\n if (processed === 0) {\n // Not enough data to process\n pending = data;\n callback(null, allocBuffer(0));\n return;\n }\n\n // Output processed bytes, keep unprocessed as pending\n const result = output.slice(0, processed);\n pending = output.slice(processed);\n globalPos += processed;\n\n callback(null, result);\n },\n flush: function (this: InstanceType<typeof Transform>, callback: (err?: Error | null) => void) {\n // Output any remaining pending bytes\n if (pending && pending.length > 0) {\n // Process final bytes - can't convert incomplete instructions\n this.push(pending);\n }\n callback(null);\n },\n });\n\n return transform;\n}\n"],"names":["createBcjDecoder","decodeBcj","Test86MSByte","b","MASK_TO_BIT_NUMBER","x86Code","state","nowPos","isEncoder","buffer","size","prevMask","prevPos","limit","bufferPos","opcode","offset","i","src","dest","input","_properties","_unpackSize","output","bufferFrom","length","globalPos","pending","transform","Transform","chunk","_encoding","callback","data","Buffer","concat","allocBuffer","processed","result","slice","flush","push"],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Transform } from 'extract-base-iterator';
|
|
2
|
+
/**
|
|
3
|
+
* Decode ARM BCJ filtered data (synchronous, for buffered use)
|
|
4
|
+
* Reverses the BCJ transformation by converting absolute addresses back to relative
|
|
5
|
+
*
|
|
6
|
+
* @param input - ARM BCJ filtered data
|
|
7
|
+
* @param _properties - Unused for ARM BCJ
|
|
8
|
+
* @param _unpackSize - Unused for ARM BCJ
|
|
9
|
+
* @returns Unfiltered data
|
|
10
|
+
*/
|
|
11
|
+
export declare function decodeBcjArm(input: Buffer, _properties?: Buffer, _unpackSize?: number): Buffer;
|
|
12
|
+
/**
|
|
13
|
+
* Create a streaming ARM BCJ decoder Transform.
|
|
14
|
+
* Processes data in 4-byte aligned chunks.
|
|
15
|
+
*/
|
|
16
|
+
export declare function createBcjArmDecoder(_properties?: Buffer, _unpackSize?: number): InstanceType<typeof Transform>;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Transform } from 'extract-base-iterator';
|
|
2
|
+
/**
|
|
3
|
+
* Decode ARM BCJ filtered data (synchronous, for buffered use)
|
|
4
|
+
* Reverses the BCJ transformation by converting absolute addresses back to relative
|
|
5
|
+
*
|
|
6
|
+
* @param input - ARM BCJ filtered data
|
|
7
|
+
* @param _properties - Unused for ARM BCJ
|
|
8
|
+
* @param _unpackSize - Unused for ARM BCJ
|
|
9
|
+
* @returns Unfiltered data
|
|
10
|
+
*/
|
|
11
|
+
export declare function decodeBcjArm(input: Buffer, _properties?: Buffer, _unpackSize?: number): Buffer;
|
|
12
|
+
/**
|
|
13
|
+
* Create a streaming ARM BCJ decoder Transform.
|
|
14
|
+
* Processes data in 4-byte aligned chunks.
|
|
15
|
+
*/
|
|
16
|
+
export declare function createBcjArmDecoder(_properties?: Buffer, _unpackSize?: number): InstanceType<typeof Transform>;
|