1pub mod greedy;
2pub mod onepass;
3pub mod correcting;
4
5use crate::types::{Algorithm, Command, DiffOptions};
6
7pub(crate) fn print_command_stats(commands: &[Command]) {
9 let mut copy_lens: Vec<usize> = Vec::new();
10 let mut total_copy: usize = 0;
11 let mut total_add: usize = 0;
12 let mut num_copies: usize = 0;
13 let mut num_adds: usize = 0;
14 for cmd in commands {
15 match cmd {
16 Command::Copy { length, .. } => {
17 total_copy += length;
18 num_copies += 1;
19 copy_lens.push(*length);
20 }
21 Command::Add { data } => {
22 total_add += data.len();
23 num_adds += 1;
24 }
25 }
26 }
27 let total_out = total_copy + total_add;
28 let copy_pct = if total_out > 0 {
29 total_copy as f64 / total_out as f64 * 100.0
30 } else {
31 0.0
32 };
33 eprintln!(
34 " result: {} copies ({} bytes), {} adds ({} bytes)\n \
35 result: copy coverage {:.1}%, output {} bytes",
36 num_copies, total_copy, num_adds, total_add, copy_pct, total_out
37 );
38 if !copy_lens.is_empty() {
39 copy_lens.sort();
40 let mean = total_copy as f64 / copy_lens.len() as f64;
41 let median = copy_lens[copy_lens.len() / 2];
42 eprintln!(
43 " copies: {} regions, min={} max={} mean={:.1} median={} bytes",
44 copy_lens.len(),
45 copy_lens.first().unwrap(),
46 copy_lens.last().unwrap(),
47 mean,
48 median
49 );
50 }
51}
52
53pub fn diff(
55 algorithm: Algorithm,
56 r: &[u8],
57 v: &[u8],
58 opts: &DiffOptions,
59) -> Vec<Command> {
60 match algorithm {
61 Algorithm::Greedy => greedy::diff_greedy(r, v, opts),
62 Algorithm::Onepass => onepass::diff_onepass(r, v, opts),
63 Algorithm::Correcting => correcting::diff_correcting(r, v, opts),
64 }
65}
66
67pub fn diff_default(algorithm: Algorithm, r: &[u8], v: &[u8]) -> Vec<Command> {
69 diff(algorithm, r, v, &DiffOptions::default())
70}