swf-toolkit 0.0.0-stage → 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 +21 -0
- package/README.md +125 -2
- package/README.tr.md +126 -0
- package/dist/abc/abc-file.d.ts +168 -0
- package/dist/abc/abc-file.js +656 -0
- package/dist/abc/analysis.d.ts +36 -0
- package/dist/abc/analysis.js +213 -0
- package/dist/abc/code.d.ts +59 -0
- package/dist/abc/code.js +379 -0
- package/dist/abc/constants.d.ts +80 -0
- package/dist/abc/constants.js +93 -0
- package/dist/abc/interner.d.ts +46 -0
- package/dist/abc/interner.js +168 -0
- package/dist/abc/model.d.ts +40 -0
- package/dist/abc/model.js +146 -0
- package/dist/abc/opcodes.d.ts +39 -0
- package/dist/abc/opcodes.js +196 -0
- package/dist/abc/pcode/assembler.d.ts +42 -0
- package/dist/abc/pcode/assembler.js +635 -0
- package/dist/abc/pcode/disassembler.d.ts +17 -0
- package/dist/abc/pcode/disassembler.js +147 -0
- package/dist/abc/pcode/format.d.ts +23 -0
- package/dist/abc/pcode/format.js +131 -0
- package/dist/abc/pcode/lexer.d.ts +34 -0
- package/dist/abc/pcode/lexer.js +183 -0
- package/dist/assets/assets.d.ts +26 -0
- package/dist/assets/assets.js +151 -0
- package/dist/assets/images.d.ts +31 -0
- package/dist/assets/images.js +238 -0
- package/dist/assets/png.d.ts +12 -0
- package/dist/assets/png.js +196 -0
- package/dist/assets/sounds.d.ts +37 -0
- package/dist/assets/sounds.js +236 -0
- package/dist/avm1/avm1.d.ts +55 -0
- package/dist/avm1/avm1.js +642 -0
- package/dist/avm1/project.d.ts +16 -0
- package/dist/avm1/project.js +81 -0
- package/dist/cjs/abc/abc-file.d.ts +168 -0
- package/dist/cjs/abc/abc-file.js +663 -0
- package/dist/cjs/abc/analysis.d.ts +36 -0
- package/dist/cjs/abc/analysis.js +221 -0
- package/dist/cjs/abc/code.d.ts +59 -0
- package/dist/cjs/abc/code.js +387 -0
- package/dist/cjs/abc/constants.d.ts +80 -0
- package/dist/cjs/abc/constants.js +97 -0
- package/dist/cjs/abc/interner.d.ts +46 -0
- package/dist/cjs/abc/interner.js +172 -0
- package/dist/cjs/abc/model.d.ts +40 -0
- package/dist/cjs/abc/model.js +155 -0
- package/dist/cjs/abc/opcodes.d.ts +39 -0
- package/dist/cjs/abc/opcodes.js +201 -0
- package/dist/cjs/abc/pcode/assembler.d.ts +42 -0
- package/dist/cjs/abc/pcode/assembler.js +640 -0
- package/dist/cjs/abc/pcode/disassembler.d.ts +17 -0
- package/dist/cjs/abc/pcode/disassembler.js +152 -0
- package/dist/cjs/abc/pcode/format.d.ts +23 -0
- package/dist/cjs/abc/pcode/format.js +141 -0
- package/dist/cjs/abc/pcode/lexer.d.ts +34 -0
- package/dist/cjs/abc/pcode/lexer.js +188 -0
- package/dist/cjs/assets/assets.d.ts +26 -0
- package/dist/cjs/assets/assets.js +159 -0
- package/dist/cjs/assets/images.d.ts +31 -0
- package/dist/cjs/assets/images.js +246 -0
- package/dist/cjs/assets/png.d.ts +12 -0
- package/dist/cjs/assets/png.js +202 -0
- package/dist/cjs/assets/sounds.d.ts +37 -0
- package/dist/cjs/assets/sounds.js +246 -0
- package/dist/cjs/avm1/avm1.d.ts +55 -0
- package/dist/cjs/avm1/avm1.js +649 -0
- package/dist/cjs/avm1/project.d.ts +16 -0
- package/dist/cjs/avm1/project.js +88 -0
- package/dist/cjs/compiler/ast.d.ts +285 -0
- package/dist/cjs/compiler/ast.js +3 -0
- package/dist/cjs/compiler/class-compiler.d.ts +34 -0
- package/dist/cjs/compiler/class-compiler.js +440 -0
- package/dist/cjs/compiler/codegen.d.ts +144 -0
- package/dist/cjs/compiler/codegen.js +1589 -0
- package/dist/cjs/compiler/lexer.d.ts +27 -0
- package/dist/cjs/compiler/lexer.js +254 -0
- package/dist/cjs/compiler/parser.d.ts +58 -0
- package/dist/cjs/compiler/parser.js +989 -0
- package/dist/cjs/compiler/program.d.ts +29 -0
- package/dist/cjs/compiler/program.js +36 -0
- package/dist/cjs/compiler/scope.d.ts +22 -0
- package/dist/cjs/compiler/scope.js +242 -0
- package/dist/cjs/compression/lzma.d.ts +37 -0
- package/dist/cjs/compression/lzma.js +575 -0
- package/dist/cjs/compression/swf-container.d.ts +19 -0
- package/dist/cjs/compression/swf-container.js +92 -0
- package/dist/cjs/decompiler/ast.d.ts +228 -0
- package/dist/cjs/decompiler/ast.js +455 -0
- package/dist/cjs/decompiler/cfg.d.ts +40 -0
- package/dist/cjs/decompiler/cfg.js +236 -0
- package/dist/cjs/decompiler/class-printer.d.ts +9 -0
- package/dist/cjs/decompiler/class-printer.js +173 -0
- package/dist/cjs/decompiler/method.d.ts +41 -0
- package/dist/cjs/decompiler/method.js +436 -0
- package/dist/cjs/decompiler/simulate.d.ts +55 -0
- package/dist/cjs/decompiler/simulate.js +591 -0
- package/dist/cjs/decompiler/structure.d.ts +48 -0
- package/dist/cjs/decompiler/structure.js +764 -0
- package/dist/cjs/errors.d.ts +11 -0
- package/dist/cjs/errors.js +25 -0
- package/dist/cjs/index.d.ts +41 -0
- package/dist/cjs/index.js +82 -0
- package/dist/cjs/io/reader.d.ts +48 -0
- package/dist/cjs/io/reader.js +180 -0
- package/dist/cjs/io/writer.d.ts +37 -0
- package/dist/cjs/io/writer.js +175 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/project/pcode-project.d.ts +32 -0
- package/dist/cjs/project/pcode-project.js +210 -0
- package/dist/cjs/project/source-export.d.ts +12 -0
- package/dist/cjs/project/source-export.js +51 -0
- package/dist/cjs/project/source-import.d.ts +13 -0
- package/dist/cjs/project/source-import.js +73 -0
- package/dist/cjs/swf/swf.d.ts +63 -0
- package/dist/cjs/swf/swf.js +147 -0
- package/dist/cjs/swf/tag-codes.d.ts +77 -0
- package/dist/cjs/swf/tag-codes.js +109 -0
- package/dist/cjs/swf/tags.d.ts +118 -0
- package/dist/cjs/swf/tags.js +330 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +296 -0
- package/dist/compiler/ast.d.ts +285 -0
- package/dist/compiler/ast.js +2 -0
- package/dist/compiler/class-compiler.d.ts +34 -0
- package/dist/compiler/class-compiler.js +437 -0
- package/dist/compiler/codegen.d.ts +144 -0
- package/dist/compiler/codegen.js +1585 -0
- package/dist/compiler/lexer.d.ts +27 -0
- package/dist/compiler/lexer.js +249 -0
- package/dist/compiler/parser.d.ts +58 -0
- package/dist/compiler/parser.js +984 -0
- package/dist/compiler/program.d.ts +29 -0
- package/dist/compiler/program.js +32 -0
- package/dist/compiler/scope.d.ts +22 -0
- package/dist/compiler/scope.js +238 -0
- package/dist/compression/lzma.d.ts +37 -0
- package/dist/compression/lzma.js +569 -0
- package/dist/compression/swf-container.d.ts +19 -0
- package/dist/compression/swf-container.js +87 -0
- package/dist/decompiler/ast.d.ts +228 -0
- package/dist/decompiler/ast.js +441 -0
- package/dist/decompiler/cfg.d.ts +40 -0
- package/dist/decompiler/cfg.js +231 -0
- package/dist/decompiler/class-printer.d.ts +9 -0
- package/dist/decompiler/class-printer.js +170 -0
- package/dist/decompiler/method.d.ts +41 -0
- package/dist/decompiler/method.js +427 -0
- package/dist/decompiler/simulate.d.ts +55 -0
- package/dist/decompiler/simulate.js +586 -0
- package/dist/decompiler/structure.d.ts +48 -0
- package/dist/decompiler/structure.js +760 -0
- package/dist/errors.d.ts +11 -0
- package/dist/errors.js +20 -0
- package/dist/index.d.ts +41 -0
- package/dist/index.js +49 -0
- package/dist/io/reader.d.ts +48 -0
- package/dist/io/reader.js +176 -0
- package/dist/io/writer.d.ts +37 -0
- package/dist/io/writer.js +169 -0
- package/dist/project/pcode-project.d.ts +32 -0
- package/dist/project/pcode-project.js +203 -0
- package/dist/project/source-export.d.ts +12 -0
- package/dist/project/source-export.js +47 -0
- package/dist/project/source-import.d.ts +13 -0
- package/dist/project/source-import.js +70 -0
- package/dist/swf/swf.d.ts +63 -0
- package/dist/swf/swf.js +143 -0
- package/dist/swf/tag-codes.d.ts +77 -0
- package/dist/swf/tag-codes.js +105 -0
- package/dist/swf/tags.d.ts +118 -0
- package/dist/swf/tags.js +316 -0
- package/package.json +71 -4
|
@@ -0,0 +1,575 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseLzmaProperties = parseLzmaProperties;
|
|
4
|
+
exports.encodeLzmaProperties = encodeLzmaProperties;
|
|
5
|
+
exports.lzmaDecompress = lzmaDecompress;
|
|
6
|
+
exports.lzmaCompress = lzmaCompress;
|
|
7
|
+
/**
|
|
8
|
+
* Pure TypeScript LZMA ("LZMA1", as used by ZWS SWF files) decoder and encoder.
|
|
9
|
+
*
|
|
10
|
+
* Written from the public LZMA format description (LZMA SDK `lzma-specification.txt`).
|
|
11
|
+
* The SWF variant stores a 5-byte properties header and raw LZMA data with a known
|
|
12
|
+
* uncompressed size and usually no end marker.
|
|
13
|
+
*/
|
|
14
|
+
const errors_js_1 = require("../errors.js");
|
|
15
|
+
const NUM_STATES = 12;
|
|
16
|
+
const POS_STATES_MAX = 1 << 4;
|
|
17
|
+
const END_POS_MODEL_INDEX = 14;
|
|
18
|
+
const NUM_FULL_DISTANCES = 128;
|
|
19
|
+
const NUM_LEN_TO_POS_STATES = 4;
|
|
20
|
+
const NUM_ALIGN_BITS = 4;
|
|
21
|
+
const MATCH_MIN_LEN = 2;
|
|
22
|
+
const MATCH_MAX_LEN = 273;
|
|
23
|
+
const PROB_INIT = 1024;
|
|
24
|
+
const TOP = 0x1000000;
|
|
25
|
+
function parseLzmaProperties(props) {
|
|
26
|
+
if (props.length < 5)
|
|
27
|
+
throw new errors_js_1.SwfFormatError('LZMA properties must be 5 bytes');
|
|
28
|
+
let d = props[0];
|
|
29
|
+
if (d >= 9 * 5 * 5)
|
|
30
|
+
throw new errors_js_1.SwfFormatError(`Invalid LZMA properties byte ${d}`);
|
|
31
|
+
const lc = d % 9;
|
|
32
|
+
d = Math.floor(d / 9);
|
|
33
|
+
const lp = d % 5;
|
|
34
|
+
const pb = Math.floor(d / 5);
|
|
35
|
+
const dictSize = (props[1] | (props[2] << 8) | (props[3] << 16) | (props[4] << 24)) >>> 0;
|
|
36
|
+
return { lc, lp, pb, dictSize };
|
|
37
|
+
}
|
|
38
|
+
function encodeLzmaProperties(p) {
|
|
39
|
+
const out = new Uint8Array(5);
|
|
40
|
+
out[0] = (p.pb * 5 + p.lp) * 9 + p.lc;
|
|
41
|
+
out[1] = p.dictSize & 0xff;
|
|
42
|
+
out[2] = (p.dictSize >>> 8) & 0xff;
|
|
43
|
+
out[3] = (p.dictSize >>> 16) & 0xff;
|
|
44
|
+
out[4] = (p.dictSize >>> 24) & 0xff;
|
|
45
|
+
return out;
|
|
46
|
+
}
|
|
47
|
+
function probs(n) {
|
|
48
|
+
return new Uint16Array(n).fill(PROB_INIT);
|
|
49
|
+
}
|
|
50
|
+
class LenModel {
|
|
51
|
+
choice = probs(2); // [0] = choice, [1] = choice2
|
|
52
|
+
low = probs(POS_STATES_MAX << 3);
|
|
53
|
+
mid = probs(POS_STATES_MAX << 3);
|
|
54
|
+
high = probs(256);
|
|
55
|
+
}
|
|
56
|
+
class Model {
|
|
57
|
+
isMatch = probs(NUM_STATES << 4);
|
|
58
|
+
isRep = probs(NUM_STATES);
|
|
59
|
+
isRepG0 = probs(NUM_STATES);
|
|
60
|
+
isRepG1 = probs(NUM_STATES);
|
|
61
|
+
isRepG2 = probs(NUM_STATES);
|
|
62
|
+
isRep0Long = probs(NUM_STATES << 4);
|
|
63
|
+
posSlot = probs(NUM_LEN_TO_POS_STATES << 6);
|
|
64
|
+
specPos = probs(1 + NUM_FULL_DISTANCES - END_POS_MODEL_INDEX);
|
|
65
|
+
align = probs(1 << NUM_ALIGN_BITS);
|
|
66
|
+
len = new LenModel();
|
|
67
|
+
repLen = new LenModel();
|
|
68
|
+
literal;
|
|
69
|
+
constructor(lc, lp) {
|
|
70
|
+
this.literal = probs(0x300 << (lc + lp));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
function stateAfterLiteral(s) {
|
|
74
|
+
return s < 4 ? 0 : s < 10 ? s - 3 : s - 6;
|
|
75
|
+
}
|
|
76
|
+
// ---------------------------------------------------------------------------
|
|
77
|
+
// Decoder
|
|
78
|
+
// ---------------------------------------------------------------------------
|
|
79
|
+
class RangeDecoder {
|
|
80
|
+
data;
|
|
81
|
+
range = 0xffffffff;
|
|
82
|
+
code = 0;
|
|
83
|
+
pos;
|
|
84
|
+
constructor(data, start = 0) {
|
|
85
|
+
this.data = data;
|
|
86
|
+
this.pos = start;
|
|
87
|
+
if (this.next() !== 0)
|
|
88
|
+
throw new errors_js_1.SwfFormatError('Corrupted LZMA stream (first byte must be 0)');
|
|
89
|
+
for (let i = 0; i < 4; i++)
|
|
90
|
+
this.code = this.code * 256 + this.next();
|
|
91
|
+
if (this.code === this.range)
|
|
92
|
+
throw new errors_js_1.SwfFormatError('Corrupted LZMA stream');
|
|
93
|
+
}
|
|
94
|
+
next() {
|
|
95
|
+
// Reading past the end yields zeros; well-formed streams never depend on it.
|
|
96
|
+
return this.pos < this.data.length ? this.data[this.pos++] : (this.pos++, 0);
|
|
97
|
+
}
|
|
98
|
+
get overrun() {
|
|
99
|
+
return this.pos > this.data.length + 4;
|
|
100
|
+
}
|
|
101
|
+
bit(p, i) {
|
|
102
|
+
const prob = p[i];
|
|
103
|
+
const bound = (this.range >>> 11) * prob;
|
|
104
|
+
let b;
|
|
105
|
+
if (this.code < bound) {
|
|
106
|
+
this.range = bound;
|
|
107
|
+
p[i] = prob + ((2048 - prob) >>> 5);
|
|
108
|
+
b = 0;
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
this.range -= bound;
|
|
112
|
+
this.code -= bound;
|
|
113
|
+
p[i] = prob - (prob >>> 5);
|
|
114
|
+
b = 1;
|
|
115
|
+
}
|
|
116
|
+
if (this.range < TOP) {
|
|
117
|
+
this.range = this.range * 256;
|
|
118
|
+
this.code = this.code * 256 + this.next();
|
|
119
|
+
}
|
|
120
|
+
return b;
|
|
121
|
+
}
|
|
122
|
+
direct(numBits) {
|
|
123
|
+
let res = 0;
|
|
124
|
+
for (let i = 0; i < numBits; i++) {
|
|
125
|
+
this.range = this.range >>> 1;
|
|
126
|
+
let b = 0;
|
|
127
|
+
if (this.code >= this.range) {
|
|
128
|
+
this.code -= this.range;
|
|
129
|
+
b = 1;
|
|
130
|
+
}
|
|
131
|
+
res = res * 2 + b;
|
|
132
|
+
if (this.range < TOP) {
|
|
133
|
+
this.range = this.range * 256;
|
|
134
|
+
this.code = this.code * 256 + this.next();
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return res;
|
|
138
|
+
}
|
|
139
|
+
tree(p, base, numBits) {
|
|
140
|
+
let m = 1;
|
|
141
|
+
for (let i = 0; i < numBits; i++)
|
|
142
|
+
m = (m << 1) + this.bit(p, base + m);
|
|
143
|
+
return m - (1 << numBits);
|
|
144
|
+
}
|
|
145
|
+
reverseTree(p, base, numBits) {
|
|
146
|
+
let m = 1;
|
|
147
|
+
let sym = 0;
|
|
148
|
+
for (let i = 0; i < numBits; i++) {
|
|
149
|
+
const b = this.bit(p, base + m);
|
|
150
|
+
m = (m << 1) + b;
|
|
151
|
+
sym |= b << i;
|
|
152
|
+
}
|
|
153
|
+
return sym;
|
|
154
|
+
}
|
|
155
|
+
len(l, posState) {
|
|
156
|
+
if (this.bit(l.choice, 0) === 0)
|
|
157
|
+
return this.tree(l.low, posState << 3, 3);
|
|
158
|
+
if (this.bit(l.choice, 1) === 0)
|
|
159
|
+
return 8 + this.tree(l.mid, posState << 3, 3);
|
|
160
|
+
return 16 + this.tree(l.high, 0, 8);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Decompress raw LZMA data.
|
|
165
|
+
* @param props 5-byte LZMA properties
|
|
166
|
+
* @param data compressed stream (without properties)
|
|
167
|
+
* @param outSize exact uncompressed size
|
|
168
|
+
*/
|
|
169
|
+
function lzmaDecompress(props, data, outSize) {
|
|
170
|
+
const { lc, lp, pb } = parseLzmaProperties(props);
|
|
171
|
+
const m = new Model(lc, lp);
|
|
172
|
+
const rc = new RangeDecoder(data);
|
|
173
|
+
const out = new Uint8Array(outSize);
|
|
174
|
+
const pbMask = (1 << pb) - 1;
|
|
175
|
+
const lpMask = (1 << lp) - 1;
|
|
176
|
+
let state = 0;
|
|
177
|
+
let rep0 = 0;
|
|
178
|
+
let rep1 = 0;
|
|
179
|
+
let rep2 = 0;
|
|
180
|
+
let rep3 = 0;
|
|
181
|
+
let pos = 0;
|
|
182
|
+
while (pos < outSize) {
|
|
183
|
+
const posState = pos & pbMask;
|
|
184
|
+
if (rc.bit(m.isMatch, (state << 4) + posState) === 0) {
|
|
185
|
+
const prev = pos > 0 ? out[pos - 1] : 0;
|
|
186
|
+
const base = 0x300 * (((pos & lpMask) << lc) + (prev >>> (8 - lc)));
|
|
187
|
+
let sym = 1;
|
|
188
|
+
if (state >= 7) {
|
|
189
|
+
let matchByte = out[pos - rep0 - 1];
|
|
190
|
+
do {
|
|
191
|
+
const matchBit = (matchByte >>> 7) & 1;
|
|
192
|
+
matchByte <<= 1;
|
|
193
|
+
const b = rc.bit(m.literal, base + ((1 + matchBit) << 8) + sym);
|
|
194
|
+
sym = (sym << 1) | b;
|
|
195
|
+
if (matchBit !== b)
|
|
196
|
+
break;
|
|
197
|
+
} while (sym < 0x100);
|
|
198
|
+
}
|
|
199
|
+
while (sym < 0x100)
|
|
200
|
+
sym = (sym << 1) | rc.bit(m.literal, base + sym);
|
|
201
|
+
out[pos++] = sym & 0xff;
|
|
202
|
+
state = stateAfterLiteral(state);
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
205
|
+
let len;
|
|
206
|
+
if (rc.bit(m.isRep, state) !== 0) {
|
|
207
|
+
if (pos === 0)
|
|
208
|
+
throw new errors_js_1.SwfFormatError('Corrupted LZMA stream (rep match at start)');
|
|
209
|
+
if (rc.bit(m.isRepG0, state) === 0) {
|
|
210
|
+
if (rc.bit(m.isRep0Long, (state << 4) + posState) === 0) {
|
|
211
|
+
state = state < 7 ? 9 : 11;
|
|
212
|
+
out[pos] = out[pos - rep0 - 1];
|
|
213
|
+
pos++;
|
|
214
|
+
continue;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
let dist;
|
|
219
|
+
if (rc.bit(m.isRepG1, state) === 0) {
|
|
220
|
+
dist = rep1;
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
if (rc.bit(m.isRepG2, state) === 0) {
|
|
224
|
+
dist = rep2;
|
|
225
|
+
}
|
|
226
|
+
else {
|
|
227
|
+
dist = rep3;
|
|
228
|
+
rep3 = rep2;
|
|
229
|
+
}
|
|
230
|
+
rep2 = rep1;
|
|
231
|
+
}
|
|
232
|
+
rep1 = rep0;
|
|
233
|
+
rep0 = dist;
|
|
234
|
+
}
|
|
235
|
+
len = rc.len(m.repLen, posState);
|
|
236
|
+
state = state < 7 ? 8 : 11;
|
|
237
|
+
}
|
|
238
|
+
else {
|
|
239
|
+
rep3 = rep2;
|
|
240
|
+
rep2 = rep1;
|
|
241
|
+
rep1 = rep0;
|
|
242
|
+
len = rc.len(m.len, posState);
|
|
243
|
+
state = state < 7 ? 7 : 10;
|
|
244
|
+
const lenState = len < NUM_LEN_TO_POS_STATES - 1 ? len : NUM_LEN_TO_POS_STATES - 1;
|
|
245
|
+
const posSlot = rc.tree(m.posSlot, lenState << 6, 6);
|
|
246
|
+
if (posSlot < 4) {
|
|
247
|
+
rep0 = posSlot;
|
|
248
|
+
}
|
|
249
|
+
else {
|
|
250
|
+
const numDirectBits = (posSlot >>> 1) - 1;
|
|
251
|
+
let dist = (2 | (posSlot & 1)) * 2 ** numDirectBits;
|
|
252
|
+
if (posSlot < END_POS_MODEL_INDEX) {
|
|
253
|
+
dist += rc.reverseTree(m.specPos, dist - posSlot, numDirectBits);
|
|
254
|
+
}
|
|
255
|
+
else {
|
|
256
|
+
dist += rc.direct(numDirectBits - NUM_ALIGN_BITS) * 16;
|
|
257
|
+
dist += rc.reverseTree(m.align, 0, NUM_ALIGN_BITS);
|
|
258
|
+
}
|
|
259
|
+
rep0 = dist;
|
|
260
|
+
}
|
|
261
|
+
if (rep0 === 0xffffffff)
|
|
262
|
+
break; // end marker
|
|
263
|
+
if (rep0 >= pos)
|
|
264
|
+
throw new errors_js_1.SwfFormatError('Corrupted LZMA stream (distance out of range)');
|
|
265
|
+
}
|
|
266
|
+
len += MATCH_MIN_LEN;
|
|
267
|
+
let src = pos - rep0 - 1;
|
|
268
|
+
const end = Math.min(outSize, pos + len);
|
|
269
|
+
while (pos < end)
|
|
270
|
+
out[pos++] = out[src++];
|
|
271
|
+
}
|
|
272
|
+
if (rc.overrun)
|
|
273
|
+
throw new errors_js_1.SwfFormatError('Corrupted LZMA stream (input truncated)');
|
|
274
|
+
return out;
|
|
275
|
+
}
|
|
276
|
+
// ---------------------------------------------------------------------------
|
|
277
|
+
// Encoder
|
|
278
|
+
// ---------------------------------------------------------------------------
|
|
279
|
+
class RangeEncoder {
|
|
280
|
+
low = 0;
|
|
281
|
+
range = 0xffffffff;
|
|
282
|
+
cache = 0;
|
|
283
|
+
cacheSize = 1;
|
|
284
|
+
buf;
|
|
285
|
+
length = 0;
|
|
286
|
+
constructor(capacity) {
|
|
287
|
+
this.buf = new Uint8Array(Math.max(1024, capacity));
|
|
288
|
+
}
|
|
289
|
+
write(b) {
|
|
290
|
+
if (this.length === this.buf.length) {
|
|
291
|
+
const next = new Uint8Array(this.buf.length * 2);
|
|
292
|
+
next.set(this.buf);
|
|
293
|
+
this.buf = next;
|
|
294
|
+
}
|
|
295
|
+
this.buf[this.length++] = b;
|
|
296
|
+
}
|
|
297
|
+
shiftLow() {
|
|
298
|
+
const lo32 = this.low >>> 0;
|
|
299
|
+
const carry = this.low > 0xffffffff ? 1 : 0;
|
|
300
|
+
if (lo32 < 0xff000000 || carry !== 0) {
|
|
301
|
+
let temp = this.cache;
|
|
302
|
+
do {
|
|
303
|
+
this.write((temp + carry) & 0xff);
|
|
304
|
+
temp = 0xff;
|
|
305
|
+
} while (--this.cacheSize !== 0);
|
|
306
|
+
this.cache = lo32 >>> 24;
|
|
307
|
+
}
|
|
308
|
+
this.cacheSize++;
|
|
309
|
+
this.low = (lo32 & 0x00ffffff) * 256;
|
|
310
|
+
}
|
|
311
|
+
bit(p, i, b) {
|
|
312
|
+
const prob = p[i];
|
|
313
|
+
const bound = (this.range >>> 11) * prob;
|
|
314
|
+
if (b === 0) {
|
|
315
|
+
this.range = bound;
|
|
316
|
+
p[i] = prob + ((2048 - prob) >>> 5);
|
|
317
|
+
}
|
|
318
|
+
else {
|
|
319
|
+
this.low += bound;
|
|
320
|
+
this.range -= bound;
|
|
321
|
+
p[i] = prob - (prob >>> 5);
|
|
322
|
+
}
|
|
323
|
+
while (this.range < TOP) {
|
|
324
|
+
this.range = this.range * 256;
|
|
325
|
+
this.shiftLow();
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
direct(value, numBits) {
|
|
329
|
+
for (let i = numBits - 1; i >= 0; i--) {
|
|
330
|
+
this.range = this.range >>> 1;
|
|
331
|
+
if (Math.floor(value / 2 ** i) & 1)
|
|
332
|
+
this.low += this.range;
|
|
333
|
+
while (this.range < TOP) {
|
|
334
|
+
this.range = this.range * 256;
|
|
335
|
+
this.shiftLow();
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
tree(p, base, numBits, sym) {
|
|
340
|
+
let m = 1;
|
|
341
|
+
for (let i = numBits - 1; i >= 0; i--) {
|
|
342
|
+
const b = (sym >>> i) & 1;
|
|
343
|
+
this.bit(p, base + m, b);
|
|
344
|
+
m = (m << 1) | b;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
reverseTree(p, base, numBits, sym) {
|
|
348
|
+
let m = 1;
|
|
349
|
+
for (let i = 0; i < numBits; i++) {
|
|
350
|
+
const b = sym & 1;
|
|
351
|
+
sym >>>= 1;
|
|
352
|
+
this.bit(p, base + m, b);
|
|
353
|
+
m = (m << 1) | b;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
len(l, posState, len) {
|
|
357
|
+
if (len < 8) {
|
|
358
|
+
this.bit(l.choice, 0, 0);
|
|
359
|
+
this.tree(l.low, posState << 3, 3, len);
|
|
360
|
+
}
|
|
361
|
+
else if (len < 16) {
|
|
362
|
+
this.bit(l.choice, 0, 1);
|
|
363
|
+
this.bit(l.choice, 1, 0);
|
|
364
|
+
this.tree(l.mid, posState << 3, 3, len - 8);
|
|
365
|
+
}
|
|
366
|
+
else {
|
|
367
|
+
this.bit(l.choice, 0, 1);
|
|
368
|
+
this.bit(l.choice, 1, 1);
|
|
369
|
+
this.tree(l.high, 0, 8, len - 16);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
finish() {
|
|
373
|
+
for (let i = 0; i < 5; i++)
|
|
374
|
+
this.shiftLow();
|
|
375
|
+
return this.buf.slice(0, this.length);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
function posSlotOf(dist) {
|
|
379
|
+
if (dist < 4)
|
|
380
|
+
return dist;
|
|
381
|
+
const n = 31 - Math.clz32(dist);
|
|
382
|
+
return (n << 1) | ((dist >>> (n - 1)) & 1);
|
|
383
|
+
}
|
|
384
|
+
/**
|
|
385
|
+
* Compress data with LZMA. Returns the 5-byte properties and the raw stream
|
|
386
|
+
* (no end marker, no size header), as stored in ZWS SWF files.
|
|
387
|
+
*/
|
|
388
|
+
function lzmaCompress(input, options = {}) {
|
|
389
|
+
const lc = options.lc ?? 3;
|
|
390
|
+
const lp = options.lp ?? 0;
|
|
391
|
+
const pb = options.pb ?? 2;
|
|
392
|
+
let dictSize = options.dictSize ?? 0;
|
|
393
|
+
if (!dictSize) {
|
|
394
|
+
dictSize = 1 << 16;
|
|
395
|
+
while (dictSize < input.length && dictSize < 1 << 26)
|
|
396
|
+
dictSize *= 2;
|
|
397
|
+
}
|
|
398
|
+
const depth = options.depth ?? 48;
|
|
399
|
+
const niceLength = Math.min(options.niceLength ?? 128, MATCH_MAX_LEN);
|
|
400
|
+
const m = new Model(lc, lp);
|
|
401
|
+
const rc = new RangeEncoder((input.length >>> 1) + 1024);
|
|
402
|
+
const pbMask = (1 << pb) - 1;
|
|
403
|
+
const lpMask = (1 << lp) - 1;
|
|
404
|
+
const n = input.length;
|
|
405
|
+
const HASH_BITS = 18;
|
|
406
|
+
const head = new Int32Array(1 << HASH_BITS).fill(-1);
|
|
407
|
+
const prev = new Int32Array(n);
|
|
408
|
+
const hash3 = (i) => Math.imul(input[i] | (input[i + 1] << 8) | (input[i + 2] << 16), 0x9e3779b1) >>> (32 - HASH_BITS);
|
|
409
|
+
const insert = (i) => {
|
|
410
|
+
if (i + 2 >= n)
|
|
411
|
+
return;
|
|
412
|
+
const h = hash3(i);
|
|
413
|
+
prev[i] = head[h];
|
|
414
|
+
head[h] = i;
|
|
415
|
+
};
|
|
416
|
+
const reps = [0, 0, 0, 0];
|
|
417
|
+
let state = 0;
|
|
418
|
+
let pos = 0;
|
|
419
|
+
const matchLen = (a, b, max) => {
|
|
420
|
+
let l = 0;
|
|
421
|
+
while (l < max && input[a + l] === input[b + l])
|
|
422
|
+
l++;
|
|
423
|
+
return l;
|
|
424
|
+
};
|
|
425
|
+
const encodeLiteral = () => {
|
|
426
|
+
const posState = pos & pbMask;
|
|
427
|
+
rc.bit(m.isMatch, (state << 4) + posState, 0);
|
|
428
|
+
const prevByte = pos > 0 ? input[pos - 1] : 0;
|
|
429
|
+
const base = 0x300 * (((pos & lpMask) << lc) + (prevByte >>> (8 - lc)));
|
|
430
|
+
const byte = input[pos];
|
|
431
|
+
let sym = 1;
|
|
432
|
+
if (state >= 7) {
|
|
433
|
+
const matchByte = input[pos - reps[0] - 1];
|
|
434
|
+
let matched = true;
|
|
435
|
+
for (let i = 7; i >= 0; i--) {
|
|
436
|
+
const b = (byte >>> i) & 1;
|
|
437
|
+
if (matched) {
|
|
438
|
+
const mb = (matchByte >>> i) & 1;
|
|
439
|
+
rc.bit(m.literal, base + ((1 + mb) << 8) + sym, b);
|
|
440
|
+
matched = mb === b;
|
|
441
|
+
}
|
|
442
|
+
else {
|
|
443
|
+
rc.bit(m.literal, base + sym, b);
|
|
444
|
+
}
|
|
445
|
+
sym = (sym << 1) | b;
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
else {
|
|
449
|
+
for (let i = 7; i >= 0; i--) {
|
|
450
|
+
const b = (byte >>> i) & 1;
|
|
451
|
+
rc.bit(m.literal, base + sym, b);
|
|
452
|
+
sym = (sym << 1) | b;
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
state = stateAfterLiteral(state);
|
|
456
|
+
};
|
|
457
|
+
const encodeShortRep = () => {
|
|
458
|
+
const posState = pos & pbMask;
|
|
459
|
+
rc.bit(m.isMatch, (state << 4) + posState, 1);
|
|
460
|
+
rc.bit(m.isRep, state, 1);
|
|
461
|
+
rc.bit(m.isRepG0, state, 0);
|
|
462
|
+
rc.bit(m.isRep0Long, (state << 4) + posState, 0);
|
|
463
|
+
state = state < 7 ? 9 : 11;
|
|
464
|
+
};
|
|
465
|
+
const encodeRep = (repIndex, len) => {
|
|
466
|
+
const posState = pos & pbMask;
|
|
467
|
+
rc.bit(m.isMatch, (state << 4) + posState, 1);
|
|
468
|
+
rc.bit(m.isRep, state, 1);
|
|
469
|
+
if (repIndex === 0) {
|
|
470
|
+
rc.bit(m.isRepG0, state, 0);
|
|
471
|
+
rc.bit(m.isRep0Long, (state << 4) + posState, 1);
|
|
472
|
+
}
|
|
473
|
+
else {
|
|
474
|
+
rc.bit(m.isRepG0, state, 1);
|
|
475
|
+
if (repIndex === 1) {
|
|
476
|
+
rc.bit(m.isRepG1, state, 0);
|
|
477
|
+
}
|
|
478
|
+
else {
|
|
479
|
+
rc.bit(m.isRepG1, state, 1);
|
|
480
|
+
rc.bit(m.isRepG2, state, repIndex - 2);
|
|
481
|
+
}
|
|
482
|
+
const dist = reps[repIndex];
|
|
483
|
+
for (let i = repIndex; i > 0; i--)
|
|
484
|
+
reps[i] = reps[i - 1];
|
|
485
|
+
reps[0] = dist;
|
|
486
|
+
}
|
|
487
|
+
rc.len(m.repLen, posState, len - MATCH_MIN_LEN);
|
|
488
|
+
state = state < 7 ? 8 : 11;
|
|
489
|
+
};
|
|
490
|
+
const encodeMatch = (dist, len) => {
|
|
491
|
+
const posState = pos & pbMask;
|
|
492
|
+
rc.bit(m.isMatch, (state << 4) + posState, 1);
|
|
493
|
+
rc.bit(m.isRep, state, 0);
|
|
494
|
+
rc.len(m.len, posState, len - MATCH_MIN_LEN);
|
|
495
|
+
const lenState = Math.min(len - MATCH_MIN_LEN, NUM_LEN_TO_POS_STATES - 1);
|
|
496
|
+
const posSlot = posSlotOf(dist);
|
|
497
|
+
rc.tree(m.posSlot, lenState << 6, 6, posSlot);
|
|
498
|
+
if (posSlot >= 4) {
|
|
499
|
+
const footerBits = (posSlot >>> 1) - 1;
|
|
500
|
+
const base = (2 | (posSlot & 1)) << footerBits;
|
|
501
|
+
const reduced = dist - base;
|
|
502
|
+
if (posSlot < END_POS_MODEL_INDEX) {
|
|
503
|
+
rc.reverseTree(m.specPos, base - posSlot, footerBits, reduced);
|
|
504
|
+
}
|
|
505
|
+
else {
|
|
506
|
+
rc.direct(reduced >>> NUM_ALIGN_BITS, footerBits - NUM_ALIGN_BITS);
|
|
507
|
+
rc.reverseTree(m.align, 0, NUM_ALIGN_BITS, reduced & 0xf);
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
reps[3] = reps[2];
|
|
511
|
+
reps[2] = reps[1];
|
|
512
|
+
reps[1] = reps[0];
|
|
513
|
+
reps[0] = dist;
|
|
514
|
+
state = state < 7 ? 7 : 10;
|
|
515
|
+
};
|
|
516
|
+
while (pos < n) {
|
|
517
|
+
const maxLen = Math.min(MATCH_MAX_LEN, n - pos);
|
|
518
|
+
// Repeat matches (cheap to encode).
|
|
519
|
+
let bestRepLen = 0;
|
|
520
|
+
let bestRepIndex = 0;
|
|
521
|
+
if (pos > 0 && maxLen >= 2) {
|
|
522
|
+
for (let r = 0; r < 4; r++) {
|
|
523
|
+
const src = pos - reps[r] - 1;
|
|
524
|
+
if (src < 0)
|
|
525
|
+
continue;
|
|
526
|
+
const l = matchLen(src, pos, maxLen);
|
|
527
|
+
if (l > bestRepLen) {
|
|
528
|
+
bestRepLen = l;
|
|
529
|
+
bestRepIndex = r;
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
// Main match via hash chains.
|
|
534
|
+
let bestLen = 0;
|
|
535
|
+
let bestDist = 0;
|
|
536
|
+
if (maxLen >= 3 && pos + 2 < n) {
|
|
537
|
+
let cand = head[hash3(pos)];
|
|
538
|
+
let chain = depth;
|
|
539
|
+
const minPos = pos - dictSize;
|
|
540
|
+
while (cand >= 0 && cand >= minPos && chain-- > 0) {
|
|
541
|
+
if (input[cand + bestLen] === input[pos + bestLen]) {
|
|
542
|
+
const l = matchLen(cand, pos, maxLen);
|
|
543
|
+
if (l > bestLen) {
|
|
544
|
+
bestLen = l;
|
|
545
|
+
bestDist = pos - cand - 1;
|
|
546
|
+
if (l >= niceLength)
|
|
547
|
+
break;
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
cand = prev[cand];
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
let advance;
|
|
554
|
+
if (bestRepLen >= 2 && bestRepLen + 1 >= bestLen) {
|
|
555
|
+
encodeRep(bestRepIndex, bestRepLen);
|
|
556
|
+
advance = bestRepLen;
|
|
557
|
+
}
|
|
558
|
+
else if (bestLen >= 3 && !(bestLen === 3 && bestDist >= 1 << 14)) {
|
|
559
|
+
encodeMatch(bestDist, bestLen);
|
|
560
|
+
advance = bestLen;
|
|
561
|
+
}
|
|
562
|
+
else if (pos > reps[0] && input[pos] === input[pos - reps[0] - 1] && state >= 7) {
|
|
563
|
+
encodeShortRep();
|
|
564
|
+
advance = 1;
|
|
565
|
+
}
|
|
566
|
+
else {
|
|
567
|
+
encodeLiteral();
|
|
568
|
+
advance = 1;
|
|
569
|
+
}
|
|
570
|
+
for (let i = 0; i < advance; i++)
|
|
571
|
+
insert(pos + i);
|
|
572
|
+
pos += advance;
|
|
573
|
+
}
|
|
574
|
+
return { props: encodeLzmaProperties({ lc, lp, pb, dictSize }), data: rc.finish() };
|
|
575
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type LzmaCompressOptions } from './lzma.js';
|
|
2
|
+
export type SwfCompression = 'none' | 'zlib' | 'lzma';
|
|
3
|
+
export interface SwfContainer {
|
|
4
|
+
compression: SwfCompression;
|
|
5
|
+
version: number;
|
|
6
|
+
/** Uncompressed SWF body: everything after the 8-byte file header. */
|
|
7
|
+
body: Uint8Array;
|
|
8
|
+
}
|
|
9
|
+
/** Detects whether a buffer starts with an SWF signature. */
|
|
10
|
+
export declare function isSwf(bytes: Uint8Array): boolean;
|
|
11
|
+
/** Unwraps an FWS/CWS/ZWS file into its uncompressed body. */
|
|
12
|
+
export declare function unpackSwf(bytes: Uint8Array): SwfContainer;
|
|
13
|
+
export interface PackOptions {
|
|
14
|
+
/** zlib level 0-9 (default 9). */
|
|
15
|
+
zlibLevel?: number;
|
|
16
|
+
lzma?: LzmaCompressOptions;
|
|
17
|
+
}
|
|
18
|
+
/** Wraps an uncompressed SWF body in an FWS/CWS/ZWS file. */
|
|
19
|
+
export declare function packSwf(container: SwfContainer, options?: PackOptions): Uint8Array;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isSwf = isSwf;
|
|
4
|
+
exports.unpackSwf = unpackSwf;
|
|
5
|
+
exports.packSwf = packSwf;
|
|
6
|
+
const node_zlib_1 = require("node:zlib");
|
|
7
|
+
const errors_js_1 = require("../errors.js");
|
|
8
|
+
const lzma_js_1 = require("./lzma.js");
|
|
9
|
+
const SIG = {
|
|
10
|
+
FWS: [0x46, 0x57, 0x53],
|
|
11
|
+
CWS: [0x43, 0x57, 0x53],
|
|
12
|
+
ZWS: [0x5a, 0x57, 0x53],
|
|
13
|
+
};
|
|
14
|
+
function sigIs(b, sig) {
|
|
15
|
+
return b[0] === sig[0] && b[1] === sig[1] && b[2] === sig[2];
|
|
16
|
+
}
|
|
17
|
+
function u32(b, o) {
|
|
18
|
+
return (b[o] | (b[o + 1] << 8) | (b[o + 2] << 16) | (b[o + 3] << 24)) >>> 0;
|
|
19
|
+
}
|
|
20
|
+
/** Detects whether a buffer starts with an SWF signature. */
|
|
21
|
+
function isSwf(bytes) {
|
|
22
|
+
return bytes.length >= 8 && (sigIs(bytes, SIG.FWS) || sigIs(bytes, SIG.CWS) || sigIs(bytes, SIG.ZWS));
|
|
23
|
+
}
|
|
24
|
+
/** Unwraps an FWS/CWS/ZWS file into its uncompressed body. */
|
|
25
|
+
function unpackSwf(bytes) {
|
|
26
|
+
if (bytes.length < 8)
|
|
27
|
+
throw new errors_js_1.SwfFormatError('File too small to be an SWF');
|
|
28
|
+
const version = bytes[3];
|
|
29
|
+
const fileLength = u32(bytes, 4);
|
|
30
|
+
const bodyLength = fileLength - 8;
|
|
31
|
+
if (bodyLength < 0)
|
|
32
|
+
throw new errors_js_1.SwfFormatError(`Invalid SWF file length ${fileLength}`);
|
|
33
|
+
if (sigIs(bytes, SIG.FWS)) {
|
|
34
|
+
// Some tools write a wrong length; trust the actual data when it is shorter.
|
|
35
|
+
const body = bytes.subarray(8, Math.min(bytes.length, fileLength)).slice();
|
|
36
|
+
return { compression: 'none', version, body };
|
|
37
|
+
}
|
|
38
|
+
if (sigIs(bytes, SIG.CWS)) {
|
|
39
|
+
let body;
|
|
40
|
+
try {
|
|
41
|
+
body = new Uint8Array((0, node_zlib_1.inflateSync)(bytes.subarray(8), { finishFlush: 2 /* Z_SYNC_FLUSH: tolerate truncated streams */ }));
|
|
42
|
+
}
|
|
43
|
+
catch (e) {
|
|
44
|
+
throw new errors_js_1.SwfFormatError(`zlib decompression failed: ${e.message}`);
|
|
45
|
+
}
|
|
46
|
+
if (body.length > bodyLength)
|
|
47
|
+
body = body.subarray(0, bodyLength);
|
|
48
|
+
return { compression: 'zlib', version, body };
|
|
49
|
+
}
|
|
50
|
+
if (sigIs(bytes, SIG.ZWS)) {
|
|
51
|
+
if (bytes.length < 17)
|
|
52
|
+
throw new errors_js_1.SwfFormatError('Truncated ZWS header');
|
|
53
|
+
const compressedLength = u32(bytes, 8);
|
|
54
|
+
const props = bytes.subarray(12, 17);
|
|
55
|
+
const data = bytes.subarray(17, Math.min(bytes.length, 17 + compressedLength));
|
|
56
|
+
const body = (0, lzma_js_1.lzmaDecompress)(props, data, bodyLength);
|
|
57
|
+
return { compression: 'lzma', version, body };
|
|
58
|
+
}
|
|
59
|
+
throw new errors_js_1.SwfFormatError('Not an SWF file (missing FWS/CWS/ZWS signature)');
|
|
60
|
+
}
|
|
61
|
+
/** Wraps an uncompressed SWF body in an FWS/CWS/ZWS file. */
|
|
62
|
+
function packSwf(container, options = {}) {
|
|
63
|
+
const { body, version, compression } = container;
|
|
64
|
+
const fileLength = body.length + 8;
|
|
65
|
+
const header = (sig) => {
|
|
66
|
+
const h = new Uint8Array(8);
|
|
67
|
+
h.set(sig, 0);
|
|
68
|
+
h[3] = version;
|
|
69
|
+
new DataView(h.buffer).setUint32(4, fileLength, true);
|
|
70
|
+
return h;
|
|
71
|
+
};
|
|
72
|
+
if (compression === 'none') {
|
|
73
|
+
const out = new Uint8Array(fileLength);
|
|
74
|
+
out.set(header(SIG.FWS), 0);
|
|
75
|
+
out.set(body, 8);
|
|
76
|
+
return out;
|
|
77
|
+
}
|
|
78
|
+
if (compression === 'zlib') {
|
|
79
|
+
const z = (0, node_zlib_1.deflateSync)(body, { level: options.zlibLevel ?? 9 });
|
|
80
|
+
const out = new Uint8Array(8 + z.length);
|
|
81
|
+
out.set(header(SIG.CWS), 0);
|
|
82
|
+
out.set(z, 8);
|
|
83
|
+
return out;
|
|
84
|
+
}
|
|
85
|
+
const { props, data } = (0, lzma_js_1.lzmaCompress)(body, options.lzma);
|
|
86
|
+
const out = new Uint8Array(17 + data.length);
|
|
87
|
+
out.set(header(SIG.ZWS), 0);
|
|
88
|
+
new DataView(out.buffer).setUint32(8, data.length, true);
|
|
89
|
+
out.set(props, 12);
|
|
90
|
+
out.set(data, 17);
|
|
91
|
+
return out;
|
|
92
|
+
}
|