2 unstable releases

0.2.0 Aug 2, 2023
0.1.0 Mar 29, 2023

#1145 in Text processing

32 downloads per month

LGPL-3.0-only

35KB
831 lines

libxdiff

Safe, idiomatic Rust bindings for the libxdiff C library.

Crates.io docs

Usage

Add this to your Cargo.toml:

[dependencies]
libxdiff = "0.2"

Example

use core::str::from_utf8;
use libxdiff::MMFile;

let mut f1 = MMFile::from_bytes(b"hello world\n");
let mut f2 = MMFile::from_bytes(b"hello world!\n");
let mut diff_lines = Vec::<String>::new();
f1.diff_raw(&mut f2, |line: &[u8]| {
    diff_lines.push(from_utf8(line).unwrap().to_owned());
})
.unwrap();
assert_eq!(
    diff_lines,
    vec![
        "@@ -1,1 +1,1 @@\n",
        "-", "hello world\n",
        "+", "hello world!\n",
    ],
);

Linkage

Upstream libxdiff is small and has no dependencies, so this crate links it statically.


lib.rs:

libxdiff bindings for Rust

This library contains bindings to the libxdiff C library. The underlying library defines "MMFiles" using chains of non-contiguous buffers to minimize reallocations when appending and mutating. This wrapper structures the API by defining all MMFiles to be compact (backed by a single buffer). The non-compact form is MMBlocks.

libxdiff tracks iteration over buffers internally, so some operations that conceptually are read-only end up requiring &mut arguments in order to be safe.

Example

use core::str::from_utf8;
use libxdiff::MMFile;

let mut f1 = MMFile::from_bytes(b"hello world\n");
let mut f2 = MMFile::from_bytes(b"hello world!\n");
let mut diff_lines = Vec::<String>::new();
f1.diff_raw(&mut f2, |line: &[u8]| {
    diff_lines.push(from_utf8(line).unwrap().to_owned());
})
.unwrap();

assert_eq!(
    diff_lines,
    vec![
        "@@ -1,1 +1,1 @@\n",
        "-", "hello world\n",
        "+", "hello world!\n",
    ],
);

Dependencies

~0.6–2.5MB
~52K SLoC