diff --git a/CHANGELOG.md b/CHANGELOG.md index c8e1ee3..8bfa286 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ All notable changes to similar are documented here. +## 1.1.0 + +* More generic lifetimes for `iter_changes` and `iter_inline_changes`. +* Added `iter_all_changes` shortcut as this is commonly useful. + ## 1.0.0 * Add `get_diff_ratio`. diff --git a/src/text/inline.rs b/src/text/inline.rs index a56c3e4..0b368f3 100644 --- a/src/text/inline.rs +++ b/src/text/inline.rs @@ -174,12 +174,15 @@ impl<'s, T: DiffableStr + ?Sized> fmt::Display for InlineChange<'s, T> { } } -pub(crate) fn iter_inline_changes<'diff, T>( - diff: &'diff TextDiff<'_, '_, '_, T>, +pub(crate) fn iter_inline_changes<'x, 'diff, 'old, 'new, 'bufs, T>( + diff: &'diff TextDiff<'old, 'new, 'bufs, T>, op: &DiffOp, -) -> impl Iterator> +) -> impl Iterator> + 'diff where T: DiffableStr + ?Sized, + 'x: 'diff, + 'old: 'x, + 'new: 'x, { let (tag, old_range, new_range) = op.as_tag_tuple(); diff --git a/src/text/mod.rs b/src/text/mod.rs index 4954d2d..f1b393c 100644 --- a/src/text/mod.rs +++ b/src/text/mod.rs @@ -294,7 +294,15 @@ impl<'old, 'new, 'bufs, T: DiffableStr + ?Sized + 'old + 'new> TextDiff<'old, 'n /// ways in which a change could be encoded (insert/delete vs replace), look /// up the value from the appropriate slice and also handle correct index /// handling. - pub fn iter_changes(&self, op: &DiffOp) -> impl Iterator> { + pub fn iter_changes<'x, 'slf>( + &'slf self, + op: &DiffOp, + ) -> impl Iterator> + 'slf + where + 'x: 'slf, + 'old: 'x, + 'new: 'x, + { op.iter_changes(self.old_slices(), self.new_slices()) } @@ -310,6 +318,22 @@ impl<'old, 'new, 'bufs, T: DiffableStr + ?Sized + 'old + 'new> TextDiff<'old, 'n group_diff_ops(self.ops().to_vec(), n) } + /// Flattens out the diff into all changes. + /// + /// This is a shortcut for combining [`TextDiff::ops`] with + /// [`TextDiff::iter_changes`]. + pub fn iter_all_changes<'x, 'slf>(&'slf self) -> impl Iterator> + 'slf + where + 'x: 'slf, + 'old: 'x, + 'new: 'x, + { + // unclear why this needs Box::new here. It seems to infer some really + // odd lifetimes I can't figure out how to work with. + Box::new(self.ops().iter().flat_map(move |op| self.iter_changes(&op))) + as Box> + } + /// Utility to return a unified diff formatter. pub fn unified_diff<'diff>(&'diff self) -> UnifiedDiff<'diff, 'old, 'new, 'bufs, T> { UnifiedDiff::from_text_diff(self) @@ -322,7 +346,15 @@ impl<'old, 'new, 'bufs, T: DiffableStr + ?Sized + 'old + 'new> TextDiff<'old, 'n /// this function with regards to how it detects those inline changes /// is currently not defined and will likely change over time. #[cfg(feature = "inline")] - pub fn iter_inline_changes(&self, op: &DiffOp) -> impl Iterator> { + pub fn iter_inline_changes<'x, 'slf>( + &'slf self, + op: &DiffOp, + ) -> impl Iterator> + 'slf + where + 'x: 'slf, + 'old: 'x, + 'new: 'x, + { inline::iter_inline_changes(self, op) } } @@ -492,3 +524,18 @@ fn test_get_close_matches() { ); assert_eq!(matches, vec!["aulo", "hulu", "uulo", "zulo"]); } + +#[test] +fn test_lifetimes_on_iter() { + fn diff_lines<'x, T>(old: &'x T, new: &'x T) -> Vec> + where + T: DiffableStrRef + ?Sized, + { + TextDiff::from_lines(old, new).iter_all_changes().collect() + } + + let a = "1\n2\n3\n".to_string(); + let b = "1\n99\n3\n".to_string(); + let changes = diff_lines(&a, &b); + insta::assert_debug_snapshot!(&changes); +} diff --git a/src/types.rs b/src/types.rs index b72ce59..23ede7e 100644 --- a/src/types.rs +++ b/src/types.rs @@ -247,15 +247,16 @@ impl DiffOp { /// /// `old` and `new` are two indexable objects like the types you pass to /// the diffing algorithm functions. - pub fn iter_changes<'x, Old, New, T>( + pub fn iter_changes<'x, 'lookup, Old, New, T>( &self, - old: &'x Old, - new: &'x New, - ) -> impl Iterator> + old: &'lookup Old, + new: &'lookup New, + ) -> impl Iterator> + 'lookup where Old: Index + ?Sized, New: Index + ?Sized, T: 'x + ?Sized, + 'x: 'lookup, { let (tag, old_range, new_range) = self.as_tag_tuple(); let mut old_index = old_range.start; diff --git a/src/udiff.rs b/src/udiff.rs index bd28c3a..5fcc231 100644 --- a/src/udiff.rs +++ b/src/udiff.rs @@ -240,11 +240,11 @@ impl<'diff, 'old, 'new, 'bufs, T: DiffableStr + ?Sized> pub fn iter_changes(&self) -> impl Iterator> + '_ { // unclear why this needs Box::new here. It seems to infer some really // odd lifetimes I can't figure out how to work with. - (Box::new( + Box::new( self.ops() .iter() .flat_map(move |op| self.diff.iter_changes(op)), - )) as Box> + ) as Box> } /// Write the hunk as bytes to the output stream.