Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A few improvement ideas #7

Merged
merged 1 commit into from
Apr 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ root = true
[*]
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
trim_trailing_whitespace = true
12 changes: 7 additions & 5 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2
- name: Build
run: cargo build --verbose
- name: Run tests
run: cargo test --verbose
- uses: actions/checkout@v2
- name: Build
run: RUSTFLAGS='-D warnings' cargo build --verbose
- name: Run tests
run: cargo test --verbose
- name: Clippy
run: cargo clippy -- -D warnings
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
target/

.DS_Store
Cargo.lock
Cargo.lock
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ keywords = ["bspatch", "patch", "diff", "delta", "binary"]
license = "BSD-2-Clause"
homepage = "https://lib.rs/bsdiff"
repository = "https://github.com/space-wizards/bsdiff-rs"
edition = "2018"
edition = "2021"
include = ["src/*.rs", "LICENSE", "README.md", "Cargo.toml"]
61 changes: 44 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,30 +1,57 @@
# bsdiff-rs

[![Build status](https://github.com/space-wizards/bsdiff-rs/actions/workflows/rust.yml/badge.svg)](https://github.com/space-wizards/bsdiff-rs/actions/workflows/rust.yml)
[![Cargo Link](https://img.shields.io/crates/v/bsdiff.svg)](https://crates.rs/crates/bsdiff)
[![GitHub](https://img.shields.io/badge/github-bsdiff-8da0cb?logo=github)](https://github.com/space-wizards/bsdiff-rs)
[![crates.io version](https://img.shields.io/crates/v/bsdiff.svg)](https://crates.io/crates/bsdiff)
[![docs.rs docs](https://docs.rs/bsdiff/badge.svg)](https://docs.rs/bsdiff)
[![crates.io version](https://img.shields.io/crates/l/bsdiff.svg)](https://github.comspace-wizards/bsdiff-rss/blob/main/LICENSE-APACHE)
[![CI build](https://github.com/space-wizards/bsdiff-rs/actions/workflows/rust.yml/badge.svg)](https://github.com/space-wizards/bsdiff-rs/actions)

Rust port of a [bsdiff library](https://github.com/mendsley/bsdiff). High performance patching. All written in safe Rust.
Bsdiff is a method of diffing files. This crate is a port of a [bsdiff library](https://github.com/mendsley/bsdiff).
High performance patching. All written in safe
Rust.

## Diffing
It is usually a good idea to use bsdiff alongside a compression algorithm like bzip2.

## Usage

```rust
let old = std::fs::read("old")?;
let new = std::fs::read("new")?;
let mut patch = Vec::new();
fn main() {
let one = vec![1, 2, 3, 4, 5];
let two = vec![1, 2, 4, 6];
let mut patch = Vec::new();

bsdiff::diff(&one, &two, &mut patch).unwrap();

bsdiff::diff(&old, &new, &mut patch)?;
// TODO: compress `patch` here
std::fs::write("patch", &patch)?;
let mut patched = Vec::with_capacity(two.len());
bsdiff::patch(&one, &mut patch.as_slice(), &mut patched).unwrap();
assert_eq!(patched, two);
}
```

## Patching
## Diffing Files

```rust
let old = std::fs::read("old")?;
let patch = std::fs::read("patch")?;
// TODO: decompress `patch` here
let mut new = Vec::new();
fn diff_files(file_a: &str, file_b: &str, patch_file: &str) -> std::io::Result<()> {
let old = std::fs::read(file_a)?;
let new = std::fs::read(file_b)?;
let mut patch = Vec::new();

bsdiff::diff(&old, &new, &mut patch)?;
// TODO: compress `patch` here
std::fs::write(patch_file, &patch)
}
```

bsdiff::patch(&old, &mut patch.as_slice(), &mut new)?;
std::fs::write("new", &new)?;
## Patching Files

```rust
fn patch_file(file_a: &str, patch_file: &str, file_b: &str) -> std::io::Result<()> {
let old = std::fs::read(file_a)?;
let patch = std::fs::read(patch_file)?;
// TODO: decompress `patch` here
let mut new = Vec::new();

bsdiff::patch(&old, &mut patch.as_slice(), &mut new)?;
std::fs::write(file_b, &new)
}
```
26 changes: 14 additions & 12 deletions src/diff.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
* POSSIBILITY OF SUCH DAMAGE.
*/

use std::cmp::Ordering;
use std::io;
use std::io::Write;

Expand Down Expand Up @@ -101,15 +102,16 @@ fn split_internal(
let mut k = 0;
let mut i = start;
while i < jj {
let v = V[usz(I[i] + h as isize)];
if v < x {
i += 1;
} else if v == x {
I.swap(i, jj + j);
j += 1;
} else {
I.swap(i, kk + k);
k += 1;
match V[usz(I[i] + h as isize)].cmp(&x) {
Ordering::Less => i += 1,
kornelski marked this conversation as resolved.
Show resolved Hide resolved
Ordering::Equal => {
I.swap(i, jj + j);
j += 1;
}
Ordering::Greater => {
I.swap(i, kk + k);
k += 1;
}
}
}
while jj + j < kk {
Expand Down Expand Up @@ -210,14 +212,14 @@ fn matchlen(old: &[u8], new: &[u8]) -> usize {
fn search(I: &[isize], old: &[u8], new: &[u8]) -> (isize, usize) {
if I.len() < 3 {
let x = matchlen(&old[usz(I[0])..], new);
let y = matchlen(&old[usz(I[I.len()-1])..], new);
let y = matchlen(&old[usz(I[I.len() - 1])..], new);
if x > y {
(I[0], x)
} else {
(I[I.len()-1], y)
(I[I.len() - 1], y)
}
} else {
let mid = (I.len()-1) / 2;
let mid = (I.len() - 1) / 2;
let left = &old[usz(I[mid])..];
let right = new;
let len_to_check = left.len().min(right.len());
Expand Down
20 changes: 1 addition & 19 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,4 @@
//! Bsdiff is a method of diffing files.
//! This crate has been ported from C code.
//! The original code and more info can be found [here](https://github.com/mendsley/bsdiff).
//!
//! It is usually a good idea to use bsdiff alongside a compression algorithm like bzip2.
//!
//! # Example
//!
//! ```
//! let one = vec![1, 2, 3, 4, 5];
//! let two = vec![1, 2, 4, 6];
//! let mut patch = Vec::new();
//!
//! bsdiff::diff(&one, &two, &mut patch).unwrap();
//!
//! let mut patched = Vec::with_capacity(two.len());
//! bsdiff::patch(&one, &mut patch.as_slice(), &mut patched).unwrap();
//! assert_eq!(patched, two);
//! ```
#![doc = include_str!("../README.md")]

mod diff;
mod patch;
Expand Down
10 changes: 5 additions & 5 deletions src/patch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,15 @@ use std::io;
use std::io::Read;

/// Apply a patch to an "old" file, returning the "new" file.
///
///
/// `old` is the old file, `patch` will be read from with the patch,`new` is the buffer that will be written into.
pub fn patch<T: Read>(old: &[u8], patch: &mut T, new: &mut Vec<u8>) -> io::Result<()> {
let mut oldpos: usize = 0;
loop {
// Read control data
let mut buf = [0; 24];
if read_or_eof(patch, &mut buf)? {
return Ok(())
return Ok(());
}

// only seek can be negative
Expand Down Expand Up @@ -99,7 +99,7 @@ fn read_or_eof<T: Read>(reader: &mut T, buf: &mut [u8; 24]) -> io::Result<bool>
} else {
Err(io::ErrorKind::UnexpectedEof.into())
}
},
}
Ok(n) => {
if n >= tmp.len() {
return Ok(false);
Expand All @@ -116,9 +116,9 @@ fn read_or_eof<T: Read>(reader: &mut T, buf: &mut [u8; 24]) -> io::Result<bool>
#[inline]
fn offtin(buf: [u8; 8]) -> i64 {
let y = i64::from_le_bytes(buf);
if 0 == y & (1<<63) {
if 0 == y & (1 << 63) {
y
} else {
-(y & !(1<<63))
-(y & !(1 << 63))
}
}
Loading