Compact binary diff & patch library and CLI for Rust.
Generates minimal patches between two binary files using rolling-hash matching, then reconstructs the target by applying the patch to the original.
- SIMD-accelerated comparison — AVX2 on x86_64, NEON on AArch64, automatic scalar fallback
- Streaming opcode iterator — zero-allocation
OpIterfor lazy patch traversal - Compact binary format — only two opcodes:
Copy(reference old) andAdd(literal bytes) - No unsafe in public API — SIMD is internal; the library surface is fully safe
- Minimal dependencies — only
rustc-hashfor the library
Add to Cargo.toml:
[dependencies]
bitcut = { version = "1", default-features = false }
default-features = falsedisables the CLI dependencies (clap,anyhow).
use bitcut::{make_patch, apply_patch};
let old = b"the quick brown fox jumps over the lazy dog";
let new = b"the quick brown cat jumps over the lazy dog";
let patch = make_patch(old, new)?;
let result = apply_patch(old, &patch)?;
assert_eq!(result, new);use bitcut::Op;
let ops: Vec<Op> = Op::iter(&patch).collect::<Result<_, _>>()?;
for op in &ops {
match op {
Op::Copy { offset, len } => println!("copy {len} bytes from offset {offset}"),
Op::Add(bytes) => println!("add {} new bytes", bytes.len()),
}
}use bitcut::{make_patch_into, apply_patch_into};
let mut patch_buf = Vec::new();
make_patch_into(old, new, &mut patch_buf)?;
let mut output = Vec::new();
apply_patch_into(old, &patch_buf, &mut output)?;A patch is a sequence of two opcodes (little-endian integers):
| Opcode | Tag | Layout |
|---|---|---|
| Copy | 0x00 |
offset:u32 len:u32 |
| Add | 0x01 |
len:u32 bytes... |
Maximum input size: 4 GiB (u32::MAX).
cargo install bitcut# create a patch
bitcut diff old.bin new.bin > patch.bin
# apply a patch
bitcut patch old.bin patch.bin > new.bincargo build --release
./target/release/bitcut diff old.bin new.bin > patch.bin