@crossbind/port-zstd 2.0.0-beta.60 → 2.0.0-beta.63
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 +94 -11
- package/mergeConfig.mjs +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -2,22 +2,31 @@
|
|
|
2
2
|
**Precompiled Zstandard (zstd) library built with crossbind for seamless integration in JavaScript, WebAssembly and React Native projects.**
|
|
3
3
|
|
|
4
4
|
<a href="https://www.npmjs.com/package/@crossbind/port-zstd">
|
|
5
|
-
<img alt="NPM version" src="https://img.shields.io/npm/v/@crossbind/port-zstd?style=for-the-badge" />
|
|
5
|
+
<img alt="NPM version" src="https://img.shields.io/npm/v/@crossbind/port-zstd/beta?style=for-the-badge" />
|
|
6
6
|
</a>
|
|
7
7
|
<a href="https://github.com/facebook/zstd">
|
|
8
|
-
<img src="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%
|
|
8
|
+
<img src="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fregistry.npmjs.org%2F%40crossbind%2Fport-zstd%2Fbeta&query=%24.nativeVersion&style=for-the-badge&label=ZSTD" />
|
|
9
9
|
</a>
|
|
10
10
|
<a href="https://github.com/facebook/zstd/blob/dev/LICENSE">
|
|
11
|
-
<img alt="License" src="https://img.shields.io/
|
|
11
|
+
<img alt="License" src="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fregistry.npmjs.org%2F%40crossbind%2Fport-zstd%2Fbeta&query=%24.license&style=for-the-badge&label=license" />
|
|
12
12
|
</a>
|
|
13
13
|
|
|
14
14
|
> Use it together with **[crossbind](https://crossbind.dev)** — the toolchain for using C++ libraries from JavaScript, TypeScript, WebAssembly, Node.js and React Native. Learn more at **[crossbind.dev](https://crossbind.dev)**.
|
|
15
15
|
|
|
16
|
+
## See it run
|
|
17
|
+
Three apps on **[crossbind.dev/ports/zstd](https://crossbind.dev/ports/zstd/#apps)** run this package in your browser, on the same generated data every time:
|
|
18
|
+
|
|
19
|
+
- **Dictionary trainer.** Trains a 4 KB dictionary on 1,000 JSON records in the tab. The next 1,000 records, compressed one by one, shrink 7.55× with it against 1.82× without.
|
|
20
|
+
- **Ship only the diff.** A 1,081,692-byte dataset update, compressed with the previous version as its dictionary, becomes a 1,022-byte [RFC 9842](https://www.rfc-editor.org/rfc/rfc9842.html) `dcz` stream.
|
|
21
|
+
- **.tar.zst opener.** Streams a `.tar.zst` in 128 KB steps and lists what is inside without unpacking it.
|
|
22
|
+
|
|
23
|
+
Their C++ wrappers, and the self-check the site build runs against numbers computed independently of this package, are in [`landing/demos/lib-zstd`](https://github.com/crossbind/crossbind/tree/main/landing/demos/lib-zstd).
|
|
24
|
+
|
|
16
25
|
## Integration
|
|
17
26
|
Install the main package together with the platform builds:
|
|
18
27
|
|
|
19
28
|
```sh
|
|
20
|
-
npm install @crossbind/port-zstd @crossbind/port-zstd-wasm @crossbind/port-zstd-android @crossbind/port-zstd-ios
|
|
29
|
+
npm install @crossbind/port-zstd@beta @crossbind/port-zstd-wasm@beta @crossbind/port-zstd-android@beta @crossbind/port-zstd-ios@beta
|
|
21
30
|
```
|
|
22
31
|
|
|
23
32
|
Then import all three platforms in `crossbind.config.js` — crossbind compiles only the one matching each build target:
|
|
@@ -39,18 +48,85 @@ export default {
|
|
|
39
48
|
};
|
|
40
49
|
```
|
|
41
50
|
|
|
51
|
+
A native Node.js addon (`crossbind build -e node`) links the build of its platform: `-p darwin`, `-p linux`, `-p linuxmusl` or `-p win32` takes `@crossbind/port-zstd-darwin`, `-linux`, `-linuxmusl` or `-win32`; `-linuxmusl` is the one for Alpine and other musl distributions. Install it and import its `crossbind.config.js` the same way.
|
|
52
|
+
|
|
42
53
|
## Usage
|
|
43
|
-
|
|
54
|
+
crossbind binds your C++ headers to JavaScript, so the usual pattern is a small wrapper around the library. This one compresses and decompresses in one call. Put it in your project's native folder (`src/native/` by default):
|
|
44
55
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
56
|
+
```cpp
|
|
57
|
+
// src/native/zstd_codec.h
|
|
58
|
+
#pragma once
|
|
59
|
+
|
|
60
|
+
#include <zstd.h>
|
|
48
61
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
62
|
+
#include <stdexcept>
|
|
63
|
+
#include <string>
|
|
64
|
+
|
|
65
|
+
// One-shot Zstandard. Bytes cross the binding as a byte string: one UTF-16 code unit (0-255) per byte.
|
|
66
|
+
class Zstd {
|
|
67
|
+
public:
|
|
68
|
+
static std::string version() { return ZSTD_versionString(); }
|
|
69
|
+
|
|
70
|
+
static std::u16string compress(const std::string& text, int level) {
|
|
71
|
+
std::string out(ZSTD_compressBound(text.size()), '\0');
|
|
72
|
+
const size_t size = ZSTD_compress(&out[0], out.size(), text.data(), text.size(), level);
|
|
73
|
+
if (ZSTD_isError(size)) throw std::runtime_error(ZSTD_getErrorName(size));
|
|
74
|
+
std::u16string bytes(size, u'\0');
|
|
75
|
+
for (size_t i = 0; i < size; ++i) bytes[i] = static_cast<unsigned char>(out[i]);
|
|
76
|
+
return bytes;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
static std::string decompress(const std::u16string& bytes) {
|
|
80
|
+
std::string in(bytes.size(), '\0');
|
|
81
|
+
for (size_t i = 0; i < bytes.size(); ++i) {
|
|
82
|
+
if (bytes[i] > 0xFF) throw std::invalid_argument("not a byte string");
|
|
83
|
+
in[i] = static_cast<char>(bytes[i]);
|
|
84
|
+
}
|
|
85
|
+
const unsigned long long size = ZSTD_getFrameContentSize(in.data(), in.size());
|
|
86
|
+
if (size == ZSTD_CONTENTSIZE_ERROR) throw std::runtime_error("not a zstd frame");
|
|
87
|
+
if (size == ZSTD_CONTENTSIZE_UNKNOWN) throw std::runtime_error("size not stored in the frame; use streaming");
|
|
88
|
+
if (size > (256u << 20)) throw std::runtime_error("refusing to allocate more than 256 MiB");
|
|
89
|
+
std::string out(static_cast<size_t>(size), '\0');
|
|
90
|
+
const size_t got = ZSTD_decompress(&out[0], out.size(), in.data(), in.size());
|
|
91
|
+
if (ZSTD_isError(got)) throw std::runtime_error(ZSTD_getErrorName(got));
|
|
92
|
+
out.resize(got);
|
|
93
|
+
return out;
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Then call it from JavaScript:
|
|
99
|
+
|
|
100
|
+
```js
|
|
101
|
+
import { initNative, Zstd } from './native/zstd_codec.h';
|
|
102
|
+
|
|
103
|
+
await initNative();
|
|
104
|
+
const text = 'crossbind '.repeat(100);
|
|
105
|
+
const frame = await Zstd.compress(text, 19);
|
|
106
|
+
const bytes = Uint8Array.from(frame, (c) => c.charCodeAt(0));
|
|
107
|
+
console.log(await Zstd.version(), bytes.length, [...bytes.slice(0, 4)].map((b) => b.toString(16)).join(' ')); // 1.5.7 27 28 b5 2f fd
|
|
108
|
+
console.log((await Zstd.decompress(frame)) === text); // true
|
|
52
109
|
```
|
|
53
110
|
|
|
111
|
+
- Binary data crosses the binding as a string with one UTF-16 code unit (0-255) per byte, which is why `compress` returns `std::u16string`. `Uint8Array.from(frame, (c) => c.charCodeAt(0))` turns it into bytes.
|
|
112
|
+
- `decompress` reads the size from the frame and refuses anything above 256 MiB, which guards against decompression bombs. Frames written without a content size need the streaming API (`ZSTD_decompressStream`).
|
|
113
|
+
- For files, pass paths instead of bytes: mount the file into the module's filesystem (`autoMountFiles`) and read it in C++ with `fopen`. The `.tar.zst` opener above works that way.
|
|
114
|
+
|
|
115
|
+
### More examples
|
|
116
|
+
Each one runs in your browser on [crossbind.dev/ports/zstd](https://crossbind.dev/ports/zstd/#usage), next to the code shown there:
|
|
117
|
+
|
|
118
|
+
- [Stream a file through zstd](https://crossbind.dev/ports/zstd/#02-stream): `ZSTD_compressStream2` and `ZSTD_decompressStream`, file to file in 128 KB steps.
|
|
119
|
+
- [Choose a level, a checksum and a window](https://crossbind.dev/ports/zstd/#03-parameters): `ZSTD_CCtx_setParameter`, read back with `ZSTD_getFrameHeader`.
|
|
120
|
+
- [Compress small messages with a dictionary](https://crossbind.dev/ports/zstd/#04-dictionary): train with `ZDICT_trainFromBuffer`, then compress against `ZSTD_createCDict` and `ZSTD_createDDict`.
|
|
121
|
+
|
|
122
|
+
Setup and differences per platform: [WebAssembly](https://crossbind.dev/ports/zstd/wasm/) · [Android](https://crossbind.dev/ports/zstd/android/) · [iOS](https://crossbind.dev/ports/zstd/ios/) · [macOS](https://crossbind.dev/ports/zstd/darwin/) · [Linux](https://crossbind.dev/ports/zstd/linux/) · [Windows](https://crossbind.dev/ports/zstd/win32/) · [WASI](https://crossbind.dev/ports/zstd/wasi/), which also has a command-line program built with `crossbind build -p wasi -e wasi`.
|
|
123
|
+
|
|
124
|
+
## What this build includes
|
|
125
|
+
- zstd 1.5.7 as a static library, with the dictionary builder (`ZDICT_*`) compiled in.
|
|
126
|
+
- No multithreaded compression: setting `ZSTD_c_nbWorkers` above 0 returns `Unsupported parameter`.
|
|
127
|
+
- No legacy formats: frames written by zstd before v0.8 are rejected.
|
|
128
|
+
- On `wasm32` the largest window is 1 GiB (`windowLog` 30), which covers `zstd --long=30` frames.
|
|
129
|
+
|
|
54
130
|
## Supported platforms
|
|
55
131
|
This is the main package; the precompiled binaries are shipped per platform:
|
|
56
132
|
|
|
@@ -59,6 +135,13 @@ This is the main package; the precompiled binaries are shipped per platform:
|
|
|
59
135
|
| WebAssembly | [`@crossbind/port-zstd-wasm`](https://www.npmjs.com/package/@crossbind/port-zstd-wasm) | `wasm32` — single-threaded & multi-threaded |
|
|
60
136
|
| Android | [`@crossbind/port-zstd-android`](https://www.npmjs.com/package/@crossbind/port-zstd-android) | `arm64-v8a` (64-bit ARM), `x86_64` (emulator) |
|
|
61
137
|
| iOS | [`@crossbind/port-zstd-ios`](https://www.npmjs.com/package/@crossbind/port-zstd-ios) | device (`arm64`), simulator (`arm64`) |
|
|
138
|
+
| macOS | [`@crossbind/port-zstd-darwin`](https://www.npmjs.com/package/@crossbind/port-zstd-darwin) | `arm64` (Apple silicon), `x64` (Intel) — native Node.js addons |
|
|
139
|
+
| Linux | [`@crossbind/port-zstd-linux`](https://www.npmjs.com/package/@crossbind/port-zstd-linux) | `x64`, `arm64` — glibc 2.28 or later, native Node.js addons |
|
|
140
|
+
| Linux (musl) | [`@crossbind/port-zstd-linuxmusl`](https://www.npmjs.com/package/@crossbind/port-zstd-linuxmusl) | `x64`, `arm64` — musl 1.2.5 or later (Alpine 3.21 and later), native Node.js addons |
|
|
141
|
+
| Windows | [`@crossbind/port-zstd-win32`](https://www.npmjs.com/package/@crossbind/port-zstd-win32) | `x64`, `arm64` — Windows 10 or later, native Node.js addons |
|
|
142
|
+
| WASI library | [`@crossbind/port-zstd-wasi`](https://www.npmjs.com/package/@crossbind/port-zstd-wasi) | `wasm32-wasip3` — single-threaded |
|
|
143
|
+
| WASI command | [`@crossbind/port-zstd-standalone-wasi`](https://www.npmjs.com/package/@crossbind/port-zstd-standalone-wasi) | the upstream `zstd` CLI as a `zstd-wasi` command (wasmtime 47+) |
|
|
144
|
+
| Node.js, ready-made | [`@crossbind/port-zstd-standalone-napi`](https://www.npmjs.com/package/@crossbind/port-zstd-standalone-napi) | prebuilt addons for macOS, Linux (glibc and musl) and Windows, `arm64` and `x64`: nothing to build |
|
|
62
145
|
|
|
63
146
|
## License
|
|
64
147
|
This project includes the precompiled zstd library, which is distributed under the [zstd License](https://github.com/facebook/zstd/blob/dev/LICENSE).
|
package/mergeConfig.mjs
CHANGED
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crossbind/port-zstd",
|
|
3
|
-
"version": "2.0.0-beta.
|
|
3
|
+
"version": "2.0.0-beta.63",
|
|
4
4
|
"nativeVersion": "1.5.7",
|
|
5
5
|
"description": "This package provides a libzstd library compiled with crossbind, enabling seamless usage of Zstandard (de)compression functionalities in JavaScript, WebAssembly and React Native projects.",
|
|
6
|
-
"homepage": "https://
|
|
6
|
+
"homepage": "https://crossbind.dev/ports/zstd/",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
9
9
|
"url": "https://github.com/crossbind/crossbind.git"
|