From 4edb2ae8d1e3e6251750e6fa0a025b9be2853707 Mon Sep 17 00:00:00 2001 From: Nickolay Ponomarev Date: Mon, 14 Jan 2019 02:50:59 +0300 Subject: [PATCH] Fix panic with custom Debug impl returning an empty string The panic was 'attempt to subtract with overflow' because the first difference is addition. PrettyString is from idubrov: https://github.com/colin-kiegel/rust-pretty-assertions/issues/24#issuecomment-453698853 --- src/format_changeset.rs | 6 ++++-- tests/pretty_string.rs | 28 ++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) create mode 100644 tests/pretty_string.rs diff --git a/src/format_changeset.rs b/src/format_changeset.rs index ef7ea43..710853f 100644 --- a/src/format_changeset.rs +++ b/src/format_changeset.rs @@ -36,7 +36,8 @@ pub fn format_changeset(f: &mut fmt::Formatter, changeset: &Changeset) -> fmt::R } } Difference::Add(ref added) => { - match diffs.get(i - 1) { + let prev = i.checked_sub(1).and_then(|x| diffs.get(x)); + match prev { Some(&Difference::Rem(ref removed)) => { // The addition is preceded by an removal. // @@ -52,7 +53,8 @@ pub fn format_changeset(f: &mut fmt::Formatter, changeset: &Changeset) -> fmt::R }; } Difference::Rem(ref removed) => { - match diffs.get(i + 1) { + let next = i.checked_add(1).and_then(|x| diffs.get(x)); + match next { Some(&Difference::Add(_)) => { // The removal is followed by an addition. // diff --git a/tests/pretty_string.rs b/tests/pretty_string.rs new file mode 100644 index 0000000..6f888a4 --- /dev/null +++ b/tests/pretty_string.rs @@ -0,0 +1,28 @@ +#[macro_use] +extern crate pretty_assertions; + +use std::fmt; +/// Wrapper around string slice that makes debug output `{:?}` to print string same way as `{}`. +/// Used in different `assert*!` macros in combination with `pretty_assertions` crate to make +/// test failures to show nice diffs. +#[derive(PartialEq, Eq)] +#[doc(hidden)] +pub struct PrettyString<'a>(pub &'a str); + +/// Make diff to display string as multi-line string +impl<'a> fmt::Debug for PrettyString<'a> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_str(self.0) + } +} + +#[test] +#[should_panic(expected = r#"assertion failed: `(left == right)` + +Diff < left / right > : +>foo + +"#)] +fn assert_eq_empty_first() { + assert_eq!(PrettyString(""), PrettyString("foo")); +}