Fast RAR archive streaming for Rust, Node.js, and browsers. Zero dependencies core.
- Installation
- Quick Start
- Examples
- API
- Feature Flags
- Format Support
- Performance
- Migrating from v3.x
- Architecture
- Contributing
- Security
- Changelog
- License
npm install rar-streamNative binaries are automatically downloaded from GitHub Releases during install. Supported platforms: Linux (x64, arm64), macOS (x64, arm64), Windows (x64).
[dependencies]
rar-stream = { version = "5", features = ["async", "crypto"] }wasm-pack build --target web --features "wasm,crypto" --no-default-featuresimport { LocalFileMedia, RarFilesPackage } from 'rar-stream';
const media = new LocalFileMedia('./archive.rar');
const pkg = new RarFilesPackage([media]);
const files = await pkg.parse();
for (const file of files) {
console.log(`${file.name}: ${file.length} bytes`);
const buffer = await file.readToEnd();
// or stream: file.createReadStream().pipe(process.stdout);
}Runnable examples in examples/:
| Example | Run | Description |
|---|---|---|
| basic.ts | npx tsx examples/basic.ts <path> |
Parse RAR, list files, read content |
| http-stream.ts | npx tsx examples/http-stream.ts <rar> |
HTTP video server with range requests |
| extract.rs | cargo run --release --example extract --features async -- archive.rar out/ |
Extract files to disk |
| browser.html | Open in browser (after npm run build:wasm) |
WASM decompression demo |
| profile.rs | cargo run --release --example profile |
Benchmark decompression loop |
| benchmark_sizes.rs | cargo run --release --example benchmark_sizes |
Benchmark across file sizes |
| Class | Description |
|---|---|
LocalFileMedia(path) |
Wraps a local file for reading |
RarFilesPackage(files) |
Parses single or multi-volume RAR archives |
InnerFile |
A file inside the archive |
class InnerFile {
readonly name: string; // Full path inside archive
readonly length: number; // Uncompressed size in bytes
readToEnd(): Promise<Buffer>;
createReadStream(opts?: { start?: number; end?: number }): Readable;
}Custom data sources (WebTorrent, S3, HTTP) must implement:
interface FileMedia {
readonly name: string;
readonly length: number;
createReadStream(opts: { start: number; end: number }): Readable;
}| Function | Description |
|---|---|
isRarArchive(buffer) |
Check if buffer starts with RAR signature |
parseRarHeader(buffer) |
Parse RAR4 header from buffer (~300 bytes) |
streamToBuffer(stream) |
Convert Readable to Buffer |
createFileMedia(source) |
Wrap any { createReadStream } as FileMedia |
| Feature | Default | Description |
|---|---|---|
async |
No | Async archive reading via tokio (RarFilesPackage, InnerFile) |
crypto |
No | AES encryption (RAR4: AES-128, RAR5: AES-256) |
parallel |
No | Multi-threaded RAR5 decompression (rayon) |
napi |
No | Node.js bindings (implies async + parallel) |
wasm |
No | Browser WASM bindings |
| Capability | Rust | Node.js (NAPI) | Browser (WASM) |
|---|---|---|---|
| Parse RAR4/RAR5 | ✅ | ✅ | ✅ |
| Decompress | ✅ | ✅ | ✅ |
| Encryption | ✅ (crypto) |
✅ (always on) | ✅ (crypto) |
| Async I/O | ✅ (async) |
✅ | — |
| Parallel decompress | ✅ (parallel) |
✅ (always on) | — |
| Multi-volume | ✅ | ✅ | ✅ |
| Streaming reads | ✅ | ✅ | — |
| Feature | RAR4 | RAR5 |
|---|---|---|
| Stored (no compression) | Yes | Yes |
| LZSS (Huffman + LZ77) | Yes | Yes |
| PPMd | Yes | -- |
| E8/E8E9 filters (x86) | Yes | Yes |
| Delta filter | Yes | Yes |
| ARM filter | -- | Yes |
| Itanium/RGB/Audio filters | Yes | -- |
| Encrypted files (AES) | Yes | Yes |
| Encrypted headers | -- | Yes |
| Multi-volume | Yes | Yes |
Encryption requires the crypto feature (always enabled in npm builds).
Benchmarked against the official C unrar (v7.0) using cargo bench.
Core decompression (3 KB files, single-threaded):
| Method | rar-stream | unrar | Speedup |
|---|---|---|---|
| LZSS | 8 µs | 92 µs | 11x |
| PPMd | 107 µs | 177 µs | 1.7x |
| Stored | 54 ns | 123 µs | 2170x |
Single-threaded decompression vs unrar across data types (200 MB, method 5, 128 MB dict):
| Data type | rar-stream | unrar | Ratio |
|---|---|---|---|
| Text | 631 MiB/s | 535 MiB/s | 1.18x faster |
| Binary | 424 MiB/s | 439 MiB/s | 0.97x |
| ISO (x86) | 297 MiB/s | 440 MiB/s | 0.67x |
With the parallel feature (enabled by default in npm), rar-stream's pipeline beats unrar across all 24 benchmark scenarios. Best case: 1.9x faster.
| Archive | Size | Pipeline | unrar | Ratio |
|---|---|---|---|---|
| Binary (ISO) | 200 MB | 289ms | 420ms | 0.69x |
| Text | 200 MB | 119ms | 197ms | 0.61x |
| Mixed | 200 MB | 307ms | 524ms | 0.59x |
| Binary | 500 MB | 683ms | 1088ms | 0.63x |
| Text | 500 MB | 357ms | 590ms | 0.61x |
| Mixed | 1 GB | 1671ms | 2407ms | 0.69x |
Full benchmark matrix (24 scenarios)
Archive Single Pipeline Unrar Pipe/Unrar
----------------------------------------------------------------
bin-500_m3_32m 1187ms 736ms 1122ms 0.66x
bin-500_m5_128m 1122ms 683ms 1088ms 0.63x
bin-500_m5_32m 1183ms 711ms 1119ms 0.64x
bin-500_m5_4m 1311ms 765ms 1206ms 0.63x
iso-200_m3_32m 693ms 289ms 420ms 0.69x
iso-200_m5_128m 694ms 296ms 455ms 0.65x
iso-200_m5_32m 697ms 290ms 418ms 0.69x
iso-200_m5_4m 694ms 293ms 426ms 0.69x
mixed-1g_m3_32m 2690ms 1818ms 2603ms 0.70x
mixed-1g_m5_128m 2909ms 1916ms 2852ms 0.67x
mixed-1g_m5_32m 2699ms 1794ms 2598ms 0.69x
mixed-1g_m5_4m 2611ms 1671ms 2407ms 0.69x
mixed-200_m3_32m 465ms 344ms 537ms 0.64x
mixed-200_m5_128m 413ms 307ms 524ms 0.59x
mixed-200_m5_32m 463ms 338ms 527ms 0.64x
mixed-200_m5_4m 487ms 350ms 531ms 0.66x
text-200_m3_32m 199ms 120ms 200ms 0.60x
text-200_m5_128m 196ms 119ms 230ms 0.52x
text-200_m5_32m 197ms 120ms 197ms 0.61x
text-200_m5_4m 218ms 127ms 199ms 0.64x
text-500_m3_32m 583ms 362ms 591ms 0.61x
text-500_m5_128m 572ms 365ms 628ms 0.58x
text-500_m5_32m 567ms 357ms 590ms 0.61x
text-500_m5_4m 623ms 382ms 620ms 0.62x
Ratio < 1.0 = rar-stream is faster.
Drop-in replacement. Same API, native Rust implementation. Requires Node.js 18+.
See CONTRIBUTING.md for development setup, conventions, and the PR process.
MIT