my fork of dmp
-rw-r--r--Cargo.toml14
-rw-r--r--examples/compat.rs81
-rw-r--r--examples/delta.rs81
-rw-r--r--examples/efficiency.rs88
-rw-r--r--src/dmp.rs7
-rw-r--r--src/lib.rs4
-rw-r--r--src/patch_input.rs21
-rw-r--r--testdata/txt_new_small.txt6
-rw-r--r--testdata/txt_old_small.txt6
-rw-r--r--tests/test.rs65
10 files changed, 355 insertions, 18 deletions
diff --git a/Cargo.toml b/Cargo.toml
index eab880c..33b4652 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "diff-match-patch-rs"
-version = "0.1.0-beta.2"
+version = "0.1.0-beta.3"
edition = "2021"
authors = ["Anubhab Bandyopadhyay"]
repository = "https://github.com/AnubhabB/diff-match-patch-rs.git"
@@ -26,12 +26,8 @@ criterion = "0"
name = "diff"
harness = false
-# [[bench]]
-# name = "bisect"
-# harness = false
+[[example]]
+name = "efficiency"
-# [profile.bench]
-# debug = true
-
-# [profile.release]
-# debug = true \ No newline at end of file
+[[example]]
+name = "compat" \ No newline at end of file
diff --git a/examples/compat.rs b/examples/compat.rs
new file mode 100644
index 0000000..691e9f9
--- /dev/null
+++ b/examples/compat.rs
@@ -0,0 +1,81 @@
+use diff_match_patch_rs::{DiffMatchPatch, Efficient, Error, PatchInput};
+
+/// An example flow of the effitient mode
+/// This demo will cover creating a diff of two texts and then `patching` it back to get the original text
+
+// This is the source text
+const TXT_OLD: &str = "I am the very model of a modern Major-General,
+I've information vegetable, animal, and mineral,
+I know the kings of England, and I quote the fights historical,
+From Marathon to Waterloo, in order categorical.
+
+Let's start with some basics 😊. We've got your standard smiley face 🙂, your sad face â˜šī¸, and your angry face 😠. But wait, there's more! 🤩 We've also got some more complex emotions like 😍, 🤤, and 🚀. And let's not forget about the classics: 😉, 👍, and 👏.";
+
+// Let's assume this to be the text that was editted from the source text
+const TXT_NEW: &str = "I am the very model of a cartoon individual,
+My animation's comical, unusual, and whimsical,
+I'm quite adept at funny gags, comedic theory I have read,
+From wicked puns and stupid jokes to anvils that drop on your head.
+
+Now, let's explore some emotional extremes 🌊. We've got your ecstatic face 🤩, your devastated face 😭, and your utterly confused face đŸ¤¯. But that's not all! 🤔 We've also got some subtle emotions like 😐, 🙃, and 👀.";
+
+// An example of a function that creates a diff and returns a set of patches serialized
+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(())
+}
+
+fn main() -> Result<(), Error> {
+ // At the source of diff where the old text is being edited we'll create a set of patches
+ let patches = at_source()?;
+
+ // We'll send this diff to some destination e.g. db or the client where these changes are going to be applied
+
+ // The destination will receive the patch string and will apply the patches to recreate the edits
+ at_destination(&patches)
+}
diff --git a/examples/delta.rs b/examples/delta.rs
new file mode 100644
index 0000000..691e9f9
--- /dev/null
+++ b/examples/delta.rs
@@ -0,0 +1,81 @@
+use diff_match_patch_rs::{DiffMatchPatch, Efficient, Error, PatchInput};
+
+/// An example flow of the effitient mode
+/// This demo will cover creating a diff of two texts and then `patching` it back to get the original text
+
+// This is the source text
+const TXT_OLD: &str = "I am the very model of a modern Major-General,
+I've information vegetable, animal, and mineral,
+I know the kings of England, and I quote the fights historical,
+From Marathon to Waterloo, in order categorical.
+
+Let's start with some basics 😊. We've got your standard smiley face 🙂, your sad face â˜šī¸, and your angry face 😠. But wait, there's more! 🤩 We've also got some more complex emotions like 😍, 🤤, and 🚀. And let's not forget about the classics: 😉, 👍, and 👏.";
+
+// Let's assume this to be the text that was editted from the source text
+const TXT_NEW: &str = "I am the very model of a cartoon individual,
+My animation's comical, unusual, and whimsical,
+I'm quite adept at funny gags, comedic theory I have read,
+From wicked puns and stupid jokes to anvils that drop on your head.
+
+Now, let's explore some emotional extremes 🌊. We've got your ecstatic face 🤩, your devastated face 😭, and your utterly confused face đŸ¤¯. But that's not all! 🤔 We've also got some subtle emotions like 😐, 🙃, and 👀.";
+
+// An example of a function that creates a diff and returns a set of patches serialized
+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(())
+}
+
+fn main() -> Result<(), Error> {
+ // At the source of diff where the old text is being edited we'll create a set of patches
+ let patches = at_source()?;
+
+ // We'll send this diff to some destination e.g. db or the client where these changes are going to be applied
+
+ // The destination will receive the patch string and will apply the patches to recreate the edits
+ at_destination(&patches)
+}
diff --git a/examples/efficiency.rs b/examples/efficiency.rs
new file mode 100644
index 0000000..dd26948
--- /dev/null
+++ b/examples/efficiency.rs
@@ -0,0 +1,88 @@
+use diff_match_patch_rs::{DiffMatchPatch, Efficient, Error, PatchInput};
+
+/// An example flow of the effitient mode
+/// This demo will cover creating a diff of two texts and then `patching` it back to get the original text
+///
+/// NOTE:
+/// This is the `efficiency` mode, here we apply `Diff` and `Patch` operations in `raw bytes &[u8]`.
+/// `Efficiency mode` is called by using `dmp.diff_main::<Efficient>()` or `dmp.patch_from_text::<Efficient>()` APIs
+/// `Efficiency mode` is not compatible with other libraries or implementations of `diff-match-patch`.
+/// Use `efficiency` mode ONLY if you are using this `crate` across your stack
+/// If you want a standardized implementation (working across libraries), use `Compat` mode istead
+
+// This is the source text
+const TXT_OLD: &str = "I am the very model of a modern Major-General,
+I've information vegetable, animal, and mineral,
+I know the kings of England, and I quote the fights historical,
+From Marathon to Waterloo, in order categorical.
+
+Let's start with some basics 😊. We've got your standard smiley face 🙂, your sad face â˜šī¸, and your angry face 😠. But wait, there's more! 🤩 We've also got some more complex emotions like 😍, 🤤, and 🚀. And let's not forget about the classics: 😉, 👍, and 👏.";
+
+// Let's assume this to be the text that was editted from the source text
+const TXT_NEW: &str = "I am the very model of a cartoon individual,
+My animation's comical, unusual, and whimsical,
+I'm quite adept at funny gags, comedic theory I have read,
+From wicked puns and stupid jokes to anvils that drop on your head.
+
+Now, let's explore some emotional extremes 🌊. We've got your ecstatic face 🤩, your devastated face 😭, and your utterly confused face đŸ¤¯. But that's not all! 🤔 We've also got some subtle emotions like 😐, 🙃, and 👀.";
+
+// An example of a function that creates a diff and returns a set of patches serialized
+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(())
+}
+
+fn main() -> Result<(), Error> {
+ // At the source of diff where the old text is being edited we'll create a set of patches
+ let patches = at_source()?;
+
+ // We'll send this diff to some destination e.g. db or the client where these changes are going to be applied
+
+ // The destination will receive the patch string and will apply the patches to recreate the edits
+ at_destination(&patches)
+}
diff --git a/src/dmp.rs b/src/dmp.rs
index ef67d74..9177707 100644
--- a/src/dmp.rs
+++ b/src/dmp.rs
@@ -3,7 +3,7 @@ use std::{char, collections::HashMap, fmt::Display};
use chrono::{NaiveTime, TimeDelta, Utc};
-use crate::{errors::Error, DType};
+use crate::{errors::Error, DType, PatchInput};
/// Enum representing the different ops of diff
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
@@ -2180,11 +2180,6 @@ impl<T: DType> Patch<T> {
&self.diffs[..]
}
}
-pub enum PatchInput<'a, T: DType> {
- Texts(&'a str, &'a str),
- Diffs(&'a [Diff<T>]),
- TextDiffs(&'a str, &'a [Diff<T>]),
-}
pub type Patches<T> = Vec<Patch<T>>;
diff --git a/src/lib.rs b/src/lib.rs
index b8394c9..cf6c8ed 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -2,9 +2,11 @@
pub mod dmp;
pub mod errors;
+pub mod patch_input;
pub mod traits;
-pub use dmp::{DiffMatchPatch, Ops, Patch, PatchInput, Patches};
+pub use dmp::{DiffMatchPatch, Ops, Patch, Patches};
pub use errors::Error;
+pub use patch_input::PatchInput;
pub(crate) use traits::DType;
pub use traits::{Compat, Efficient};
diff --git a/src/patch_input.rs b/src/patch_input.rs
new file mode 100644
index 0000000..824bfc8
--- /dev/null
+++ b/src/patch_input.rs
@@ -0,0 +1,21 @@
+use crate::{dmp::Diff, DType};
+
+pub enum PatchInput<'a, T: DType> {
+ Texts(&'a str, &'a str),
+ Diffs(&'a [Diff<T>]),
+ TextDiffs(&'a str, &'a [Diff<T>]),
+}
+
+impl<'a, T: DType> PatchInput<'a, T> {
+ pub fn new_text_text(old: &'a str, new: &'a str) -> Self {
+ Self::Texts(old, new)
+ }
+
+ pub fn new_diffs(diffs: &'a [Diff<T>]) -> Self {
+ Self::Diffs(diffs)
+ }
+
+ pub fn new_text_diffs(old: &'a str, diffs: &'a [Diff<T>]) -> Self {
+ Self::TextDiffs(old, diffs)
+ }
+}
diff --git a/testdata/txt_new_small.txt b/testdata/txt_new_small.txt
new file mode 100644
index 0000000..4ff6aed
--- /dev/null
+++ b/testdata/txt_new_small.txt
@@ -0,0 +1,6 @@
+I am the very model of a cartoon individual,
+My animation's comical, unusual, and whimsical,
+I'm quite adept at funny gags, comedic theory I have read,
+From wicked puns and stupid jokes to anvils that drop on your head.
+
+Now, let's explore some emotional extremes 🌊. We've got your ecstatic face 🤩, your devastated face 😭, and your utterly confused face đŸ¤¯. But that's not all! 🤔 We've also got some subtle emotions like 😐, 🙃, and 👀. \ No newline at end of file
diff --git a/testdata/txt_old_small.txt b/testdata/txt_old_small.txt
new file mode 100644
index 0000000..4aac022
--- /dev/null
+++ b/testdata/txt_old_small.txt
@@ -0,0 +1,6 @@
+I am the very model of a modern Major-General,
+I've information vegetable, animal, and mineral,
+I know the kings of England, and I quote the fights historical,
+From Marathon to Waterloo, in order categorical.
+
+Let's start with some basics 😊. We've got your standard smiley face 🙂, your sad face â˜šī¸, and your angry face 😠. But wait, there's more! 🤩 We've also got some more complex emotions like 😍, 🤤, and 🚀. And let's not forget about the classics: 😉, 👍, and 👏. \ No newline at end of file
diff --git a/tests/test.rs b/tests/test.rs
index e4dc6a6..a05ee1c 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -678,6 +678,35 @@ fn test_diff_delta() -> Result<(), Error> {
// Generates error (19 != 18).
assert!(DiffMatchPatch::from_delta(&txt_old[1..], &delta).is_err());
+ let diffs = vec![
+ Diff::equal(&"jump".chars().collect::<Vec<_>>()[..]),
+ Diff::delete(&['s']),
+ Diff::insert(&['e', 'd']),
+ Diff::equal(&" over ".chars().collect::<Vec<_>>()[..]),
+ Diff::delete(&"the".chars().collect::<Vec<_>>()[..]),
+ Diff::insert(&['a']),
+ Diff::equal(&" lazy".chars().collect::<Vec<_>>()[..]),
+ Diff::insert(&"old dog".chars().collect::<Vec<_>>()[..]),
+ ];
+ let txt_old = &"jumps over the lazy".chars().collect::<Vec<_>>()[..];
+ assert_eq!(txt_old, DiffMatchPatch::diff_text_old(&diffs));
+
+ let delta = DiffMatchPatch::to_delta(&diffs);
+ assert_eq!(
+ &"=4\t-1\t+ed\t=6\t-3\t+a\t=5\t+old dog"
+ .chars()
+ .collect::<Vec<_>>()[..],
+ &delta
+ );
+ // Convert delta string into a diff.
+ assert_eq!(diffs, DiffMatchPatch::from_delta(txt_old, &delta)?);
+
+ // Generates error (19 != 20).
+ assert!(DiffMatchPatch::from_delta(&[txt_old, &['+']].concat()[..], &delta).is_err());
+
+ // Generates error (19 != 18).
+ assert!(DiffMatchPatch::from_delta(&txt_old[1..], &delta).is_err());
+
// Test deltas with special characters.
let diffs = vec![
Diff::equal("\u{0680} \x00 \t %".as_bytes()),
@@ -692,6 +721,27 @@ fn test_diff_delta() -> Result<(), Error> {
// Convert delta string into a diff.
assert_eq!(&diffs, &DiffMatchPatch::from_delta(&txt_old, &delta)?);
+ let diffs = vec![
+ Diff::equal(&"\u{0680} \x00 \t %".chars().collect::<Vec<_>>()[..]),
+ Diff::delete(&"\u{0681} \x01 \n ^".chars().collect::<Vec<_>>()[..]),
+ Diff::insert(&"\u{0682} \x02 \\ |".chars().collect::<Vec<_>>()[..]),
+ ];
+ let txt_old = DiffMatchPatch::diff_text_old(&diffs);
+ assert_eq!(
+ &"\u{0680} \x00 \t %\u{0681} \x01 \n ^"
+ .chars()
+ .collect::<Vec<_>>()[..],
+ txt_old
+ );
+ let delta = DiffMatchPatch::to_delta(&diffs);
+
+ assert_eq!(
+ &"=7\t-7\t+%DA%82 %02 %5C %7C".chars().collect::<Vec<_>>()[..],
+ &delta[..]
+ );
+ // Convert delta string into a diff.
+ assert_eq!(&diffs, &DiffMatchPatch::from_delta(&txt_old, &delta)?);
+
// Verify pool of unchanged characters.
let diffs = vec![Diff::insert(
"A-Z a-z 0-9 - _ . ! ~ * ' ( ) ; / ? : @ & = + $ , # ".as_bytes(),
@@ -702,14 +752,25 @@ fn test_diff_delta() -> Result<(), Error> {
std::str::from_utf8(&txt_new).unwrap()
);
+ let diffs = vec![Diff::insert(
+ &"A-Z a-z 0-9 - _ . ! ~ * ' ( ) ; / ? : @ & = + $ , # "
+ .chars()
+ .collect::<Vec<_>>()[..],
+ )];
+ let txt_new = DiffMatchPatch::diff_text_new(&diffs);
+ assert_eq!(
+ "A-Z a-z 0-9 - _ . ! ~ * \' ( ) ; / ? : @ & = + $ , # ",
+ &txt_new.iter().collect::<String>()
+ );
+
let delta = DiffMatchPatch::to_delta(&diffs);
assert_eq!(
"+A-Z a-z 0-9 - _ . ! ~ * \' ( ) ; / ? : @ & = + $ , # ",
- std::str::from_utf8(&delta).unwrap()
+ &delta.iter().collect::<String>()
);
// Convert delta string into a diff.
- assert_eq!(diffs, DiffMatchPatch::from_delta("".as_bytes(), &delta)?);
+ assert_eq!(diffs, DiffMatchPatch::from_delta(&[], &delta)?);
Ok(())
}