compiletest/runtest/
compute_diff.rs1use std::collections::VecDeque;
2
3#[derive(Debug, PartialEq)]
4pub enum DiffLine {
5 Context(String),
6 Expected(String),
7 Resulting(String),
8}
9
10#[derive(Debug, PartialEq)]
11pub struct Mismatch {
12 pub line_number: u32,
13 pub lines: Vec<DiffLine>,
14}
15
16impl Mismatch {
17 fn new(line_number: u32) -> Mismatch {
18 Mismatch { line_number, lines: Vec::new() }
19 }
20}
21
22pub fn make_diff(expected: &str, actual: &str, context_size: usize) -> Vec<Mismatch> {
24 let mut line_number = 1;
25 let mut context_queue: VecDeque<&str> = VecDeque::with_capacity(context_size);
26 let mut lines_since_mismatch = context_size + 1;
27 let mut results = Vec::new();
28 let mut mismatch = Mismatch::new(0);
29
30 for result in diff::lines(expected, actual) {
31 match result {
32 diff::Result::Left(s) => {
33 if lines_since_mismatch >= context_size && lines_since_mismatch > 0 {
34 results.push(mismatch);
35 mismatch = Mismatch::new(line_number - context_queue.len() as u32);
36 }
37
38 while let Some(line) = context_queue.pop_front() {
39 mismatch.lines.push(DiffLine::Context(line.to_owned()));
40 }
41
42 mismatch.lines.push(DiffLine::Expected(s.to_owned()));
43 line_number += 1;
44 lines_since_mismatch = 0;
45 }
46 diff::Result::Right(s) => {
47 if lines_since_mismatch >= context_size && lines_since_mismatch > 0 {
48 results.push(mismatch);
49 mismatch = Mismatch::new(line_number - context_queue.len() as u32);
50 }
51
52 while let Some(line) = context_queue.pop_front() {
53 mismatch.lines.push(DiffLine::Context(line.to_owned()));
54 }
55
56 mismatch.lines.push(DiffLine::Resulting(s.to_owned()));
57 lines_since_mismatch = 0;
58 }
59 diff::Result::Both(s, _) => {
60 if context_queue.len() >= context_size {
61 let _ = context_queue.pop_front();
62 }
63
64 if lines_since_mismatch < context_size {
65 mismatch.lines.push(DiffLine::Context(s.to_owned()));
66 } else if context_size > 0 {
67 context_queue.push_back(s);
68 }
69
70 line_number += 1;
71 lines_since_mismatch += 1;
72 }
73 }
74 }
75
76 results.push(mismatch);
77 results.remove(0);
78
79 results
80}
81
82pub(crate) fn write_diff(expected: &str, actual: &str, context_size: usize) -> String {
83 use std::fmt::Write;
84 let mut output = String::new();
85 let diff_results = make_diff(expected, actual, context_size);
86 for result in diff_results {
87 let mut line_number = result.line_number;
88 for line in result.lines {
89 match line {
90 DiffLine::Expected(e) => {
91 writeln!(output, "-\t{}", e).unwrap();
92 line_number += 1;
93 }
94 DiffLine::Context(c) => {
95 writeln!(output, "{}\t{}", line_number, c).unwrap();
96 line_number += 1;
97 }
98 DiffLine::Resulting(r) => {
99 writeln!(output, "+\t{}", r).unwrap();
100 }
101 }
102 }
103 writeln!(output).unwrap();
104 }
105 output
106}