bzip3-rs
Pure-Rust port of the bzip3 compressor.
- No C code. No FFI. No
unsafecode (#![forbid(unsafe_code)]). - Output is compatible with C bzip3 in both directions.
- Blocks run in parallel with rayon.
- Each block carries a CRC32 check.
- The crate has a library API and a
bzip3command-line tool.
Each block passes through four stages: run-length coding, LZP, a Burrows-Wheeler transform (suffix array), and an order-0 context-mixing coder.
Install
Add the library to a project:
The library name in Rust code is bzip3_rs.
Install the command-line tool:
Debian and Ubuntu
Download the .deb file for your architecture (amd64 or arm64) from the release page.
Then install it:
The package replaces the C bzip3 package. It supports Debian 12 and later, and Ubuntu 22.04 and later.
Library usage
Each example below is a complete program.
One call
use ;
Parallel blocks
Jobs::SERIAL runs on the calling thread. Jobs::Global uses the global rayon pool. Jobs::from_count(4) builds a private pool. Output bytes are the same for every job count.
use ;
Streams
Module stream reads from a Read value and writes to a Write value. It uses the 9-byte streaming frame.
use Cursor;
use ;
Read and Write adapters
use ;
use BlockSize;
use ;
use ;
write::Encoder also writes the last block when you drop it. A drop ignores errors, so call finish.
Block by block
Use BlockEncoder and BlockDecoder to build the streaming frame yourself.
use ;
BlockDecoder::recover_block_into decodes a damaged block. It always appends the original number of bytes. A checksum fault keeps the decoded bytes. Any other fault appends zero bytes. The call returns a BlockStatus value that tells which case happened.
Helpers
use ;
Block size
| Item | Value |
|---|---|
BlockSize::MIN |
65 KiB |
BlockSize::DEFAULT |
16 MiB |
BlockSize::MAX |
511 MiB |
BlockSize::from_level maps levels 1 to 14 to these sizes:
| Level | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|---|---|---|---|---|---|---|---|
| Size | 65 KiB | 128 KiB | 256 KiB | 512 KiB | 1 MiB | 2 MiB | 4 MiB |
| Level | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
|---|---|---|---|---|---|---|---|
| Size | 8 MiB | 16 MiB | 32 MiB | 64 MiB | 128 MiB | 256 MiB | 511 MiB |
Full API documentation: https://docs.rs/bzip3-rs.
Command-line tool
Build the tool with the cli feature. The cargo install command above does this.
To run from a checkout without install:
Modes
The last mode flag wins.
| Flag | Action |
|---|---|
-e, -z, --encode |
Compress data (default). |
-d, --decode |
Decompress data. |
-t, --test |
Check data. Write no output. |
-r, --recover |
Decompress damaged data. Write zeros for bad blocks. |
-h, --help |
Show help. |
-V, --version |
Show the version. |
Flags
| Flag | Action |
|---|---|
-c, --stdout |
Write to standard output. |
-f, --force |
Overwrite existing output. |
-k, --keep |
Keep input files. |
-v, --verbose |
Show byte counts. |
-q, --quiet |
Hide non-essential warnings. |
-b N, --block=N |
Set the block size. N is in MiB, or use NK / NKiB for KiB. Range: 65 KiB to 511 MiB. Default: 16 MiB. |
-j N, --jobs=N |
Set the thread count, 0 to 64. Default: 0 (all cores). |
-1 to -14 |
Set the block size by level. See the level table above. |
--fast |
Same as -1. |
--best |
Same as -14. |
File rules
- Encode adds the suffix
.bz3. - Decode removes the suffix
.bz3. If the name has no suffix, decode writes<name>.out. - Encode refuses an input name that already ends with
.bz3. - After success, the tool removes the input file. It keeps the file with
-k,-c, test mode, or standard input. - Recover mode never removes the input file. It keeps its output after a failure.
- If
argv[0]isbunzip3orbz3cat, the tool decodes.bz3catalso writes to standard output.
Recover mode
Recover mode decodes every block that it can find.
- A block with a checksum fault keeps its decoded bytes. Any other damaged block gives zero bytes. The output keeps its size, so the offsets after a damaged block stay correct.
- A damaged block prints one line on standard error:
Writing invalid block <number> at input offset <offset>: <fault>. Output bytes <first> to <last> keep the decoded bytes.The line ends withare zero.when the block gives zero bytes. - A bad block header or missing data stops the run. The blocks before it stay in the output.
The tool prints
Recovery stopped at block <number>, input offset <offset>. Output bytes written: <size>. Damaged blocks: <count>.Bzip3 blocks have no sync marker, so the tool does not search for the next block. - A bad block size in the frame header prints
Recovery mode: Proceeding.. The tool then takes the block size from the block headers. - The exit code is 2 when a block is damaged or the run stops early. A bad signature is a fatal fault.
Helper scripts and man pages
The repository holds the scripts bz3diff, bz3grep, and bz3more.
These scripts need the bzip3 tool in PATH.
The directory man/man1 holds the man pages.
Compatibility with C bzip3
- This crate reads files from C bzip3. C bzip3 reads files from this crate.
- One-shot output uses a 13-byte frame header.
- Streaming output uses a 9-byte frame header.
- One-shot decode ignores bytes after the last block.
- Streaming decode rejects trailing bytes that do not form a full block.
- Streaming encode records the requested block size as given.
- One-shot encode clamps small inputs to 65 KiB.
Differences from C bzip3
- The default job count is 0 (all cores). C bzip3 uses 1 thread.
- Output bytes are the same at every job count.
- Recover mode writes zero bytes for a block with a fault other than the checksum. C bzip3 writes the decode buffer, which holds partial data.
- Recover mode exits with code 2 when it finds damage. C bzip3 exits with code 0.
- Recover mode never removes the input file. C bzip3 removes it unless
-kis set. - Recover mode takes the block size from the block headers when the frame header has a bad block size. The reference uses 511 MiB.
- Batch remove paths are absent.
Cargo features
| Feature | Default | Purpose |
|---|---|---|
cli |
no | Builds the bzip3 tool. Adds the clap dependency. |
bench-internals |
no | Exposes stage functions for benchmarks. Not public API. |
Minimum Rust version
Rust 1.88 or later. The crate uses edition 2024.
Development
The workflow perf-gate compares the speed of the bzip3 tool with the C bzip3 tool.
The file tests/corpus/README.md describes the test corpus.
License
The crate has the license Apache-2.0.
LICENSEholds the Apache-2.0 text.
Attribution
This crate is an independent rewrite in Rust of bzip3 by Kamila Szewczyk.
- Original C code: Copyright 2022-2024 Kamila Szewczyk.
- BWT (libsais) and LZP code: Copyright 2021-2022 Ilya Grebnov.