diffs/
lib.rs

1//! Various diff (longest common subsequence) algorithms, used in
2//! practice:
3//!
4//! - Myers' diff, in time O((N+M)D) and space O(N+M), where N and M
5//! are the sizes of the old and new version, respectively. See [the
6//! original article by Eugene
7//! W. Myers](http://www.xmailserver.org/diff2.pdf).
8//!
9//! - Patience diff, in time O(N log N + M log M + (N+M)D), and space
10//! O(N+M), which tends to give more human-readable outputs. See [Bram
11//! Cohen's blog post describing
12//! it](https://bramcohen.livejournal.com/73318.html).
13
14mod replace;
15pub use replace::*;
16
17use std::ops::Index;
18
19pub trait DiffAlgorithm {
20    fn diff<S: Index<usize> + ?Sized, T: Index<usize> + ?Sized, D: Diff>(
21        d: &mut D,
22        e: &S,
23        e0: usize,
24        e1: usize,
25        f: &T,
26        f0: usize,
27        f1: usize,
28    ) -> Result<(), D::Error>;
29}
30
31/// Myers' diff algorithm
32pub mod myers;
33/// Patience diff algorithm
34pub mod patience;
35/// Binary diff algorithm
36pub mod bin;
37
38#[cfg(test)]
39mod test;
40
41#[allow(unused_variables)]
42/// A trait for reacting to an edit script from the "old" version to
43/// the "new" version.
44pub trait Diff: Sized {
45    type Error;
46    /// Called when lines with indices `old` (in the old version) and
47    /// `new` (in the new version) start an section equal in both
48    /// versions, of length `len`.
49    fn equal(&mut self, old: usize, new: usize, len: usize) -> Result<(), Self::Error> {
50        Ok(())
51    }
52    /// Called when a section of length `len`, starting at `old`,
53    /// needs to be deleted from the old version.
54    fn delete(&mut self, old: usize, len: usize, new: usize) -> Result<(), Self::Error> {
55        Ok(())
56    }
57    /// Called when a section of the new version, of length `new_len`
58    /// and starting at `new`, needs to be inserted at position `old'.
59    fn insert(&mut self, old: usize, new: usize, new_len: usize) -> Result<(), Self::Error> {
60        Ok(())
61    }
62    /// Called when a section of the old version, starting at index
63    /// `old` and of length `old_len`, needs to be replaced with a
64    /// section of length `new_len`, starting at `new`, of the new
65    /// version.
66    fn replace(
67        &mut self,
68        old: usize,
69        old_len: usize,
70        new: usize,
71        new_len: usize,
72    ) -> Result<(), Self::Error> {
73        self.delete(old, old_len, new)?;
74        self.insert(old, new, new_len)
75    }
76    /// Always called at the end of the algorithm.
77    fn finish(&mut self) -> Result<(), Self::Error> {
78        Ok(())
79    }
80}
81
82impl<'a, D: Diff + 'a> Diff for &'a mut D {
83    type Error = D::Error;
84    fn equal(&mut self, old: usize, new: usize, len: usize) -> Result<(), Self::Error> {
85        (*self).equal(old, new, len)
86    }
87    fn delete(&mut self, old: usize, len: usize, new: usize) -> Result<(), Self::Error> {
88        (*self).delete(old, len, new)
89    }
90
91    fn insert(&mut self, old: usize, new: usize, new_len: usize) -> Result<(), Self::Error> {
92        (*self).insert(old, new, new_len)
93    }
94
95    fn replace(
96        &mut self,
97        old: usize,
98        old_len: usize,
99        new: usize,
100        new_len: usize,
101    ) -> Result<(), Self::Error> {
102        (*self).replace(old, old_len, new, new_len)
103    }
104
105    fn finish(&mut self) -> Result<(), Self::Error> {
106        (*self).finish()
107    }
108}