trybuild/
diff.rs

1pub(crate) use self::r#impl::Diff;
2
3pub(crate) enum Render<'a> {
4    Common(&'a str),
5    Unique(&'a str),
6}
7
8#[cfg(all(feature = "diff", not(windows)))]
9mod r#impl {
10    use super::Render;
11    use dissimilar::Chunk;
12    use std::cmp;
13    use std::panic;
14
15    pub(crate) struct Diff<'a> {
16        expected: &'a str,
17        actual: &'a str,
18        diff: Vec<Chunk<'a>>,
19    }
20
21    impl<'a> Diff<'a> {
22        pub fn compute(expected: &'a str, actual: &'a str) -> Option<Self> {
23            if expected.len() + actual.len() > 2048 {
24                // We don't yet trust the dissimilar crate to work well on large
25                // inputs.
26                return None;
27            }
28
29            // Nor on non-ascii inputs.
30            let diff = panic::catch_unwind(|| dissimilar::diff(expected, actual)).ok()?;
31
32            let mut common_len = 0;
33            for chunk in &diff {
34                if let Chunk::Equal(common) = chunk {
35                    common_len += common.len();
36                }
37            }
38
39            let bigger_len = cmp::max(expected.len(), actual.len());
40            let worth_printing = 5 * common_len >= 4 * bigger_len;
41            if !worth_printing {
42                return None;
43            }
44
45            Some(Diff {
46                expected,
47                actual,
48                diff,
49            })
50        }
51
52        pub fn iter<'i>(&'i self, input: &str) -> impl Iterator<Item = Render<'a>> + 'i {
53            let expected = input == self.expected;
54            let actual = input == self.actual;
55            self.diff.iter().filter_map(move |chunk| match chunk {
56                Chunk::Equal(common) => Some(Render::Common(common)),
57                Chunk::Delete(unique) if expected => Some(Render::Unique(unique)),
58                Chunk::Insert(unique) if actual => Some(Render::Unique(unique)),
59                _ => None,
60            })
61        }
62    }
63}
64
65#[cfg(any(not(feature = "diff"), windows))]
66mod r#impl {
67    use super::Render;
68
69    pub(crate) enum Diff {}
70
71    impl Diff {
72        pub fn compute(_expected: &str, _actual: &str) -> Option<Self> {
73            None
74        }
75
76        pub fn iter(&self, _input: &str) -> Box<dyn Iterator<Item = Render>> {
77            let _ = Render::Common;
78            let _ = Render::Unique;
79            match *self {}
80        }
81    }
82}