@cloudpss/compress 0.3.0-alpha.14 → 0.3.0-alpha.22
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/README.md +31 -13
- package/benchmark.js +62 -0
- package/dist/{cjs/gzip → gzip}/index-browser.d.ts +0 -0
- package/dist/{esm/gzip → gzip}/index-browser.js +0 -0
- package/dist/gzip/index-browser.js.map +1 -0
- package/dist/{cjs/gzip → gzip}/index.d.ts +0 -0
- package/dist/{esm/gzip → gzip}/index.js +0 -0
- package/dist/gzip/index.js.map +1 -0
- package/dist/{cjs/index.d.ts → index.d.ts} +2 -0
- package/dist/index.js +55 -0
- package/dist/index.js.map +1 -0
- package/dist/zstd/index-browser.d.ts +2 -0
- package/dist/zstd/index-browser.js +3 -0
- package/dist/zstd/index-browser.js.map +1 -0
- package/dist/{cjs/zstd → zstd}/index.d.ts +0 -0
- package/dist/zstd/index.js +14 -0
- package/dist/zstd/index.js.map +1 -0
- package/dist/zstd/wasm/compress.d.ts +2 -0
- package/dist/zstd/wasm/compress.js +28 -0
- package/dist/zstd/wasm/compress.js.map +1 -0
- package/dist/zstd/wasm/decompress.d.ts +6 -0
- package/dist/zstd/wasm/decompress.js +30 -0
- package/dist/zstd/wasm/decompress.js.map +1 -0
- package/dist/zstd/wasm/module.d.ts +2 -0
- package/dist/zstd/wasm/module.js +4 -0
- package/dist/zstd/wasm/module.js.map +1 -0
- package/package.json +13 -13
- package/src/index.ts +30 -13
- package/src/zstd/index-browser.ts +2 -0
- package/src/zstd/index.ts +7 -18
- package/src/zstd/wasm/compress.ts +27 -0
- package/src/zstd/wasm/decompress.ts +37 -0
- package/src/zstd/wasm/module.ts +5 -0
- package/tsconfig.json +1 -2
- package/wasm/zstd.g.d.ts +16 -0
- package/wasm/zstd.g.js +29 -0
- package/dist/cjs/gzip/index-browser.js +0 -15
- package/dist/cjs/gzip/index-browser.js.map +0 -1
- package/dist/cjs/gzip/index.js +0 -27
- package/dist/cjs/gzip/index.js.map +0 -1
- package/dist/cjs/index.js +0 -46
- package/dist/cjs/index.js.map +0 -1
- package/dist/cjs/zstd/index.js +0 -29
- package/dist/cjs/zstd/index.js.map +0 -1
- package/dist/cjs/zstd/lib/errors/index.d.ts +0 -1
- package/dist/cjs/zstd/lib/errors/index.js +0 -16
- package/dist/cjs/zstd/lib/errors/index.js.map +0 -1
- package/dist/cjs/zstd/lib/index.node.d.ts +0 -3
- package/dist/cjs/zstd/lib/index.node.js +0 -45
- package/dist/cjs/zstd/lib/index.node.js.map +0 -1
- package/dist/cjs/zstd/lib/index.web.d.ts +0 -3
- package/dist/cjs/zstd/lib/index.web.js +0 -44
- package/dist/cjs/zstd/lib/index.web.js.map +0 -1
- package/dist/cjs/zstd/lib/module.d.ts +0 -3
- package/dist/cjs/zstd/lib/module.js +0 -33
- package/dist/cjs/zstd/lib/module.js.map +0 -1
- package/dist/cjs/zstd/lib/simple/compress.d.ts +0 -1
- package/dist/cjs/zstd/lib/simple/compress.js +0 -46
- package/dist/cjs/zstd/lib/simple/compress.js.map +0 -1
- package/dist/cjs/zstd/lib/simple/decompress.d.ts +0 -3
- package/dist/cjs/zstd/lib/simple/decompress.js +0 -46
- package/dist/cjs/zstd/lib/simple/decompress.js.map +0 -1
- package/dist/cjs/zstd/lib/wasm/zstd.d.ts +0 -2
- package/dist/cjs/zstd/lib/wasm/zstd.js +0 -324
- package/dist/cjs/zstd/lib/wasm/zstd.js.map +0 -1
- package/dist/cjs/zstd/lib/wasm/zstd.wasm.d.ts +0 -1
- package/dist/cjs/zstd/lib/wasm/zstd.wasm.js +0 -5
- package/dist/cjs/zstd/lib/wasm/zstd.wasm.js.map +0 -1
- package/dist/esm/gzip/index-browser.d.ts +0 -4
- package/dist/esm/gzip/index-browser.js.map +0 -1
- package/dist/esm/gzip/index.d.ts +0 -4
- package/dist/esm/gzip/index.js.map +0 -1
- package/dist/esm/index.d.ts +0 -16
- package/dist/esm/index.js +0 -41
- package/dist/esm/index.js.map +0 -1
- package/dist/esm/zstd/index.d.ts +0 -4
- package/dist/esm/zstd/index.js +0 -24
- package/dist/esm/zstd/index.js.map +0 -1
- package/dist/esm/zstd/lib/errors/index.d.ts +0 -1
- package/dist/esm/zstd/lib/errors/index.js +0 -12
- package/dist/esm/zstd/lib/errors/index.js.map +0 -1
- package/dist/esm/zstd/lib/index.node.d.ts +0 -3
- package/dist/esm/zstd/lib/index.node.js +0 -31
- package/dist/esm/zstd/lib/index.node.js.map +0 -1
- package/dist/esm/zstd/lib/index.web.d.ts +0 -3
- package/dist/esm/zstd/lib/index.web.js +0 -30
- package/dist/esm/zstd/lib/index.web.js.map +0 -1
- package/dist/esm/zstd/lib/module.d.ts +0 -3
- package/dist/esm/zstd/lib/module.js +0 -29
- package/dist/esm/zstd/lib/module.js.map +0 -1
- package/dist/esm/zstd/lib/simple/compress.d.ts +0 -1
- package/dist/esm/zstd/lib/simple/compress.js +0 -42
- package/dist/esm/zstd/lib/simple/compress.js.map +0 -1
- package/dist/esm/zstd/lib/simple/decompress.d.ts +0 -3
- package/dist/esm/zstd/lib/simple/decompress.js +0 -42
- package/dist/esm/zstd/lib/simple/decompress.js.map +0 -1
- package/dist/esm/zstd/lib/wasm/zstd.d.ts +0 -2
- package/dist/esm/zstd/lib/wasm/zstd.js +0 -324
- package/dist/esm/zstd/lib/wasm/zstd.js.map +0 -1
- package/dist/esm/zstd/lib/wasm/zstd.wasm.d.ts +0 -1
- package/dist/esm/zstd/lib/wasm/zstd.wasm.js +0 -2
- package/dist/esm/zstd/lib/wasm/zstd.wasm.js.map +0 -1
- package/update-zstd.ps1 +0 -11
package/README.md
CHANGED
|
@@ -6,10 +6,11 @@ Be carful when handling binary files since their data might be confusing with ma
|
|
|
6
6
|
|
|
7
7
|
## Algorithms
|
|
8
8
|
|
|
9
|
-
| Algorithm
|
|
10
|
-
|
|
|
11
|
-
| gzip
|
|
12
|
-
| Zstandard
|
|
9
|
+
| Algorithm | Magic number | Filename extension | Mime type |
|
|
10
|
+
| ----------------------- | ------------------------------------------- | ------------------ | ------------------ |
|
|
11
|
+
| gzip | `␟ (\x1F)` `� (\x8B)` | .gz | application/gzip |
|
|
12
|
+
| Zstandard | `( (\x28)` `� (\xB5)` `/ (\x2F)` `� (\xFD)` | .zst | application/zstd |
|
|
13
|
+
| brotli (benchmark only) | None (any data might be brotli) | .br | application/brotli |
|
|
13
14
|
|
|
14
15
|
## Benchmarks
|
|
15
16
|
|
|
@@ -18,14 +19,31 @@ Be carful when handling binary files since their data might be confusing with ma
|
|
|
18
19
|
yarn run v1.22.15
|
|
19
20
|
$ node ./benchmark
|
|
20
21
|
File: 四川-PSS独立-直流等值机_Main.cproj Raw: 12.1 MiB
|
|
21
|
-
gzip(wasm):
|
|
22
|
-
gzip(node):
|
|
23
|
-
gzip(pako):
|
|
24
|
-
zstd(
|
|
22
|
+
gzip -d (wasm): 13.03(953 kiB) 371.84ms 193.38ms
|
|
23
|
+
gzip -d (node): 12.65(981 kiB) 115.73ms 17.17ms
|
|
24
|
+
gzip -d (pako): 12.65(981 kiB) 381.96ms 113.91ms
|
|
25
|
+
zstd -4 (node): 17.37(714 kiB) 25.31ms 15.97ms
|
|
26
|
+
zstd -3 (Oz,wasm): 17.40(713 kiB) 53.01ms 24.49ms
|
|
27
|
+
zstd -3 (O3,wasm): 17.40(713 kiB) 30.39ms 16.01ms
|
|
28
|
+
br -3 (node): 18.32(677 kiB) 49.92ms 18.48ms
|
|
29
|
+
br -1 (wasm): 3.90(3.11 MiB) 450.04ms 171.55ms
|
|
30
|
+
File: 电磁暂态方案 1_参数方案 1 (2).cjob Raw: 8.76 MiB
|
|
31
|
+
gzip -d (wasm): 3.69(2.37 MiB) 661.18ms 182.66ms
|
|
32
|
+
gzip -d (node): 3.68(2.38 MiB) 197.01ms 18.04ms
|
|
33
|
+
gzip -d (pako): 3.68(2.38 MiB) 456.53ms 101.31ms
|
|
34
|
+
zstd -4 (node): 3.45(2.54 MiB) 66.06ms 15.66ms
|
|
35
|
+
zstd -3 (Oz,wasm): 3.47(2.52 MiB) 119.57ms 36.27ms
|
|
36
|
+
zstd -3 (O3,wasm): 3.47(2.52 MiB) 66.22ms 18.07ms
|
|
37
|
+
br -3 (node): 3.63(2.41 MiB) 84.41ms 24.57ms
|
|
38
|
+
br -1 (wasm): 2.92(3 MiB) 396.91ms 168.17ms
|
|
25
39
|
File: 电磁暂态方案 1_参数方案 1.cjob Raw: 24.1 MiB
|
|
26
|
-
gzip(wasm):
|
|
27
|
-
gzip(node):
|
|
28
|
-
gzip(pako):
|
|
29
|
-
zstd(
|
|
30
|
-
|
|
40
|
+
gzip -d (wasm): 4.18(5.77 MiB) 1314.32ms 455.43ms
|
|
41
|
+
gzip -d (node): 4.17(5.79 MiB) 254.84ms 47.28ms
|
|
42
|
+
gzip -d (pako): 4.17(5.79 MiB) 793.62ms 204.64ms
|
|
43
|
+
zstd -4 (node): 4.29(5.62 MiB) 232.69ms 38.53ms
|
|
44
|
+
zstd -3 (Oz,wasm): 4.26(5.65 MiB) 230.65ms 60.13ms
|
|
45
|
+
zstd -3 (O3,wasm): 4.26(5.65 MiB) 155.36ms 29.62ms
|
|
46
|
+
br -3 (node): 4.25(5.67 MiB) 167.06ms 52.79ms
|
|
47
|
+
br -1 (wasm): 3.05(7.91 MiB) 981.26ms 391.41ms
|
|
48
|
+
Done in 11.43s.
|
|
31
49
|
```
|
package/benchmark.js
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import prettyBytes from 'pretty-bytes';
|
|
2
|
+
import wasmFlate from 'wasm-flate';
|
|
3
|
+
import zlib from 'zlib';
|
|
4
|
+
import zstd from '@bokuweb/zstd-wasm';
|
|
5
|
+
import * as myZstd from './dist/zstd/index-browser.js';
|
|
6
|
+
import cppzst from '@xingrz/cppzst';
|
|
7
|
+
import pako from 'pako';
|
|
8
|
+
import brotli from 'brotli-wasm';
|
|
9
|
+
import files from '../../benchmark-files/index.js';
|
|
10
|
+
|
|
11
|
+
const pb = (size) => prettyBytes(size, { binary: true });
|
|
12
|
+
const t = (time) => time.toFixed(2) + 'ms';
|
|
13
|
+
|
|
14
|
+
/* eslint-disable no-console */
|
|
15
|
+
(async function () {
|
|
16
|
+
await zstd.init();
|
|
17
|
+
|
|
18
|
+
function createTest(name, compressor, decompressor) {
|
|
19
|
+
function fn(data) {
|
|
20
|
+
let start = performance.now();
|
|
21
|
+
const compressed = compressor(data);
|
|
22
|
+
const compressTime = performance.now() - start;
|
|
23
|
+
start = performance.now();
|
|
24
|
+
const decompressed = decompressor(compressed);
|
|
25
|
+
const decompressTime = performance.now() - start;
|
|
26
|
+
console.assert(data.equals(decompressed), name, `unmatched`);
|
|
27
|
+
return { compressed, compressTime, decompressTime };
|
|
28
|
+
}
|
|
29
|
+
Object.defineProperty(fn, 'name', { value: name });
|
|
30
|
+
return fn;
|
|
31
|
+
}
|
|
32
|
+
const tests = [
|
|
33
|
+
createTest('gzip -d (wasm)', wasmFlate.gzip_encode_raw, wasmFlate.gzip_decode_raw),
|
|
34
|
+
createTest('gzip -d (node)', zlib.gzipSync, zlib.gunzipSync),
|
|
35
|
+
createTest('gzip -d (pako)', pako.gzip, pako.ungzip),
|
|
36
|
+
createTest('zstd -4 (node)', (buf) => cppzst.compressSync(buf, { level: 4 }), cppzst.decompressSync),
|
|
37
|
+
createTest('zstd -3 (Oz,wasm)', (buf) => zstd.compress(buf, 3), zstd.decompress),
|
|
38
|
+
createTest('zstd -3 (O3,wasm)', (buf) => myZstd.compress(buf, 3), myZstd.decompress),
|
|
39
|
+
createTest(
|
|
40
|
+
'br -3 (node)',
|
|
41
|
+
(buf) =>
|
|
42
|
+
zlib.brotliCompressSync(buf, {
|
|
43
|
+
params: { [zlib.constants.BROTLI_PARAM_QUALITY]: 3 },
|
|
44
|
+
}),
|
|
45
|
+
zlib.brotliDecompressSync,
|
|
46
|
+
),
|
|
47
|
+
createTest('br -1 (wasm)', (buf) => brotli.compress(buf, { quality: 1 }), brotli.decompress),
|
|
48
|
+
];
|
|
49
|
+
for await (const { file, data } of files()) {
|
|
50
|
+
console.log(`File: ${file} \tRaw: ${pb(data.length)}`);
|
|
51
|
+
for (const test of tests) {
|
|
52
|
+
const result = test(data);
|
|
53
|
+
const compressed = result.compressed.length;
|
|
54
|
+
const ratio = (data.length / result.compressed.length).toFixed(2);
|
|
55
|
+
console.log(
|
|
56
|
+
` ${test.name}: \t${ratio}(${pb(compressed)}) \t${t(result.compressTime)} \t${t(
|
|
57
|
+
result.decompressTime,
|
|
58
|
+
)}`,
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
})();
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-browser.js","sourceRoot":"","sources":["../../src/gzip/index-browser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAEpC,SAAS;AACT,MAAM,UAAU,QAAQ,CAAC,IAAgB;IACrC,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC;AACtB,CAAC;AAED,SAAS;AACT,MAAM,UAAU,UAAU,CAAC,IAAgB;IACvC,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC;AACxB,CAAC"}
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/gzip/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAEpC,SAAS;AACT,MAAM,UAAU,QAAQ,CAAC,IAAgB;IACrC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACnC,IAAI,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE;YACvB,IAAI,GAAG,IAAI,CAAC,MAAM;gBAAE,MAAM,CAAC,GAAG,CAAC,CAAC;YAChC,OAAO,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;QAC7E,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;AACP,CAAC;AAED,SAAS;AACT,MAAM,UAAU,UAAU,CAAC,IAAgB;IACvC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACnC,MAAM,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE;YACzB,IAAI,GAAG,IAAI,CAAC,MAAM;gBAAE,MAAM,CAAC,GAAG,CAAC,CAAC;YAChC,OAAO,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;QAC7E,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -11,6 +11,8 @@ export declare function compress(data: Uint8Array, algorithm?: Algorithm): Promi
|
|
|
11
11
|
declare type DecompressResult = Promise<Uint8Array> & {
|
|
12
12
|
algorithm: Algorithm;
|
|
13
13
|
};
|
|
14
|
+
/** 探测压缩算法 */
|
|
15
|
+
export declare function detectCompression(data: Uint8Array): Algorithm;
|
|
14
16
|
/** 探测压缩算法并解压缩 */
|
|
15
17
|
export declare function decompress(data: Uint8Array): DecompressResult;
|
|
16
18
|
export {};
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/** 压缩算法的魔数 */
|
|
2
|
+
export const MAGIC_NUMBERS = {
|
|
3
|
+
zstd: [0x28, 0xb5, 0x2f, 0xfd],
|
|
4
|
+
gzip: [0x1f, 0x8b],
|
|
5
|
+
};
|
|
6
|
+
const modules = {
|
|
7
|
+
zstd: () => import('./zstd/index.js'),
|
|
8
|
+
gzip: () => import('./gzip/index.js'),
|
|
9
|
+
};
|
|
10
|
+
/** 加载相关库 */
|
|
11
|
+
function loadLib(algorithm) {
|
|
12
|
+
if (!(algorithm in modules))
|
|
13
|
+
throw new Error();
|
|
14
|
+
return modules[algorithm]();
|
|
15
|
+
}
|
|
16
|
+
/** 使用指定算法压缩 */
|
|
17
|
+
export async function compress(data, algorithm = 'zstd') {
|
|
18
|
+
if (algorithm === 'none')
|
|
19
|
+
return data;
|
|
20
|
+
const lib = await loadLib(algorithm);
|
|
21
|
+
return await lib.compress(data);
|
|
22
|
+
}
|
|
23
|
+
/** 探测压缩算法 */
|
|
24
|
+
export function detectCompression(data) {
|
|
25
|
+
for (const key in MAGIC_NUMBERS) {
|
|
26
|
+
const k = key;
|
|
27
|
+
const magicNumber = MAGIC_NUMBERS[k];
|
|
28
|
+
if (data.length <= magicNumber.length)
|
|
29
|
+
continue;
|
|
30
|
+
let match = true;
|
|
31
|
+
for (let i = 0; i < magicNumber.length; i++) {
|
|
32
|
+
if (data[i] !== magicNumber[i]) {
|
|
33
|
+
match = false;
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
if (match)
|
|
38
|
+
return k;
|
|
39
|
+
}
|
|
40
|
+
return 'none';
|
|
41
|
+
}
|
|
42
|
+
/** 探测压缩算法并解压缩 */
|
|
43
|
+
export function decompress(data) {
|
|
44
|
+
const algorithm = detectCompression(data);
|
|
45
|
+
if (algorithm === 'none') {
|
|
46
|
+
// 不是压缩数据
|
|
47
|
+
const result = Promise.resolve(data);
|
|
48
|
+
result.algorithm = 'none';
|
|
49
|
+
return result;
|
|
50
|
+
}
|
|
51
|
+
const result = loadLib(algorithm).then(({ decompress }) => decompress(data));
|
|
52
|
+
result.algorithm = algorithm;
|
|
53
|
+
return result;
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,cAAc;AACd,MAAM,CAAC,MAAM,aAAa,GAAG;IACzB,IAAI,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC;IAC9B,IAAI,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC;CACrB,CAAC;AAEF,MAAM,OAAO,GAAG;IACZ,IAAI,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,iBAAiB,CAAC;IACrC,IAAI,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,iBAAiB,CAAC;CACxC,CAAC;AAEF,YAAY;AACZ,SAAS,OAAO,CAAC,SAAoB;IACjC,IAAI,CAAC,CAAC,SAAS,IAAI,OAAO,CAAC;QAAE,MAAM,IAAI,KAAK,EAAE,CAAC;IAC/C,OAAO,OAAO,CAAC,SAAiC,CAAC,EAAE,CAAC;AACxD,CAAC;AAED,eAAe;AACf,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,IAAgB,EAAE,YAAuB,MAAM;IAC1E,IAAI,SAAS,KAAK,MAAM;QAAE,OAAO,IAAI,CAAC;IACtC,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC,CAAC;IACrC,OAAO,MAAM,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AACpC,CAAC;AAKD,aAAa;AACb,MAAM,UAAU,iBAAiB,CAAC,IAAgB;IAC9C,KAAK,MAAM,GAAG,IAAI,aAAa,EAAE;QAC7B,MAAM,CAAC,GAAG,GAAiC,CAAC;QAC5C,MAAM,WAAW,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;QACrC,IAAI,IAAI,CAAC,MAAM,IAAI,WAAW,CAAC,MAAM;YAAE,SAAS;QAChD,IAAI,KAAK,GAAG,IAAI,CAAC;QACjB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;YACzC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,WAAW,CAAC,CAAC,CAAC,EAAE;gBAC5B,KAAK,GAAG,KAAK,CAAC;gBACd,MAAM;aACT;SACJ;QACD,IAAI,KAAK;YAAE,OAAO,CAAC,CAAC;KACvB;IACD,OAAO,MAAM,CAAC;AAClB,CAAC;AAED,iBAAiB;AACjB,MAAM,UAAU,UAAU,CAAC,IAAgB;IACvC,MAAM,SAAS,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;IAE1C,IAAI,SAAS,KAAK,MAAM,EAAE;QACtB,SAAS;QACT,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,CAAqB,CAAC;QACzD,MAAM,CAAC,SAAS,GAAG,MAAM,CAAC;QAC1B,OAAO,MAAM,CAAC;KACjB;IAED,MAAM,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CAAqB,CAAC;IACjG,MAAM,CAAC,SAAS,GAAG,SAAS,CAAC;IAC7B,OAAO,MAAM,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-browser.js","sourceRoot":"","sources":["../../src/zstd/index-browser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC"}
|
|
File without changes
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { compress as c, decompress as d } from '@xingrz/cppzst';
|
|
2
|
+
/** 压缩 */
|
|
3
|
+
export async function compress(data) {
|
|
4
|
+
const buf = Buffer.from(data.buffer, data.byteOffset, data.length);
|
|
5
|
+
const result = await c(buf, { level: 4 });
|
|
6
|
+
return new Uint8Array(result.buffer, result.byteOffset, result.length);
|
|
7
|
+
}
|
|
8
|
+
/** 解压 */
|
|
9
|
+
export async function decompress(data) {
|
|
10
|
+
const buf = Buffer.from(data.buffer, data.byteOffset, data.length);
|
|
11
|
+
const result = await d(buf);
|
|
12
|
+
return new Uint8Array(result.buffer, result.byteOffset, result.length);
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/zstd/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,IAAI,CAAC,EAAE,UAAU,IAAI,CAAC,EAAE,MAAM,gBAAgB,CAAC;AAEhE,SAAS;AACT,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,IAAgB;IAC3C,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IACnE,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;IAC1C,OAAO,IAAI,UAAU,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;AAC3E,CAAC;AAED,SAAS;AACT,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAgB;IAC7C,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IACnE,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC;IAC5B,OAAO,IAAI,UAAU,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;AAC3E,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Module } from './module.js';
|
|
2
|
+
/** 压缩 */
|
|
3
|
+
export function compress(buf, level = 3) {
|
|
4
|
+
const bound = Module._ZSTD_compressBound(buf.byteLength);
|
|
5
|
+
const compressed = Module._malloc(bound);
|
|
6
|
+
const src = Module._malloc(buf.byteLength);
|
|
7
|
+
Module.HEAPU8.set(buf, src);
|
|
8
|
+
try {
|
|
9
|
+
/*
|
|
10
|
+
@See https://zstd.docsforge.com/dev/api/ZSTD_compress/
|
|
11
|
+
size_t ZSTD_compress( void* dst, size_t dstCapacity, const void* src, size_t srcSize, int compressionLevel);
|
|
12
|
+
Compresses `src` content as a single zstd compressed frame into already allocated `dst`.
|
|
13
|
+
Hint : compression runs faster if `dstCapacity` >= `ZSTD_compressBound(srcSize)`.
|
|
14
|
+
@return : compressed size written into `dst` (<= `dstCapacity),
|
|
15
|
+
or an error code if it fails (which can be tested using ZSTD_isError()).
|
|
16
|
+
*/
|
|
17
|
+
const sizeOrError = Module._ZSTD_compress(compressed, bound, src, buf.byteLength, level);
|
|
18
|
+
if (Module._ZSTD_isError(sizeOrError)) {
|
|
19
|
+
throw new Error(`Failed to compress with code ${sizeOrError}`);
|
|
20
|
+
}
|
|
21
|
+
return new Uint8Array(Module.HEAPU8.buffer, compressed, sizeOrError).slice();
|
|
22
|
+
}
|
|
23
|
+
finally {
|
|
24
|
+
Module._free(compressed);
|
|
25
|
+
Module._free(src);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=compress.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compress.js","sourceRoot":"","sources":["../../../src/zstd/wasm/compress.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,SAAS;AACT,MAAM,UAAU,QAAQ,CAAC,GAAe,EAAE,KAAK,GAAG,CAAC;IAC/C,MAAM,KAAK,GAAG,MAAM,CAAC,mBAAmB,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IACzD,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IACzC,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IAC3C,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAC5B,IAAI;QACA;;;;;;;MAOF;QACE,MAAM,WAAW,GAAG,MAAM,CAAC,cAAc,CAAC,UAAU,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;QACzF,IAAI,MAAM,CAAC,aAAa,CAAC,WAAW,CAAC,EAAE;YACnC,MAAM,IAAI,KAAK,CAAC,gCAAgC,WAAW,EAAE,CAAC,CAAC;SAClE;QACD,OAAO,IAAI,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC,KAAK,EAAE,CAAC;KAChF;YAAS;QACN,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QACzB,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;KACrB;AACL,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Module } from './module.js';
|
|
2
|
+
/** 解压 */
|
|
3
|
+
export function decompress(buf, opts = { defaultHeapSize: 1024 * 1024 }) {
|
|
4
|
+
const src = Module._malloc(buf.byteLength);
|
|
5
|
+
Module.HEAP8.set(buf, src);
|
|
6
|
+
const contentSize = Module._ZSTD_getFrameContentSize(src, buf.byteLength);
|
|
7
|
+
const size = contentSize === -1 ? opts.defaultHeapSize ?? 1024 * 1024 : contentSize;
|
|
8
|
+
const heap = Module._malloc(size);
|
|
9
|
+
try {
|
|
10
|
+
/*
|
|
11
|
+
@See https://zstd.docsforge.com/dev/api/ZSTD_decompress/
|
|
12
|
+
compressedSize : must be the exact size of some number of compressed and/or skippable frames.
|
|
13
|
+
dstCapacity is an upper bound of originalSize to regenerate.
|
|
14
|
+
If user cannot imply a maximum upper bound, it's better to use streaming mode to decompress data.
|
|
15
|
+
@return: the number of bytes decompressed into dst (<= dstCapacity), or an errorCode if it fails (which can be tested using ZSTD_isError()).
|
|
16
|
+
*/
|
|
17
|
+
const sizeOrError = Module._ZSTD_decompress(heap, size, src, buf.byteLength);
|
|
18
|
+
if (Module._ZSTD_isError(sizeOrError)) {
|
|
19
|
+
throw new Error(`Failed to compress with code ${sizeOrError}`);
|
|
20
|
+
}
|
|
21
|
+
// Copy buffer
|
|
22
|
+
// Uint8Array.prototype.slice() return copied buffer.
|
|
23
|
+
return new Uint8Array(Module.HEAPU8.buffer, heap, sizeOrError).slice();
|
|
24
|
+
}
|
|
25
|
+
finally {
|
|
26
|
+
Module._free(heap);
|
|
27
|
+
Module._free(src);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=decompress.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decompress.js","sourceRoot":"","sources":["../../../src/zstd/wasm/decompress.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAOrC,SAAS;AACT,MAAM,UAAU,UAAU,CACtB,GAAe,EACf,OAAyB,EAAE,eAAe,EAAE,IAAI,GAAG,IAAI,EAAE;IAEzD,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IAC3C,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAC3B,MAAM,WAAW,GAAG,MAAM,CAAC,yBAAyB,CAAC,GAAG,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC;IAC1E,MAAM,IAAI,GAAG,WAAW,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,IAAI,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC;IACpF,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAClC,IAAI;QACA;;;;;;MAMF;QACE,MAAM,WAAW,GAAG,MAAM,CAAC,gBAAgB,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC;QAC7E,IAAI,MAAM,CAAC,aAAa,CAAC,WAAW,CAAC,EAAE;YACnC,MAAM,IAAI,KAAK,CAAC,gCAAgC,WAAW,EAAE,CAAC,CAAC;SAClE;QACD,cAAc;QACd,qDAAqD;QACrD,OAAO,IAAI,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC,KAAK,EAAE,CAAC;KAC1E;YAAS;QACN,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACnB,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;KACrB;AACL,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"module.js","sourceRoot":"","sources":["../../../src/zstd/wasm/module.ts"],"names":[],"mappings":"AAAA,OAAO,YAAY,MAAM,yBAAyB,CAAC;AAEnD,MAAM,MAAM,GAAG,MAAM,YAAY,EAAE,CAAC;AAEpC,OAAO,EAAE,MAAM,EAAE,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,38 +1,38 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cloudpss/compress",
|
|
3
|
-
"version": "0.3.0-alpha.
|
|
3
|
+
"version": "0.3.0-alpha.22",
|
|
4
4
|
"author": "CloudPSS",
|
|
5
5
|
"license": "MIT",
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
"
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "dist/index.js",
|
|
8
|
+
"module": "dist/index.js",
|
|
9
|
+
"types": "dist/index.d.ts",
|
|
9
10
|
"exports": {
|
|
10
|
-
"types": "./dist/
|
|
11
|
-
"
|
|
12
|
-
"import": "./dist/esm/index.js"
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"default": "./dist/index.js"
|
|
13
13
|
},
|
|
14
14
|
"browser": {
|
|
15
|
-
"./dist/
|
|
16
|
-
"./dist/
|
|
15
|
+
"./dist/gzip/index.js": "./dist/gzip/index-browser.js",
|
|
16
|
+
"./dist/zstd/index.js": "./dist/zstd/index-browser.js"
|
|
17
17
|
},
|
|
18
18
|
"scripts": {
|
|
19
|
-
"postinstall": "pwsh ./update-zstd.ps1",
|
|
20
19
|
"start": "yarn clean && tsc --watch",
|
|
21
|
-
"build": "yarn clean &&
|
|
20
|
+
"build": "yarn clean && tsc",
|
|
22
21
|
"prepublishOnly": "yarn build",
|
|
23
|
-
"build:cjs": "tsc",
|
|
24
|
-
"build:esm": "tsc --outDir dist/esm --module ESNext",
|
|
25
22
|
"clean": "rimraf dist",
|
|
26
23
|
"benchmark": "node ./benchmark"
|
|
27
24
|
},
|
|
28
25
|
"dependencies": {
|
|
26
|
+
"@xingrz/cppzst": "^2.1.0-alpha.6",
|
|
29
27
|
"pako": "^2.0.4"
|
|
30
28
|
},
|
|
31
29
|
"devDependencies": {
|
|
32
30
|
"@bokuweb/zstd-wasm": "^0.0.14",
|
|
33
31
|
"@types/node": "^16.11.6",
|
|
34
32
|
"@types/pako": "^1.0.2",
|
|
33
|
+
"brotli-wasm": "^1.1.0",
|
|
35
34
|
"pretty-bytes": "^5.6.0",
|
|
35
|
+
"type-fest": "^2.5.2",
|
|
36
36
|
"wasm-flate": "1.0.2"
|
|
37
37
|
}
|
|
38
38
|
}
|
package/src/index.ts
CHANGED
|
@@ -8,39 +8,56 @@ export const MAGIC_NUMBERS = {
|
|
|
8
8
|
};
|
|
9
9
|
|
|
10
10
|
const modules = {
|
|
11
|
-
zstd: () => import('./zstd'),
|
|
12
|
-
gzip: () => import('./gzip'),
|
|
11
|
+
zstd: () => import('./zstd/index.js'),
|
|
12
|
+
gzip: () => import('./gzip/index.js'),
|
|
13
13
|
};
|
|
14
14
|
|
|
15
|
+
/** 加载相关库 */
|
|
16
|
+
function loadLib(algorithm: Algorithm): ReturnType<typeof modules[keyof typeof modules]> {
|
|
17
|
+
if (!(algorithm in modules)) throw new Error();
|
|
18
|
+
return modules[algorithm as keyof typeof modules]();
|
|
19
|
+
}
|
|
20
|
+
|
|
15
21
|
/** 使用指定算法压缩 */
|
|
16
22
|
export async function compress(data: Uint8Array, algorithm: Algorithm = 'zstd'): Promise<Uint8Array> {
|
|
17
23
|
if (algorithm === 'none') return data;
|
|
18
|
-
const lib = await
|
|
24
|
+
const lib = await loadLib(algorithm);
|
|
19
25
|
return await lib.compress(data);
|
|
20
26
|
}
|
|
21
27
|
|
|
22
28
|
/** 解压缩结果 */
|
|
23
29
|
type DecompressResult = Promise<Uint8Array> & { algorithm: Algorithm };
|
|
24
30
|
|
|
25
|
-
/**
|
|
26
|
-
export function
|
|
27
|
-
let result: DecompressResult | undefined;
|
|
31
|
+
/** 探测压缩算法 */
|
|
32
|
+
export function detectCompression(data: Uint8Array): Algorithm {
|
|
28
33
|
for (const key in MAGIC_NUMBERS) {
|
|
29
34
|
const k = key as keyof typeof MAGIC_NUMBERS;
|
|
30
35
|
const magicNumber = MAGIC_NUMBERS[k];
|
|
31
36
|
if (data.length <= magicNumber.length) continue;
|
|
37
|
+
let match = true;
|
|
32
38
|
for (let i = 0; i < magicNumber.length; i++) {
|
|
33
|
-
if (data[i] !== magicNumber[i])
|
|
39
|
+
if (data[i] !== magicNumber[i]) {
|
|
40
|
+
match = false;
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
34
43
|
}
|
|
35
|
-
|
|
36
|
-
result = modules[k]().then(({ decompress }) => decompress(data)) as DecompressResult;
|
|
37
|
-
result.algorithm = k;
|
|
38
|
-
break;
|
|
44
|
+
if (match) return k;
|
|
39
45
|
}
|
|
40
|
-
|
|
46
|
+
return 'none';
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** 探测压缩算法并解压缩 */
|
|
50
|
+
export function decompress(data: Uint8Array): DecompressResult {
|
|
51
|
+
const algorithm = detectCompression(data);
|
|
52
|
+
|
|
53
|
+
if (algorithm === 'none') {
|
|
41
54
|
// 不是压缩数据
|
|
42
|
-
result = Promise.resolve(data) as DecompressResult;
|
|
55
|
+
const result = Promise.resolve(data) as DecompressResult;
|
|
43
56
|
result.algorithm = 'none';
|
|
57
|
+
return result;
|
|
44
58
|
}
|
|
59
|
+
|
|
60
|
+
const result = loadLib(algorithm).then(({ decompress }) => decompress(data)) as DecompressResult;
|
|
61
|
+
result.algorithm = algorithm;
|
|
45
62
|
return result;
|
|
46
63
|
}
|
package/src/zstd/index.ts
CHANGED
|
@@ -1,26 +1,15 @@
|
|
|
1
|
-
import { decompress as d } from '
|
|
2
|
-
import { compress as c } from './lib/simple/compress';
|
|
3
|
-
import { Module, waitInitialized } from './lib/module';
|
|
4
|
-
import { data } from './lib/wasm/zstd.wasm.js';
|
|
5
|
-
|
|
6
|
-
let wasm;
|
|
7
|
-
if (typeof Buffer !== 'undefined') {
|
|
8
|
-
wasm = Buffer.from(data, 'base64');
|
|
9
|
-
} else {
|
|
10
|
-
wasm = 'data:application/wasm;base64,' + data;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
(Module as { init: (wasm: string | Uint8Array) => void }).init(wasm);
|
|
14
|
-
const init = waitInitialized();
|
|
1
|
+
import { compress as c, decompress as d } from '@xingrz/cppzst';
|
|
15
2
|
|
|
16
3
|
/** 压缩 */
|
|
17
4
|
export async function compress(data: Uint8Array): Promise<Uint8Array> {
|
|
18
|
-
|
|
19
|
-
|
|
5
|
+
const buf = Buffer.from(data.buffer, data.byteOffset, data.length);
|
|
6
|
+
const result = await c(buf, { level: 4 });
|
|
7
|
+
return new Uint8Array(result.buffer, result.byteOffset, result.length);
|
|
20
8
|
}
|
|
21
9
|
|
|
22
10
|
/** 解压 */
|
|
23
11
|
export async function decompress(data: Uint8Array): Promise<Uint8Array> {
|
|
24
|
-
|
|
25
|
-
|
|
12
|
+
const buf = Buffer.from(data.buffer, data.byteOffset, data.length);
|
|
13
|
+
const result = await d(buf);
|
|
14
|
+
return new Uint8Array(result.buffer, result.byteOffset, result.length);
|
|
26
15
|
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Module } from './module.js';
|
|
2
|
+
|
|
3
|
+
/** 压缩 */
|
|
4
|
+
export function compress(buf: Uint8Array, level = 3): Uint8Array {
|
|
5
|
+
const bound = Module._ZSTD_compressBound(buf.byteLength);
|
|
6
|
+
const compressed = Module._malloc(bound);
|
|
7
|
+
const src = Module._malloc(buf.byteLength);
|
|
8
|
+
Module.HEAPU8.set(buf, src);
|
|
9
|
+
try {
|
|
10
|
+
/*
|
|
11
|
+
@See https://zstd.docsforge.com/dev/api/ZSTD_compress/
|
|
12
|
+
size_t ZSTD_compress( void* dst, size_t dstCapacity, const void* src, size_t srcSize, int compressionLevel);
|
|
13
|
+
Compresses `src` content as a single zstd compressed frame into already allocated `dst`.
|
|
14
|
+
Hint : compression runs faster if `dstCapacity` >= `ZSTD_compressBound(srcSize)`.
|
|
15
|
+
@return : compressed size written into `dst` (<= `dstCapacity),
|
|
16
|
+
or an error code if it fails (which can be tested using ZSTD_isError()).
|
|
17
|
+
*/
|
|
18
|
+
const sizeOrError = Module._ZSTD_compress(compressed, bound, src, buf.byteLength, level);
|
|
19
|
+
if (Module._ZSTD_isError(sizeOrError)) {
|
|
20
|
+
throw new Error(`Failed to compress with code ${sizeOrError}`);
|
|
21
|
+
}
|
|
22
|
+
return new Uint8Array(Module.HEAPU8.buffer, compressed, sizeOrError).slice();
|
|
23
|
+
} finally {
|
|
24
|
+
Module._free(compressed);
|
|
25
|
+
Module._free(src);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Module } from './module.js';
|
|
2
|
+
|
|
3
|
+
/** DecompressOption */
|
|
4
|
+
export type DecompressOption = {
|
|
5
|
+
defaultHeapSize: number;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
/** 解压 */
|
|
9
|
+
export function decompress(
|
|
10
|
+
buf: Uint8Array,
|
|
11
|
+
opts: DecompressOption = { defaultHeapSize: 1024 * 1024 }, // Use 1MB on default if it is failed to get content size.
|
|
12
|
+
): Uint8Array {
|
|
13
|
+
const src = Module._malloc(buf.byteLength);
|
|
14
|
+
Module.HEAP8.set(buf, src);
|
|
15
|
+
const contentSize = Module._ZSTD_getFrameContentSize(src, buf.byteLength);
|
|
16
|
+
const size = contentSize === -1 ? opts.defaultHeapSize ?? 1024 * 1024 : contentSize;
|
|
17
|
+
const heap = Module._malloc(size);
|
|
18
|
+
try {
|
|
19
|
+
/*
|
|
20
|
+
@See https://zstd.docsforge.com/dev/api/ZSTD_decompress/
|
|
21
|
+
compressedSize : must be the exact size of some number of compressed and/or skippable frames.
|
|
22
|
+
dstCapacity is an upper bound of originalSize to regenerate.
|
|
23
|
+
If user cannot imply a maximum upper bound, it's better to use streaming mode to decompress data.
|
|
24
|
+
@return: the number of bytes decompressed into dst (<= dstCapacity), or an errorCode if it fails (which can be tested using ZSTD_isError()).
|
|
25
|
+
*/
|
|
26
|
+
const sizeOrError = Module._ZSTD_decompress(heap, size, src, buf.byteLength);
|
|
27
|
+
if (Module._ZSTD_isError(sizeOrError)) {
|
|
28
|
+
throw new Error(`Failed to compress with code ${sizeOrError}`);
|
|
29
|
+
}
|
|
30
|
+
// Copy buffer
|
|
31
|
+
// Uint8Array.prototype.slice() return copied buffer.
|
|
32
|
+
return new Uint8Array(Module.HEAPU8.buffer, heap, sizeOrError).slice();
|
|
33
|
+
} finally {
|
|
34
|
+
Module._free(heap);
|
|
35
|
+
Module._free(src);
|
|
36
|
+
}
|
|
37
|
+
}
|
package/tsconfig.json
CHANGED
package/wasm/zstd.g.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/* eslint-disable jsdoc/require-jsdoc */
|
|
2
|
+
import { Opaque } from 'type-fest';
|
|
3
|
+
type Ptr = Opaque<number, 'void*'>;
|
|
4
|
+
type Module = {
|
|
5
|
+
readonly HEAP8: Int8Array;
|
|
6
|
+
readonly HEAPU8: Uint8Array;
|
|
7
|
+
|
|
8
|
+
_ZSTD_isError(code: number): number;
|
|
9
|
+
_ZSTD_compressBound(size: number): number;
|
|
10
|
+
_ZSTD_compress(outPtr: number, outSize: number, inPtr: number, inSize: number, level: number): number;
|
|
11
|
+
_ZSTD_getFrameContentSize(src: number, size: number): number;
|
|
12
|
+
_ZSTD_decompress(outPtr: number, outSize: number, inPtr: number, inSize: number): number;
|
|
13
|
+
_malloc(size: number): Ptr;
|
|
14
|
+
_free(ptr: Ptr): void;
|
|
15
|
+
};
|
|
16
|
+
export default function createModule(): Promise<Module>;
|