Struct diff_match_patch_rs::dmp::DiffMatchPatch

source ·
pub struct DiffMatchPatch { /* private fields */ }

Implementations§

source§

impl DiffMatchPatch

source

pub fn set_checklines(&mut self, checklines: bool)

Enables or disables line mode optimization. When enabled, the diff algorithm tries to find the lines that have changes and apply diff on the same

This optimization makes sense for text with many lines (~100s), defaults to true

source

pub fn set_edit_cost(&mut self, edit_cost: usize)

Update edit cost

source

pub fn set_timeout(&mut self, tout: Option<u32>)

Set a timeout in number of milliseconds. This creates a cutoff for internal recursive function calls

Defaults to 1000ms (1 second)

None means infinite time

source

pub fn deadline(&self) -> Option<Instant>

source

pub fn set_match_threshold(&mut self, threshold: f32)

The match_threshold property determines the cut-off value for a valid match. If match_threshold is closer to 0, the requirements for accuracy increase. If match_threshold is closer to 1 then it is more likely that a match will be found. The match_threshold is, the slower match_main() may take to compute.

defaults to 0.5

source

pub fn set_delete_threshold(&mut self, threshold: f32)

When deleting a large block of text (over ~64 characters), how close does the contents have to match the expected contents. (0.0 = perfection, 1.0 = very loose). Note that match_threshold controls how closely the end points of a delete need to match.

Defaults to 0.5

source

pub fn set_match_distance(&mut self, distance: usize)

How far to search for a match (0 = exact location, 1000+ = broad match). A match this many characters away from the expected location will add 1.0 to the score (0.0 is a perfect match).

source

pub fn bisect<'a, T: DType>( &self, old: &'a [T], new: &'a [T], deadline: Option<Instant>, ) -> Result<Vec<Diff<T>>, Error>

source

pub fn diff_text_old<T: DType>(diffs: &[Diff<T>]) -> Vec<T>

source

pub fn diff_text_new<T: DType>(diffs: &[Diff<T>]) -> Vec<T>

source§

impl DiffMatchPatch

source

pub fn new() -> Self

Create a new instance of the struct with default settings

§Example
use diff_match_patch_rs::{DiffMatchPatch, Error, Efficient};

let mut dmp = DiffMatchPatch::new();
// change some settings, e.g. set `line mode` optimization to `false` because you know you have a small text and not many lines
dmp.set_checklines(false);
// do the diffing
let diffs = dmp.diff_main::<Efficient>("Fast enough", "Blazing fast")?;
Examples found in repository?
examples/delta.rs (line 25)
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
fn at_source() -> Result<String, Error> {
    // initializing the module
    let dmp = DiffMatchPatch::new();

    // create a list of diffs
    let diffs = dmp.diff_main::<Efficient>(TXT_OLD, TXT_NEW)?;

    // When dealing with large text blocks and if you want to transmit this diff, `delta` will give you a minimal over the air representation of diffs
    // We'll use this delta string to recreate `diffs` at the destination and then create patches to apply
    let delta = dmp.diff_to_delta(&diffs)?;

    // lets see how our delta looks
    println!("{delta:?}");
    // You should see something like this
    // =25\t-1\t+carto\t=1\t-3\t=2\t-8\t+i\t=1\t-2\t+dividu\t=4\t-4\t+My\t=1\t-1\t+a\t=1\t-3\t+i\t=6\t+'s\t=1\t-5\t+comic\t=1\t-1\t=1\t-1\t=2\t-1\t+u\t=1\t-2\t+usu\t=8\t+whi\t=1\t+s\t=1\t-3\t+c\t=5\t+'m\t=1\t-5\t+qui\t=1\t-1\t=2\t-13\t=1\t-1\t=1\t-1\t+ept\t=2\t+t fu\t=1\t-1\t+ny\t=1\t-1\t+gags,\t=1\t-2\t+c\t=1\t-1\t+m\t=1\t+dic\t=4\t+ory\t=1\t-6\t+I\t=2\t-4\t+ave \t=1\t-2\t+e\t=1\t-1\t+d\t=7\t-1\t+wicked puns \t=1\t-2\t+nd s\t=1\t-1\t+upid j\t=1\t-1\t+kes\t=4\t-1\t+anvils th\t=2\t-1\t+ d\t=1\t-1\t=1\t+p \t=1\t-3\t=2\t+y\t=1\t-3\t+u\t=2\t-3\t+h\t=1\t-5\t=1\t-1\t+d\t=3\t-1\t+Now, l\t=5\t-3\t+explo\t=1\t-6\t+e\t=6\t-3\t+emot\t=1\t-1\t+onal extreme\t=4\t-1\t+%8C\t=18\t+ec\t=3\t-8\t+t\t=1\t-3\t+c\t=8\t-2\t+%A4%A9\t=7\t+deva\t=1\t+t\t=1\t+te\t=7\t-1\t+%F0%9F\t=1\t-4\t+%AD\t=11\t-3\t+utte\t=1\t+l\t=2\t+confused \t=7\t-2\t+%A4%AF\t=6\t-1\t+th\t=1\t-1\t=1\t-7\t=3\t-1\t+n\t=1\t-2\t+t all\t=5\t-1\t+%94\t=21\t-9\t+subt\t=2\t-1\t=18\t-64\t+%90\t=4\t-2\t+%99%83\t=9\t-1\t+%80\t=1

    Ok(delta)
}

fn at_destination(delta: &str) -> Result<(), Error> {
    // initializing the module
    let dmp = DiffMatchPatch::new();

    // lets recreate the diffs from the minimal `delta` string
    let delta = dmp.diff_from_delta::<Efficient>(TXT_OLD, delta)?;
    // Additional step of conveting `delta` -> `patches`
    let patches = dmp.patch_make(PatchInput::new_diffs(&delta))?;

    // Now, lets apply these patches to the `old_txt` which is the original to get the new text
    let (new_txt, ops) = dmp.patch_apply(&patches, TXT_OLD)?;

    // Lets print out if the ops succeeded or not
    ops.iter()
        .for_each(|&o| println!("{}", if o { "OK" } else { "FAIL" }));

    // If everything goes as per plan you should see
    // OK
    // OK
    // ... and so on

    // lets check out if our `NEW_TXT` (presumably the edited one)
    if new_txt != TXT_NEW {
        return Err(Error::InvalidInput);
    }

    println!("Wallah! Patch applied successfully!");

    Ok(())
}
More examples
Hide additional examples
examples/compat.rs (line 25)
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
fn at_source() -> Result<String, Error> {
    // initializing the module
    let dmp = DiffMatchPatch::new();

    // create a list of diffs
    let diffs = dmp.diff_main::<Efficient>(TXT_OLD, TXT_NEW)?;

    // Now, we are going to create a list of `patches` to be applied to the old text to get the new text
    let patches = dmp.patch_make(PatchInput::new_diffs(&diffs))?;

    // in the real world you are going to transmit or store this diff serialized to undiff format to be consumed or used somewhere elese
    let patch_txt = dmp.patch_to_text(&patches);

    // lets see how our patches look
    println!("{patch_txt:?}");
    // You should see something like this
    // @@ -22,225 +22,250 @@\n f a \n-m\n+carto\n o\n-der\n n \n-Major-Ge\n+i\n n\n-er\n+dividu\n al,%0A\n-I've\n+My\n  \n-i\n+a\n n\n-for\n+i\n mation\n+'s\n  \n-veget\n+comic\n a\n-b\n l\n-e\n , \n-a\n+u\n n\n-im\n+usu\n al, and \n+whi\n m\n+s\n i\n-ner\n+c\n al,%0AI\n+'m\n  \n-know \n+qui\n t\n-h\n e \n-kings of Engl\n a\n-n\n d\n-,\n+ept\n  a\n+t fu\n n\n-d\n+ny\n  \n-I\n+gags,\n  \n-qu\n+c\n o\n-t\n+m\n e\n+dic\n  the\n+ory\n  \n-fights\n+I\n  h\n-isto\n+ave \n r\n-ic\n+e\n a\n-l\n+d\n ,%0AFrom \n-M\n+wicked puns \n a\n-ra\n+nd s\n t\n-h\n+upid j\n o\n-n\n+kes\n  to \n-W\n+anvils th\n at\n-e\n+ d\n r\n-l\n o\n+p \n o\n-, i\n n \n+y\n o\n-rde\n+u\n r \n-cat\n+h\n e\n-goric\n a\n-l\n+d\n .%0A%0A\n-L\n+Now, l\n et's \n-sta\n+explo\n r\n-t with\n+e\n  some \n-bas\n+emot\n i\n-c\n+onal extreme\n s %F0%9F\n-%98\n+%8C\n %8A. W\n@@ -282,55 +282,53 @@\n our \n+ec\n sta\n-ndard sm\n+t\n i\n-ley\n+c\n  face %F0%9F\n-%99%82\n+%A4%A9\n , your \n+deva\n s\n+t\n a\n+te\n d face \n-%E2\n+%F0%9F\n %98\n-%B9%EF%B8%8F\n+%AD\n , an\n@@ -338,53 +338,60 @@\n our \n-ang\n+utte\n r\n+l\n y \n+confused \n face %F0%9F\n-%98%A0\n+%A4%AF\n . But \n-w\n+th\n a\n-i\n t\n-, there\n 's \n-m\n+n\n o\n-re\n+t all\n ! %F0%9F%A4\n-%A9\n+%94\n  We'\n@@ -411,20 +411,14 @@\n ome \n-more comp\n+subt\n le\n-x\n  emo\n@@ -435,78 +435,15 @@\n  %F0%9F%98\n-%8D, %F0%9F%A4%A4, and %F0%9F%9A%80. And let's not forget about the classics: %F0%9F%98%89\n+%90\n , %F0%9F\n-%91%8D\n+%99%83\n , an\n@@ -451,6 +451,6 @@\n  %F0%9F%91\n-%8F\n+%80\n .\n

    Ok(patch_txt)
}

fn at_destination(patches: &str) -> Result<(), Error> {
    // initializing the module
    let dmp = DiffMatchPatch::new();

    // lets recreate the diffs from patches
    let patches = dmp.patch_from_text::<Efficient>(patches)?;

    // Now, lets apply these patches to the `old_txt` which is the original to get the new text
    let (new_txt, ops) = dmp.patch_apply(&patches, TXT_OLD)?;

    // Lets print out if the ops succeeded or not
    ops.iter()
        .for_each(|&o| println!("{}", if o { "OK" } else { "FAIL" }));

    // If everything goes as per plan you should see
    // OK
    // OK
    // ... and so on

    // lets check out if our `NEW_TXT` (presumably the edited one)
    if new_txt != TXT_NEW {
        return Err(Error::InvalidInput);
    }

    println!("Wallah! Patch applied successfully!");

    Ok(())
}
examples/efficiency.rs (line 32)
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
fn at_source() -> Result<String, Error> {
    // initializing the module
    let dmp = DiffMatchPatch::new();

    // create a list of diffs
    let diffs = dmp.diff_main::<Efficient>(TXT_OLD, TXT_NEW)?;

    // Now, we are going to create a list of `patches` to be applied to the old text to get the new text
    let patches = dmp.patch_make(PatchInput::new_diffs(&diffs))?;

    // in the real world you are going to transmit or store this diff serialized to undiff format to be consumed or used somewhere elese
    let patch_txt = dmp.patch_to_text(&patches);

    // lets see how our patches look
    println!("{patch_txt:?}");
    // You should see something like this
    // @@ -22,225 +22,250 @@\n f a \n-m\n+carto\n o\n-der\n n \n-Major-Ge\n+i\n n\n-er\n+dividu\n al,%0A\n-I've\n+My\n  \n-i\n+a\n n\n-for\n+i\n mation\n+'s\n  \n-veget\n+comic\n a\n-b\n l\n-e\n , \n-a\n+u\n n\n-im\n+usu\n al, and \n+whi\n m\n+s\n i\n-ner\n+c\n al,%0AI\n+'m\n  \n-know \n+qui\n t\n-h\n e \n-kings of Engl\n a\n-n\n d\n-,\n+ept\n  a\n+t fu\n n\n-d\n+ny\n  \n-I\n+gags,\n  \n-qu\n+c\n o\n-t\n+m\n e\n+dic\n  the\n+ory\n  \n-fights\n+I\n  h\n-isto\n+ave \n r\n-ic\n+e\n a\n-l\n+d\n ,%0AFrom \n-M\n+wicked puns \n a\n-ra\n+nd s\n t\n-h\n+upid j\n o\n-n\n+kes\n  to \n-W\n+anvils th\n at\n-e\n+ d\n r\n-l\n o\n+p \n o\n-, i\n n \n+y\n o\n-rde\n+u\n r \n-cat\n+h\n e\n-goric\n a\n-l\n+d\n .%0A%0A\n-L\n+Now, l\n et's \n-sta\n+explo\n r\n-t with\n+e\n  some \n-bas\n+emot\n i\n-c\n+onal extreme\n s %F0%9F\n-%98\n+%8C\n %8A. W\n@@ -282,55 +282,53 @@\n our \n+ec\n sta\n-ndard sm\n+t\n i\n-ley\n+c\n  face %F0%9F\n-%99%82\n+%A4%A9\n , your \n+deva\n s\n+t\n a\n+te\n d face \n-%E2\n+%F0%9F\n %98\n-%B9%EF%B8%8F\n+%AD\n , an\n@@ -338,53 +338,60 @@\n our \n-ang\n+utte\n r\n+l\n y \n+confused \n face %F0%9F\n-%98%A0\n+%A4%AF\n . But \n-w\n+th\n a\n-i\n t\n-, there\n 's \n-m\n+n\n o\n-re\n+t all\n ! %F0%9F%A4\n-%A9\n+%94\n  We'\n@@ -411,20 +411,14 @@\n ome \n-more comp\n+subt\n le\n-x\n  emo\n@@ -435,78 +435,15 @@\n  %F0%9F%98\n-%8D, %F0%9F%A4%A4, and %F0%9F%9A%80. And let's not forget about the classics: %F0%9F%98%89\n+%90\n , %F0%9F\n-%91%8D\n+%99%83\n , an\n@@ -451,6 +451,6 @@\n  %F0%9F%91\n-%8F\n+%80\n .\n

    Ok(patch_txt)
}

fn at_destination(patches: &str) -> Result<(), Error> {
    // initializing the module
    let dmp = DiffMatchPatch::new();

    // lets recreate the diffs from patches
    let patches = dmp.patch_from_text::<Efficient>(patches)?;

    // Now, lets apply these patches to the `old_txt` which is the original to get the new text
    let (new_txt, ops) = dmp.patch_apply(&patches, TXT_OLD)?;

    // Lets print out if the ops succeeded or not
    ops.iter()
        .for_each(|&o| println!("{}", if o { "OK" } else { "FAIL" }));

    // If everything goes as per plan you should see
    // OK
    // OK
    // ... and so on

    // lets check out if our `NEW_TXT` (presumably the edited one)
    if new_txt != TXT_NEW {
        return Err(Error::InvalidInput);
    }

    println!("Wallah! Patch applied successfully!");

    Ok(())
}
source

pub fn diff_main<T: DType>( &self, old: &str, new: &str, ) -> Result<Vec<Diff<T>>, Error>

Find the differences between two texts (old and new). Simplifies the problem by stripping any common prefix or suffix off the texts before diffing.

Returns: Vec of changes (Diff).

§Example

let mut dmp = DiffMatchPatch::new();
// change some settings, e.g. set `line mode` optimization to `false` because you know you have a small text and not many lines
dmp.set_checklines(false);
// do the diffing
let diffs = dmp.diff_main::<Efficient>("Fast enough", "Blazing fast")?;
println!("{}", diffs.iter().map(|d| format!("d")).collect::<Vec<_>>().join("\n"));
// You should see the following output
// (Delete, F)
// (Insert, Blazing f)
// (Equal, ast)
// (Delete,  enough)
Examples found in repository?
examples/delta.rs (line 28)
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
fn at_source() -> Result<String, Error> {
    // initializing the module
    let dmp = DiffMatchPatch::new();

    // create a list of diffs
    let diffs = dmp.diff_main::<Efficient>(TXT_OLD, TXT_NEW)?;

    // When dealing with large text blocks and if you want to transmit this diff, `delta` will give you a minimal over the air representation of diffs
    // We'll use this delta string to recreate `diffs` at the destination and then create patches to apply
    let delta = dmp.diff_to_delta(&diffs)?;

    // lets see how our delta looks
    println!("{delta:?}");
    // You should see something like this
    // =25\t-1\t+carto\t=1\t-3\t=2\t-8\t+i\t=1\t-2\t+dividu\t=4\t-4\t+My\t=1\t-1\t+a\t=1\t-3\t+i\t=6\t+'s\t=1\t-5\t+comic\t=1\t-1\t=1\t-1\t=2\t-1\t+u\t=1\t-2\t+usu\t=8\t+whi\t=1\t+s\t=1\t-3\t+c\t=5\t+'m\t=1\t-5\t+qui\t=1\t-1\t=2\t-13\t=1\t-1\t=1\t-1\t+ept\t=2\t+t fu\t=1\t-1\t+ny\t=1\t-1\t+gags,\t=1\t-2\t+c\t=1\t-1\t+m\t=1\t+dic\t=4\t+ory\t=1\t-6\t+I\t=2\t-4\t+ave \t=1\t-2\t+e\t=1\t-1\t+d\t=7\t-1\t+wicked puns \t=1\t-2\t+nd s\t=1\t-1\t+upid j\t=1\t-1\t+kes\t=4\t-1\t+anvils th\t=2\t-1\t+ d\t=1\t-1\t=1\t+p \t=1\t-3\t=2\t+y\t=1\t-3\t+u\t=2\t-3\t+h\t=1\t-5\t=1\t-1\t+d\t=3\t-1\t+Now, l\t=5\t-3\t+explo\t=1\t-6\t+e\t=6\t-3\t+emot\t=1\t-1\t+onal extreme\t=4\t-1\t+%8C\t=18\t+ec\t=3\t-8\t+t\t=1\t-3\t+c\t=8\t-2\t+%A4%A9\t=7\t+deva\t=1\t+t\t=1\t+te\t=7\t-1\t+%F0%9F\t=1\t-4\t+%AD\t=11\t-3\t+utte\t=1\t+l\t=2\t+confused \t=7\t-2\t+%A4%AF\t=6\t-1\t+th\t=1\t-1\t=1\t-7\t=3\t-1\t+n\t=1\t-2\t+t all\t=5\t-1\t+%94\t=21\t-9\t+subt\t=2\t-1\t=18\t-64\t+%90\t=4\t-2\t+%99%83\t=9\t-1\t+%80\t=1

    Ok(delta)
}
More examples
Hide additional examples
examples/compat.rs (line 28)
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
fn at_source() -> Result<String, Error> {
    // initializing the module
    let dmp = DiffMatchPatch::new();

    // create a list of diffs
    let diffs = dmp.diff_main::<Efficient>(TXT_OLD, TXT_NEW)?;

    // Now, we are going to create a list of `patches` to be applied to the old text to get the new text
    let patches = dmp.patch_make(PatchInput::new_diffs(&diffs))?;

    // in the real world you are going to transmit or store this diff serialized to undiff format to be consumed or used somewhere elese
    let patch_txt = dmp.patch_to_text(&patches);

    // lets see how our patches look
    println!("{patch_txt:?}");
    // You should see something like this
    // @@ -22,225 +22,250 @@\n f a \n-m\n+carto\n o\n-der\n n \n-Major-Ge\n+i\n n\n-er\n+dividu\n al,%0A\n-I've\n+My\n  \n-i\n+a\n n\n-for\n+i\n mation\n+'s\n  \n-veget\n+comic\n a\n-b\n l\n-e\n , \n-a\n+u\n n\n-im\n+usu\n al, and \n+whi\n m\n+s\n i\n-ner\n+c\n al,%0AI\n+'m\n  \n-know \n+qui\n t\n-h\n e \n-kings of Engl\n a\n-n\n d\n-,\n+ept\n  a\n+t fu\n n\n-d\n+ny\n  \n-I\n+gags,\n  \n-qu\n+c\n o\n-t\n+m\n e\n+dic\n  the\n+ory\n  \n-fights\n+I\n  h\n-isto\n+ave \n r\n-ic\n+e\n a\n-l\n+d\n ,%0AFrom \n-M\n+wicked puns \n a\n-ra\n+nd s\n t\n-h\n+upid j\n o\n-n\n+kes\n  to \n-W\n+anvils th\n at\n-e\n+ d\n r\n-l\n o\n+p \n o\n-, i\n n \n+y\n o\n-rde\n+u\n r \n-cat\n+h\n e\n-goric\n a\n-l\n+d\n .%0A%0A\n-L\n+Now, l\n et's \n-sta\n+explo\n r\n-t with\n+e\n  some \n-bas\n+emot\n i\n-c\n+onal extreme\n s %F0%9F\n-%98\n+%8C\n %8A. W\n@@ -282,55 +282,53 @@\n our \n+ec\n sta\n-ndard sm\n+t\n i\n-ley\n+c\n  face %F0%9F\n-%99%82\n+%A4%A9\n , your \n+deva\n s\n+t\n a\n+te\n d face \n-%E2\n+%F0%9F\n %98\n-%B9%EF%B8%8F\n+%AD\n , an\n@@ -338,53 +338,60 @@\n our \n-ang\n+utte\n r\n+l\n y \n+confused \n face %F0%9F\n-%98%A0\n+%A4%AF\n . But \n-w\n+th\n a\n-i\n t\n-, there\n 's \n-m\n+n\n o\n-re\n+t all\n ! %F0%9F%A4\n-%A9\n+%94\n  We'\n@@ -411,20 +411,14 @@\n ome \n-more comp\n+subt\n le\n-x\n  emo\n@@ -435,78 +435,15 @@\n  %F0%9F%98\n-%8D, %F0%9F%A4%A4, and %F0%9F%9A%80. And let's not forget about the classics: %F0%9F%98%89\n+%90\n , %F0%9F\n-%91%8D\n+%99%83\n , an\n@@ -451,6 +451,6 @@\n  %F0%9F%91\n-%8F\n+%80\n .\n

    Ok(patch_txt)
}
examples/efficiency.rs (line 35)
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
fn at_source() -> Result<String, Error> {
    // initializing the module
    let dmp = DiffMatchPatch::new();

    // create a list of diffs
    let diffs = dmp.diff_main::<Efficient>(TXT_OLD, TXT_NEW)?;

    // Now, we are going to create a list of `patches` to be applied to the old text to get the new text
    let patches = dmp.patch_make(PatchInput::new_diffs(&diffs))?;

    // in the real world you are going to transmit or store this diff serialized to undiff format to be consumed or used somewhere elese
    let patch_txt = dmp.patch_to_text(&patches);

    // lets see how our patches look
    println!("{patch_txt:?}");
    // You should see something like this
    // @@ -22,225 +22,250 @@\n f a \n-m\n+carto\n o\n-der\n n \n-Major-Ge\n+i\n n\n-er\n+dividu\n al,%0A\n-I've\n+My\n  \n-i\n+a\n n\n-for\n+i\n mation\n+'s\n  \n-veget\n+comic\n a\n-b\n l\n-e\n , \n-a\n+u\n n\n-im\n+usu\n al, and \n+whi\n m\n+s\n i\n-ner\n+c\n al,%0AI\n+'m\n  \n-know \n+qui\n t\n-h\n e \n-kings of Engl\n a\n-n\n d\n-,\n+ept\n  a\n+t fu\n n\n-d\n+ny\n  \n-I\n+gags,\n  \n-qu\n+c\n o\n-t\n+m\n e\n+dic\n  the\n+ory\n  \n-fights\n+I\n  h\n-isto\n+ave \n r\n-ic\n+e\n a\n-l\n+d\n ,%0AFrom \n-M\n+wicked puns \n a\n-ra\n+nd s\n t\n-h\n+upid j\n o\n-n\n+kes\n  to \n-W\n+anvils th\n at\n-e\n+ d\n r\n-l\n o\n+p \n o\n-, i\n n \n+y\n o\n-rde\n+u\n r \n-cat\n+h\n e\n-goric\n a\n-l\n+d\n .%0A%0A\n-L\n+Now, l\n et's \n-sta\n+explo\n r\n-t with\n+e\n  some \n-bas\n+emot\n i\n-c\n+onal extreme\n s %F0%9F\n-%98\n+%8C\n %8A. W\n@@ -282,55 +282,53 @@\n our \n+ec\n sta\n-ndard sm\n+t\n i\n-ley\n+c\n  face %F0%9F\n-%99%82\n+%A4%A9\n , your \n+deva\n s\n+t\n a\n+te\n d face \n-%E2\n+%F0%9F\n %98\n-%B9%EF%B8%8F\n+%AD\n , an\n@@ -338,53 +338,60 @@\n our \n-ang\n+utte\n r\n+l\n y \n+confused \n face %F0%9F\n-%98%A0\n+%A4%AF\n . But \n-w\n+th\n a\n-i\n t\n-, there\n 's \n-m\n+n\n o\n-re\n+t all\n ! %F0%9F%A4\n-%A9\n+%94\n  We'\n@@ -411,20 +411,14 @@\n ome \n-more comp\n+subt\n le\n-x\n  emo\n@@ -435,78 +435,15 @@\n  %F0%9F%98\n-%8D, %F0%9F%A4%A4, and %F0%9F%9A%80. And let's not forget about the classics: %F0%9F%98%89\n+%90\n , %F0%9F\n-%91%8D\n+%99%83\n , an\n@@ -451,6 +451,6 @@\n  %F0%9F%91\n-%8F\n+%80\n .\n

    Ok(patch_txt)
}
source

pub fn diff_cleanup_semantic(diffs: &mut Vec<Diff<u8>>)

A diff of two unrelated texts can be filled with coincidental matches. For example, the diff of “mouse” and “sofas” is [(-1, “m”), (1, “s”), (0, “o”), (-1, “u”), (1, “fa”), (0, “s”), (-1, “e”)]. While this is the optimum diff, it is difficult for humans to understand. Semantic cleanup rewrites the diff, expanding it into a more intelligible format. The above example would become: [(-1, “mouse”), (1, “sofas”)]. If a diff is to be human-readable, it should be passed to diff_cleanup_semantic.

source

pub fn diff_cleanup_efficiency(&self, diffs: &mut Vec<Diff<u8>>)

This function is similar to diff_cleanupSemantic, except that instead of optimising a diff to be human-readable, it optimises the diff to be efficient for machine processing. The results of both cleanup types are often the same.

The efficiency cleanup is based on the observation that a diff made up of large numbers of small diffs edits may take longer to process (in downstream applications) or take more capacity to store or transmit than a smaller number of larger diffs. The diff_match_patch.Diff_EditCost property sets what the cost of handling a new edit is in terms of handling extra characters in an existing edit. The default value is 4, which means if expanding the length of a diff by three characters can eliminate one edit, then that optimisation will reduce the total costs.

source

pub fn diff_levenshtein<T: DType>(&self, diffs: &[Diff<T>]) -> usize

Given a diff, measure its Levenshtein distance in terms of the number of inserted, deleted or substituted characters. The minimum distance is 0 which means equality, the maximum distance is the length of the longer string.

source

pub fn diff_pretty_html<T: DType>( &self, diffs: &[Diff<T>], html_cfg: &HtmlConfig<'_>, ) -> Result<String, Error>

Takes a diff array and returns a pretty HTML sequence. This function is mainly intended as an example from which to write ones own display functions.

§Example
let dmp = DiffMatchPatch::new();

let diffs = dmp.diff_main::<Efficient>("The old man and the new house?", "The old man and the old dog!")?;
let htmlcfg = HtmlConfig::new();

let pretty = dmp.diff_pretty_html(&diffs, &htmlcfg)?;
// Should print: "<span>The old man and the </span><del>new house?</del><ins>old dog!</ins>"
println!("{pretty}");

Check out HtmlConfig options for ways to control the generated html.

source

pub fn match_main(&self, text: &str, pattern: &str, loc: usize) -> Option<usize>

Given a text to search, a pattern to search for and an expected location in the text near which to find the pattern, return the location which matches closest. The function will search for the best match based on both the number of character errors between the pattern and the potential match, as well as the distance between the expected location and the potential match.

The following example is a classic dilemma. There are two potential matches, one is close to the expected location but contains a one character error, the other is far from the expected location but is exactly the pattern sought after: match_main(“abc12345678901234567890abbc”, “abc”, 26) Which result is returned (0 or 24) is determined by the diff_match_patch.match_distance property. An exact letter match which is ‘distance’ characters away from the fuzzy location would score as a complete mismatch. For example, a distance of ‘0’ requires the match be at the exact location specified, whereas a threshold of ‘1000’ would require a perfect match to be within 800 characters of the expected location to be found using a 0.8 threshold (see below). The larger match_distance is, the slower match_main() may take to compute. This variable defaults to 1000.

Another property is diff_match_patch.match_threshold which determines the cut-off value for a valid match. If match_threshold is closer to 0, the requirements for accuracy increase. If match_threshold is closer to 1 then it is more likely that a match will be found. The larger match_threshold is, the slower match_main() may take to compute. match_threshold defaults to 0.5 and can be updated by dmp.set_match_threshold() method.

If no match is found, the function returns -1.

source

pub fn patch_make<T: DType>( &self, input: PatchInput<'_, T>, ) -> Result<Patches<T>, Error>

Given two texts, or an already computed list of differences (diffs), return an array of patch objects.

§Example

let dmp = DiffMatchPatch::new();

// You can also make patches from the old and new string directly
let patches = dmp.patch_make::<Efficient>(PatchInput::new_text_text("Apples are a fruit.", "Bananas are also fruit"))?;
let (new_from_old, _) = dmp.patch_apply(&patches, "Apples are a fruit.")?;
assert_eq!("Bananas are also fruit", new_from_old);

// Or, create some diffs in `Efficient` or `Compact` mode
let diffs = dmp.diff_main::<Efficient>("Apples are a fruit.", "Bananas are also fruit")?;
// Now, lets convert the diffs to a bunch of patches - you can use an existing set of diffs to create patches
let patches = dmp.patch_make(PatchInput::new_diffs(&diffs))?;
let (new_from_old, _) = dmp.patch_apply(&patches, "Apples are a fruit.")?;
assert_eq!("Bananas are also fruit", new_from_old);

// Or, from the source texts and diffs
let patches = dmp.patch_make(PatchInput::new_text_diffs("Apples are a fruit.", &diffs))?;
let (new_from_old, _) = dmp.patch_apply(&patches, "Apples are a fruit.")?;
assert_eq!("Bananas are also fruit", new_from_old);

The PatchInput::new_text_diffs method is preferred, use it if you happen to have that data available, otherwise this function will compute the missing pieces.

Examples found in repository?
examples/delta.rs (line 49)
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
fn at_destination(delta: &str) -> Result<(), Error> {
    // initializing the module
    let dmp = DiffMatchPatch::new();

    // lets recreate the diffs from the minimal `delta` string
    let delta = dmp.diff_from_delta::<Efficient>(TXT_OLD, delta)?;
    // Additional step of conveting `delta` -> `patches`
    let patches = dmp.patch_make(PatchInput::new_diffs(&delta))?;

    // Now, lets apply these patches to the `old_txt` which is the original to get the new text
    let (new_txt, ops) = dmp.patch_apply(&patches, TXT_OLD)?;

    // Lets print out if the ops succeeded or not
    ops.iter()
        .for_each(|&o| println!("{}", if o { "OK" } else { "FAIL" }));

    // If everything goes as per plan you should see
    // OK
    // OK
    // ... and so on

    // lets check out if our `NEW_TXT` (presumably the edited one)
    if new_txt != TXT_NEW {
        return Err(Error::InvalidInput);
    }

    println!("Wallah! Patch applied successfully!");

    Ok(())
}
More examples
Hide additional examples
examples/compat.rs (line 31)
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
fn at_source() -> Result<String, Error> {
    // initializing the module
    let dmp = DiffMatchPatch::new();

    // create a list of diffs
    let diffs = dmp.diff_main::<Efficient>(TXT_OLD, TXT_NEW)?;

    // Now, we are going to create a list of `patches` to be applied to the old text to get the new text
    let patches = dmp.patch_make(PatchInput::new_diffs(&diffs))?;

    // in the real world you are going to transmit or store this diff serialized to undiff format to be consumed or used somewhere elese
    let patch_txt = dmp.patch_to_text(&patches);

    // lets see how our patches look
    println!("{patch_txt:?}");
    // You should see something like this
    // @@ -22,225 +22,250 @@\n f a \n-m\n+carto\n o\n-der\n n \n-Major-Ge\n+i\n n\n-er\n+dividu\n al,%0A\n-I've\n+My\n  \n-i\n+a\n n\n-for\n+i\n mation\n+'s\n  \n-veget\n+comic\n a\n-b\n l\n-e\n , \n-a\n+u\n n\n-im\n+usu\n al, and \n+whi\n m\n+s\n i\n-ner\n+c\n al,%0AI\n+'m\n  \n-know \n+qui\n t\n-h\n e \n-kings of Engl\n a\n-n\n d\n-,\n+ept\n  a\n+t fu\n n\n-d\n+ny\n  \n-I\n+gags,\n  \n-qu\n+c\n o\n-t\n+m\n e\n+dic\n  the\n+ory\n  \n-fights\n+I\n  h\n-isto\n+ave \n r\n-ic\n+e\n a\n-l\n+d\n ,%0AFrom \n-M\n+wicked puns \n a\n-ra\n+nd s\n t\n-h\n+upid j\n o\n-n\n+kes\n  to \n-W\n+anvils th\n at\n-e\n+ d\n r\n-l\n o\n+p \n o\n-, i\n n \n+y\n o\n-rde\n+u\n r \n-cat\n+h\n e\n-goric\n a\n-l\n+d\n .%0A%0A\n-L\n+Now, l\n et's \n-sta\n+explo\n r\n-t with\n+e\n  some \n-bas\n+emot\n i\n-c\n+onal extreme\n s %F0%9F\n-%98\n+%8C\n %8A. W\n@@ -282,55 +282,53 @@\n our \n+ec\n sta\n-ndard sm\n+t\n i\n-ley\n+c\n  face %F0%9F\n-%99%82\n+%A4%A9\n , your \n+deva\n s\n+t\n a\n+te\n d face \n-%E2\n+%F0%9F\n %98\n-%B9%EF%B8%8F\n+%AD\n , an\n@@ -338,53 +338,60 @@\n our \n-ang\n+utte\n r\n+l\n y \n+confused \n face %F0%9F\n-%98%A0\n+%A4%AF\n . But \n-w\n+th\n a\n-i\n t\n-, there\n 's \n-m\n+n\n o\n-re\n+t all\n ! %F0%9F%A4\n-%A9\n+%94\n  We'\n@@ -411,20 +411,14 @@\n ome \n-more comp\n+subt\n le\n-x\n  emo\n@@ -435,78 +435,15 @@\n  %F0%9F%98\n-%8D, %F0%9F%A4%A4, and %F0%9F%9A%80. And let's not forget about the classics: %F0%9F%98%89\n+%90\n , %F0%9F\n-%91%8D\n+%99%83\n , an\n@@ -451,6 +451,6 @@\n  %F0%9F%91\n-%8F\n+%80\n .\n

    Ok(patch_txt)
}
examples/efficiency.rs (line 38)
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
fn at_source() -> Result<String, Error> {
    // initializing the module
    let dmp = DiffMatchPatch::new();

    // create a list of diffs
    let diffs = dmp.diff_main::<Efficient>(TXT_OLD, TXT_NEW)?;

    // Now, we are going to create a list of `patches` to be applied to the old text to get the new text
    let patches = dmp.patch_make(PatchInput::new_diffs(&diffs))?;

    // in the real world you are going to transmit or store this diff serialized to undiff format to be consumed or used somewhere elese
    let patch_txt = dmp.patch_to_text(&patches);

    // lets see how our patches look
    println!("{patch_txt:?}");
    // You should see something like this
    // @@ -22,225 +22,250 @@\n f a \n-m\n+carto\n o\n-der\n n \n-Major-Ge\n+i\n n\n-er\n+dividu\n al,%0A\n-I've\n+My\n  \n-i\n+a\n n\n-for\n+i\n mation\n+'s\n  \n-veget\n+comic\n a\n-b\n l\n-e\n , \n-a\n+u\n n\n-im\n+usu\n al, and \n+whi\n m\n+s\n i\n-ner\n+c\n al,%0AI\n+'m\n  \n-know \n+qui\n t\n-h\n e \n-kings of Engl\n a\n-n\n d\n-,\n+ept\n  a\n+t fu\n n\n-d\n+ny\n  \n-I\n+gags,\n  \n-qu\n+c\n o\n-t\n+m\n e\n+dic\n  the\n+ory\n  \n-fights\n+I\n  h\n-isto\n+ave \n r\n-ic\n+e\n a\n-l\n+d\n ,%0AFrom \n-M\n+wicked puns \n a\n-ra\n+nd s\n t\n-h\n+upid j\n o\n-n\n+kes\n  to \n-W\n+anvils th\n at\n-e\n+ d\n r\n-l\n o\n+p \n o\n-, i\n n \n+y\n o\n-rde\n+u\n r \n-cat\n+h\n e\n-goric\n a\n-l\n+d\n .%0A%0A\n-L\n+Now, l\n et's \n-sta\n+explo\n r\n-t with\n+e\n  some \n-bas\n+emot\n i\n-c\n+onal extreme\n s %F0%9F\n-%98\n+%8C\n %8A. W\n@@ -282,55 +282,53 @@\n our \n+ec\n sta\n-ndard sm\n+t\n i\n-ley\n+c\n  face %F0%9F\n-%99%82\n+%A4%A9\n , your \n+deva\n s\n+t\n a\n+te\n d face \n-%E2\n+%F0%9F\n %98\n-%B9%EF%B8%8F\n+%AD\n , an\n@@ -338,53 +338,60 @@\n our \n-ang\n+utte\n r\n+l\n y \n+confused \n face %F0%9F\n-%98%A0\n+%A4%AF\n . But \n-w\n+th\n a\n-i\n t\n-, there\n 's \n-m\n+n\n o\n-re\n+t all\n ! %F0%9F%A4\n-%A9\n+%94\n  We'\n@@ -411,20 +411,14 @@\n ome \n-more comp\n+subt\n le\n-x\n  emo\n@@ -435,78 +435,15 @@\n  %F0%9F%98\n-%8D, %F0%9F%A4%A4, and %F0%9F%9A%80. And let's not forget about the classics: %F0%9F%98%89\n+%90\n , %F0%9F\n-%91%8D\n+%99%83\n , an\n@@ -451,6 +451,6 @@\n  %F0%9F%91\n-%8F\n+%80\n .\n

    Ok(patch_txt)
}
source

pub fn patch_to_text<T: DType>(&self, patches: &Patches<T>) -> String

Reduces an array of patch objects to a block of text which looks extremely similar to the standard GNU diff/patch format. This text may be stored or transmitted.

§Example

let dmp = DiffMatchPatch::new();

// Making patches from source and edited text - both in `Efficient` and `Compat` mode
let patches = dmp.patch_make::<Compat>(PatchInput::new_text_text("Apples are fruit!", "Bananas are also fruit!"))?;
let patch_to_text = dmp.patch_to_text(&patches);

// Prints patches in GNU diff/ patch format
// You can use this format for transmission and/ or storage.
println!("{patch_to_text}");

Check out the diff_to_delta and diff_from_delta methods for a more compact way of representing diffs.

Examples found in repository?
examples/compat.rs (line 34)
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
fn at_source() -> Result<String, Error> {
    // initializing the module
    let dmp = DiffMatchPatch::new();

    // create a list of diffs
    let diffs = dmp.diff_main::<Efficient>(TXT_OLD, TXT_NEW)?;

    // Now, we are going to create a list of `patches` to be applied to the old text to get the new text
    let patches = dmp.patch_make(PatchInput::new_diffs(&diffs))?;

    // in the real world you are going to transmit or store this diff serialized to undiff format to be consumed or used somewhere elese
    let patch_txt = dmp.patch_to_text(&patches);

    // lets see how our patches look
    println!("{patch_txt:?}");
    // You should see something like this
    // @@ -22,225 +22,250 @@\n f a \n-m\n+carto\n o\n-der\n n \n-Major-Ge\n+i\n n\n-er\n+dividu\n al,%0A\n-I've\n+My\n  \n-i\n+a\n n\n-for\n+i\n mation\n+'s\n  \n-veget\n+comic\n a\n-b\n l\n-e\n , \n-a\n+u\n n\n-im\n+usu\n al, and \n+whi\n m\n+s\n i\n-ner\n+c\n al,%0AI\n+'m\n  \n-know \n+qui\n t\n-h\n e \n-kings of Engl\n a\n-n\n d\n-,\n+ept\n  a\n+t fu\n n\n-d\n+ny\n  \n-I\n+gags,\n  \n-qu\n+c\n o\n-t\n+m\n e\n+dic\n  the\n+ory\n  \n-fights\n+I\n  h\n-isto\n+ave \n r\n-ic\n+e\n a\n-l\n+d\n ,%0AFrom \n-M\n+wicked puns \n a\n-ra\n+nd s\n t\n-h\n+upid j\n o\n-n\n+kes\n  to \n-W\n+anvils th\n at\n-e\n+ d\n r\n-l\n o\n+p \n o\n-, i\n n \n+y\n o\n-rde\n+u\n r \n-cat\n+h\n e\n-goric\n a\n-l\n+d\n .%0A%0A\n-L\n+Now, l\n et's \n-sta\n+explo\n r\n-t with\n+e\n  some \n-bas\n+emot\n i\n-c\n+onal extreme\n s %F0%9F\n-%98\n+%8C\n %8A. W\n@@ -282,55 +282,53 @@\n our \n+ec\n sta\n-ndard sm\n+t\n i\n-ley\n+c\n  face %F0%9F\n-%99%82\n+%A4%A9\n , your \n+deva\n s\n+t\n a\n+te\n d face \n-%E2\n+%F0%9F\n %98\n-%B9%EF%B8%8F\n+%AD\n , an\n@@ -338,53 +338,60 @@\n our \n-ang\n+utte\n r\n+l\n y \n+confused \n face %F0%9F\n-%98%A0\n+%A4%AF\n . But \n-w\n+th\n a\n-i\n t\n-, there\n 's \n-m\n+n\n o\n-re\n+t all\n ! %F0%9F%A4\n-%A9\n+%94\n  We'\n@@ -411,20 +411,14 @@\n ome \n-more comp\n+subt\n le\n-x\n  emo\n@@ -435,78 +435,15 @@\n  %F0%9F%98\n-%8D, %F0%9F%A4%A4, and %F0%9F%9A%80. And let's not forget about the classics: %F0%9F%98%89\n+%90\n , %F0%9F\n-%91%8D\n+%99%83\n , an\n@@ -451,6 +451,6 @@\n  %F0%9F%91\n-%8F\n+%80\n .\n

    Ok(patch_txt)
}
More examples
Hide additional examples
examples/efficiency.rs (line 41)
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
fn at_source() -> Result<String, Error> {
    // initializing the module
    let dmp = DiffMatchPatch::new();

    // create a list of diffs
    let diffs = dmp.diff_main::<Efficient>(TXT_OLD, TXT_NEW)?;

    // Now, we are going to create a list of `patches` to be applied to the old text to get the new text
    let patches = dmp.patch_make(PatchInput::new_diffs(&diffs))?;

    // in the real world you are going to transmit or store this diff serialized to undiff format to be consumed or used somewhere elese
    let patch_txt = dmp.patch_to_text(&patches);

    // lets see how our patches look
    println!("{patch_txt:?}");
    // You should see something like this
    // @@ -22,225 +22,250 @@\n f a \n-m\n+carto\n o\n-der\n n \n-Major-Ge\n+i\n n\n-er\n+dividu\n al,%0A\n-I've\n+My\n  \n-i\n+a\n n\n-for\n+i\n mation\n+'s\n  \n-veget\n+comic\n a\n-b\n l\n-e\n , \n-a\n+u\n n\n-im\n+usu\n al, and \n+whi\n m\n+s\n i\n-ner\n+c\n al,%0AI\n+'m\n  \n-know \n+qui\n t\n-h\n e \n-kings of Engl\n a\n-n\n d\n-,\n+ept\n  a\n+t fu\n n\n-d\n+ny\n  \n-I\n+gags,\n  \n-qu\n+c\n o\n-t\n+m\n e\n+dic\n  the\n+ory\n  \n-fights\n+I\n  h\n-isto\n+ave \n r\n-ic\n+e\n a\n-l\n+d\n ,%0AFrom \n-M\n+wicked puns \n a\n-ra\n+nd s\n t\n-h\n+upid j\n o\n-n\n+kes\n  to \n-W\n+anvils th\n at\n-e\n+ d\n r\n-l\n o\n+p \n o\n-, i\n n \n+y\n o\n-rde\n+u\n r \n-cat\n+h\n e\n-goric\n a\n-l\n+d\n .%0A%0A\n-L\n+Now, l\n et's \n-sta\n+explo\n r\n-t with\n+e\n  some \n-bas\n+emot\n i\n-c\n+onal extreme\n s %F0%9F\n-%98\n+%8C\n %8A. W\n@@ -282,55 +282,53 @@\n our \n+ec\n sta\n-ndard sm\n+t\n i\n-ley\n+c\n  face %F0%9F\n-%99%82\n+%A4%A9\n , your \n+deva\n s\n+t\n a\n+te\n d face \n-%E2\n+%F0%9F\n %98\n-%B9%EF%B8%8F\n+%AD\n , an\n@@ -338,53 +338,60 @@\n our \n-ang\n+utte\n r\n+l\n y \n+confused \n face %F0%9F\n-%98%A0\n+%A4%AF\n . But \n-w\n+th\n a\n-i\n t\n-, there\n 's \n-m\n+n\n o\n-re\n+t all\n ! %F0%9F%A4\n-%A9\n+%94\n  We'\n@@ -411,20 +411,14 @@\n ome \n-more comp\n+subt\n le\n-x\n  emo\n@@ -435,78 +435,15 @@\n  %F0%9F%98\n-%8D, %F0%9F%A4%A4, and %F0%9F%9A%80. And let's not forget about the classics: %F0%9F%98%89\n+%90\n , %F0%9F\n-%91%8D\n+%99%83\n , an\n@@ -451,6 +451,6 @@\n  %F0%9F%91\n-%8F\n+%80\n .\n

    Ok(patch_txt)
}
source

pub fn patch_from_text<T: DType>(&self, text: &str) -> Result<Patches<T>, Error>

Parses a block of text (which was presumably created by the patch_to_text method) and returns an array of patch objects.

§Example

let dmp = DiffMatchPatch::new();

// Making patches from source and edited text - both in `Efficient` and `Compat` mode
let patches = dmp.patch_make::<Compat>(PatchInput::new_text_text("Apples are fruit!", "Bananas are also fruit!"))?;
let patch_to_text = dmp.patch_to_text(&patches);

// let's create patches back from text
let patches_recreated = dmp.patch_from_text::<Compat>(&patch_to_text)?;

// Now you can `patch_apply` the `patches_recreated` to your source text
Examples found in repository?
examples/compat.rs (line 49)
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
fn at_destination(patches: &str) -> Result<(), Error> {
    // initializing the module
    let dmp = DiffMatchPatch::new();

    // lets recreate the diffs from patches
    let patches = dmp.patch_from_text::<Efficient>(patches)?;

    // Now, lets apply these patches to the `old_txt` which is the original to get the new text
    let (new_txt, ops) = dmp.patch_apply(&patches, TXT_OLD)?;

    // Lets print out if the ops succeeded or not
    ops.iter()
        .for_each(|&o| println!("{}", if o { "OK" } else { "FAIL" }));

    // If everything goes as per plan you should see
    // OK
    // OK
    // ... and so on

    // lets check out if our `NEW_TXT` (presumably the edited one)
    if new_txt != TXT_NEW {
        return Err(Error::InvalidInput);
    }

    println!("Wallah! Patch applied successfully!");

    Ok(())
}
More examples
Hide additional examples
examples/efficiency.rs (line 56)
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
fn at_destination(patches: &str) -> Result<(), Error> {
    // initializing the module
    let dmp = DiffMatchPatch::new();

    // lets recreate the diffs from patches
    let patches = dmp.patch_from_text::<Efficient>(patches)?;

    // Now, lets apply these patches to the `old_txt` which is the original to get the new text
    let (new_txt, ops) = dmp.patch_apply(&patches, TXT_OLD)?;

    // Lets print out if the ops succeeded or not
    ops.iter()
        .for_each(|&o| println!("{}", if o { "OK" } else { "FAIL" }));

    // If everything goes as per plan you should see
    // OK
    // OK
    // ... and so on

    // lets check out if our `NEW_TXT` (presumably the edited one)
    if new_txt != TXT_NEW {
        return Err(Error::InvalidInput);
    }

    println!("Wallah! Patch applied successfully!");

    Ok(())
}
source

pub fn diff_to_delta<T: DType>( &self, diffs: &[Diff<T>], ) -> Result<String, Error>

Crush the diff into an encoded string which describes the operations required to transform text_old into text_new. E.g. =3\t-2\t+ing -> Keep 3 chars, delete 2 chars, insert ‘ing’. Operations are tab-separated. Inserted text is escaped using %xx notation.

§Example

let dmp = DiffMatchPatch::new();

// let's create some diffs
let diffs = dmp.diff_main::<Compat>("The old house and the new dog!", "The old man and the new dog!")?;
// now, you can create a `delta` string which can be used to re-create the diffs
let delta = dmp.diff_to_delta(&diffs)?;
println!("{delta:?}");
// You should see something like the following
// "=8\t-5\t+man\t=17"

// now you can use the `diff_from_delta()` to recover the diffs
let diffs_later = dmp.diff_from_delta::<Compat>("The old house and the new dog!", &delta);
Examples found in repository?
examples/delta.rs (line 32)
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
fn at_source() -> Result<String, Error> {
    // initializing the module
    let dmp = DiffMatchPatch::new();

    // create a list of diffs
    let diffs = dmp.diff_main::<Efficient>(TXT_OLD, TXT_NEW)?;

    // When dealing with large text blocks and if you want to transmit this diff, `delta` will give you a minimal over the air representation of diffs
    // We'll use this delta string to recreate `diffs` at the destination and then create patches to apply
    let delta = dmp.diff_to_delta(&diffs)?;

    // lets see how our delta looks
    println!("{delta:?}");
    // You should see something like this
    // =25\t-1\t+carto\t=1\t-3\t=2\t-8\t+i\t=1\t-2\t+dividu\t=4\t-4\t+My\t=1\t-1\t+a\t=1\t-3\t+i\t=6\t+'s\t=1\t-5\t+comic\t=1\t-1\t=1\t-1\t=2\t-1\t+u\t=1\t-2\t+usu\t=8\t+whi\t=1\t+s\t=1\t-3\t+c\t=5\t+'m\t=1\t-5\t+qui\t=1\t-1\t=2\t-13\t=1\t-1\t=1\t-1\t+ept\t=2\t+t fu\t=1\t-1\t+ny\t=1\t-1\t+gags,\t=1\t-2\t+c\t=1\t-1\t+m\t=1\t+dic\t=4\t+ory\t=1\t-6\t+I\t=2\t-4\t+ave \t=1\t-2\t+e\t=1\t-1\t+d\t=7\t-1\t+wicked puns \t=1\t-2\t+nd s\t=1\t-1\t+upid j\t=1\t-1\t+kes\t=4\t-1\t+anvils th\t=2\t-1\t+ d\t=1\t-1\t=1\t+p \t=1\t-3\t=2\t+y\t=1\t-3\t+u\t=2\t-3\t+h\t=1\t-5\t=1\t-1\t+d\t=3\t-1\t+Now, l\t=5\t-3\t+explo\t=1\t-6\t+e\t=6\t-3\t+emot\t=1\t-1\t+onal extreme\t=4\t-1\t+%8C\t=18\t+ec\t=3\t-8\t+t\t=1\t-3\t+c\t=8\t-2\t+%A4%A9\t=7\t+deva\t=1\t+t\t=1\t+te\t=7\t-1\t+%F0%9F\t=1\t-4\t+%AD\t=11\t-3\t+utte\t=1\t+l\t=2\t+confused \t=7\t-2\t+%A4%AF\t=6\t-1\t+th\t=1\t-1\t=1\t-7\t=3\t-1\t+n\t=1\t-2\t+t all\t=5\t-1\t+%94\t=21\t-9\t+subt\t=2\t-1\t=18\t-64\t+%90\t=4\t-2\t+%99%83\t=9\t-1\t+%80\t=1

    Ok(delta)
}
source

pub fn diff_from_delta<T: DType>( &self, old: &str, delta: &str, ) -> Result<Vec<Diff<T>>, Error>

Given the original text old, and an encoded string which describes the operations required to transform text1 into text2, compute the full diff.

§Example

let dmp = DiffMatchPatch::new();

// let's create some diffs
let diffs = dmp.diff_main::<Compat>("The old house and the new dog!", "The old man and the new dog!")?;
// now, you can create a `delta` string which can be used to re-create the diffs
let delta = dmp.diff_to_delta(&diffs)?;
println!("{delta:?}");
// You should see something like the following
// "=8\t-5\t+man\t=17"

// now you can use the `diff_from_delta()` to recover the diffs
let diffs_later = dmp.diff_from_delta::<Compat>("The old house and the new dog!", &delta);
// Now, you can use these diffs to apply patches to the source text
let patches = dmp.patch_make(PatchInput::new_text_diffs("The old house and the new dog!", &diffs))?;
let (new_from_old, _) = dmp.patch_apply(&patches, "The old house and the new dog!")?;


assert_eq!("The old man and the new dog!", &new_from_old);
Examples found in repository?
examples/delta.rs (line 47)
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
fn at_destination(delta: &str) -> Result<(), Error> {
    // initializing the module
    let dmp = DiffMatchPatch::new();

    // lets recreate the diffs from the minimal `delta` string
    let delta = dmp.diff_from_delta::<Efficient>(TXT_OLD, delta)?;
    // Additional step of conveting `delta` -> `patches`
    let patches = dmp.patch_make(PatchInput::new_diffs(&delta))?;

    // Now, lets apply these patches to the `old_txt` which is the original to get the new text
    let (new_txt, ops) = dmp.patch_apply(&patches, TXT_OLD)?;

    // Lets print out if the ops succeeded or not
    ops.iter()
        .for_each(|&o| println!("{}", if o { "OK" } else { "FAIL" }));

    // If everything goes as per plan you should see
    // OK
    // OK
    // ... and so on

    // lets check out if our `NEW_TXT` (presumably the edited one)
    if new_txt != TXT_NEW {
        return Err(Error::InvalidInput);
    }

    println!("Wallah! Patch applied successfully!");

    Ok(())
}
source

pub fn patch_apply<T: DType>( &self, patches: &Patches<T>, source_txt: &str, ) -> Result<(String, Vec<bool>), Error>

Applies a list of patches to source_txt. The first element of the return value is the newly patched text. The second element is an array of true/false values indicating which of the patches were successfully applied. [Note that this second element is not too useful since large patches may get broken up internally, resulting in a longer results list than the input with no way to figure out which patch succeeded or failed. A more informative API is in development.]

The match_distance and match_threshold properties are used to evaluate patch application on text which does not match exactly. In addition, the DiffMatchPatch.delete_threshold property determines how closely the text within a major (~64 character) delete needs to match the expected text. If delete_threshold is closer to 0, then the deleted text must match the expected text more closely. If delete_threshold is closer to 1, then the deleted text may contain anything. In most use cases delete_threshold should just be set to the same value as match_threshold. Both values default to 0.5

§Example
§Example

let dmp = DiffMatchPatch::new();

// You can also make patches from the old and new string directly
let patches = dmp.patch_make::<Efficient>(PatchInput::new_text_text("Apples are a fruit.", "Bananas are also fruit"))?;
let (new_from_old, _) = dmp.patch_apply(&patches, "Apples are a fruit.")?;
assert_eq!("Bananas are also fruit", new_from_old);

// Or, create some diffs in `Efficient` or `Compact` mode
let diffs = dmp.diff_main::<Efficient>("Apples are a fruit.", "Bananas are also fruit")?;
// Now, lets convert the diffs to a bunch of patches - you can use an existing set of diffs to create patches
let patches = dmp.patch_make(PatchInput::new_diffs(&diffs))?;
let (new_from_old, _) = dmp.patch_apply(&patches, "Apples are a fruit.")?;
assert_eq!("Bananas are also fruit", new_from_old);

// Or, from the source texts and diffs
let patches = dmp.patch_make(PatchInput::new_text_diffs("Apples are a fruit.", &diffs))?;
let (new_from_old, _) = dmp.patch_apply(&patches, "Apples are a fruit.")?;
assert_eq!("Bananas are also fruit", new_from_old);
Examples found in repository?
examples/compat.rs (line 52)
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
fn at_destination(patches: &str) -> Result<(), Error> {
    // initializing the module
    let dmp = DiffMatchPatch::new();

    // lets recreate the diffs from patches
    let patches = dmp.patch_from_text::<Efficient>(patches)?;

    // Now, lets apply these patches to the `old_txt` which is the original to get the new text
    let (new_txt, ops) = dmp.patch_apply(&patches, TXT_OLD)?;

    // Lets print out if the ops succeeded or not
    ops.iter()
        .for_each(|&o| println!("{}", if o { "OK" } else { "FAIL" }));

    // If everything goes as per plan you should see
    // OK
    // OK
    // ... and so on

    // lets check out if our `NEW_TXT` (presumably the edited one)
    if new_txt != TXT_NEW {
        return Err(Error::InvalidInput);
    }

    println!("Wallah! Patch applied successfully!");

    Ok(())
}
More examples
Hide additional examples
examples/efficiency.rs (line 59)
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
fn at_destination(patches: &str) -> Result<(), Error> {
    // initializing the module
    let dmp = DiffMatchPatch::new();

    // lets recreate the diffs from patches
    let patches = dmp.patch_from_text::<Efficient>(patches)?;

    // Now, lets apply these patches to the `old_txt` which is the original to get the new text
    let (new_txt, ops) = dmp.patch_apply(&patches, TXT_OLD)?;

    // Lets print out if the ops succeeded or not
    ops.iter()
        .for_each(|&o| println!("{}", if o { "OK" } else { "FAIL" }));

    // If everything goes as per plan you should see
    // OK
    // OK
    // ... and so on

    // lets check out if our `NEW_TXT` (presumably the edited one)
    if new_txt != TXT_NEW {
        return Err(Error::InvalidInput);
    }

    println!("Wallah! Patch applied successfully!");

    Ok(())
}
examples/delta.rs (line 52)
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
fn at_destination(delta: &str) -> Result<(), Error> {
    // initializing the module
    let dmp = DiffMatchPatch::new();

    // lets recreate the diffs from the minimal `delta` string
    let delta = dmp.diff_from_delta::<Efficient>(TXT_OLD, delta)?;
    // Additional step of conveting `delta` -> `patches`
    let patches = dmp.patch_make(PatchInput::new_diffs(&delta))?;

    // Now, lets apply these patches to the `old_txt` which is the original to get the new text
    let (new_txt, ops) = dmp.patch_apply(&patches, TXT_OLD)?;

    // Lets print out if the ops succeeded or not
    ops.iter()
        .for_each(|&o| println!("{}", if o { "OK" } else { "FAIL" }));

    // If everything goes as per plan you should see
    // OK
    // OK
    // ... and so on

    // lets check out if our `NEW_TXT` (presumably the edited one)
    if new_txt != TXT_NEW {
        return Err(Error::InvalidInput);
    }

    println!("Wallah! Patch applied successfully!");

    Ok(())
}

Trait Implementations§

source§

impl Default for DiffMatchPatch

source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.