Add support for Rust 1.41.0 (#14)
This commit is contained in:
parent
d056522da4
commit
b6e2894f21
9 changed files with 230 additions and 96 deletions
4
.github/workflows/tests.yml
vendored
4
.github/workflows/tests.yml
vendored
|
|
@ -18,14 +18,14 @@ jobs:
|
|||
run: make test
|
||||
|
||||
build-stable:
|
||||
name: Test on 1.43.0
|
||||
name: Test on 1.41.0
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: 1.43.0
|
||||
toolchain: 1.41.0
|
||||
profile: minimal
|
||||
override: true
|
||||
- name: Test
|
||||
|
|
|
|||
|
|
@ -2,7 +2,11 @@
|
|||
|
||||
All notable changes to similar are documented here.
|
||||
|
||||
## 1.3.0
|
||||
## 1.2.2
|
||||
|
||||
* Added support for Rust 1.41.0 for better compatibility.
|
||||
|
||||
## 1.2.1
|
||||
|
||||
* Added support for Rust 1.43.0 for better compatibility.
|
||||
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
msrv = "1.42.0"
|
||||
msrv = "1.41.0"
|
||||
|
|
|
|||
198
src/iter.rs
Normal file
198
src/iter.rs
Normal file
|
|
@ -0,0 +1,198 @@
|
|||
//! The various iterators this crate provides.
|
||||
//!
|
||||
//! These iterators are not a very stable interface and you really should
|
||||
//! avoid considering them to be concrete types. A lot of the iterators in
|
||||
//! this crate use `impl Iterator` for this reason but restrictions in the
|
||||
//! language don't allow this to be used in all places on the versions of
|
||||
//! rust this crate wants to compile for.
|
||||
use std::marker::PhantomData;
|
||||
use std::ops::{Index, Range};
|
||||
|
||||
use crate::{Change, ChangeTag, DiffOp, DiffTag};
|
||||
|
||||
/// Iterator for [`DiffOp::iter_changes`].
|
||||
pub struct ChangesIter<'lookup, 'data, Old: ?Sized, New: ?Sized, T: ?Sized> {
|
||||
old: &'lookup Old,
|
||||
new: &'lookup New,
|
||||
old_range: Range<usize>,
|
||||
new_range: Range<usize>,
|
||||
old_index: usize,
|
||||
new_index: usize,
|
||||
old_i: usize,
|
||||
new_i: usize,
|
||||
tag: DiffTag,
|
||||
_marker: PhantomData<&'data T>,
|
||||
}
|
||||
|
||||
impl<'lookup, 'data, Old, New, T> ChangesIter<'lookup, 'data, Old, New, T>
|
||||
where
|
||||
Old: Index<usize, Output = &'data T> + ?Sized,
|
||||
New: Index<usize, Output = &'data T> + ?Sized,
|
||||
T: 'data + ?Sized,
|
||||
'data: 'lookup,
|
||||
{
|
||||
pub(crate) fn new(old: &'lookup Old, new: &'lookup New, op: DiffOp) -> Self {
|
||||
let (tag, old_range, new_range) = op.as_tag_tuple();
|
||||
let old_index = old_range.start;
|
||||
let new_index = new_range.start;
|
||||
let old_i = old_range.start;
|
||||
let new_i = new_range.start;
|
||||
ChangesIter {
|
||||
old,
|
||||
new,
|
||||
old_range,
|
||||
new_range,
|
||||
old_index,
|
||||
new_index,
|
||||
old_i,
|
||||
new_i,
|
||||
tag,
|
||||
_marker: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'lookup, 'data, Old, New, T> Iterator for ChangesIter<'lookup, 'data, Old, New, T>
|
||||
where
|
||||
Old: Index<usize, Output = &'data T> + ?Sized,
|
||||
New: Index<usize, Output = &'data T> + ?Sized,
|
||||
T: 'data + ?Sized,
|
||||
'data: 'lookup,
|
||||
{
|
||||
type Item = Change<'data, T>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
match self.tag {
|
||||
DiffTag::Equal => {
|
||||
if self.old_i < self.old_range.end {
|
||||
let value = self.old[self.old_i];
|
||||
self.old_i += 1;
|
||||
self.old_index += 1;
|
||||
self.new_index += 1;
|
||||
Some(Change {
|
||||
tag: ChangeTag::Equal,
|
||||
old_index: Some(self.old_index - 1),
|
||||
new_index: Some(self.new_index - 1),
|
||||
value,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
DiffTag::Delete => {
|
||||
if self.old_i < self.old_range.end {
|
||||
let value = self.old[self.old_i];
|
||||
self.old_i += 1;
|
||||
self.old_index += 1;
|
||||
Some(Change {
|
||||
tag: ChangeTag::Delete,
|
||||
old_index: Some(self.old_index - 1),
|
||||
new_index: None,
|
||||
value,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
DiffTag::Insert => {
|
||||
if self.new_i < self.new_range.end {
|
||||
let value = self.new[self.new_i];
|
||||
self.new_i += 1;
|
||||
self.new_index += 1;
|
||||
Some(Change {
|
||||
tag: ChangeTag::Insert,
|
||||
old_index: None,
|
||||
new_index: Some(self.new_index - 1),
|
||||
value,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
DiffTag::Replace => {
|
||||
if self.old_i < self.old_range.end {
|
||||
let value = self.old[self.old_i];
|
||||
self.old_i += 1;
|
||||
self.old_index += 1;
|
||||
Some(Change {
|
||||
tag: ChangeTag::Delete,
|
||||
old_index: Some(self.old_index - 1),
|
||||
new_index: None,
|
||||
value,
|
||||
})
|
||||
} else if self.new_i < self.new_range.end {
|
||||
let value = self.new[self.new_i];
|
||||
self.new_i += 1;
|
||||
self.new_index += 1;
|
||||
Some(Change {
|
||||
tag: ChangeTag::Insert,
|
||||
old_index: None,
|
||||
new_index: Some(self.new_index - 1),
|
||||
value,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "text")]
|
||||
mod text {
|
||||
use super::*;
|
||||
|
||||
/// Iterator for [`TextDiff::iter_all_changes`](crate::TextDiff::iter_all_changes).
|
||||
pub struct AllChangesIter<'slf, 'data, T: ?Sized> {
|
||||
old: &'slf [&'data T],
|
||||
new: &'slf [&'data T],
|
||||
ops: &'slf [DiffOp],
|
||||
current_iter: Option<ChangesIter<'slf, 'data, [&'data T], [&'data T], T>>,
|
||||
}
|
||||
|
||||
impl<'slf, 'data, T> AllChangesIter<'slf, 'data, T>
|
||||
where
|
||||
T: 'data + ?Sized + PartialEq,
|
||||
{
|
||||
pub(crate) fn new(
|
||||
old: &'slf [&'data T],
|
||||
new: &'slf [&'data T],
|
||||
ops: &'slf [DiffOp],
|
||||
) -> Self {
|
||||
AllChangesIter {
|
||||
old,
|
||||
new,
|
||||
ops,
|
||||
current_iter: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'slf, 'data, T> Iterator for AllChangesIter<'slf, 'data, T>
|
||||
where
|
||||
T: PartialEq + 'data + ?Sized,
|
||||
'data: 'slf,
|
||||
{
|
||||
type Item = Change<'data, T>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
loop {
|
||||
if let Some(ref mut iter) = self.current_iter {
|
||||
if let Some(rv) = iter.next() {
|
||||
return Some(rv);
|
||||
}
|
||||
self.current_iter.take();
|
||||
}
|
||||
if let Some((&first, rest)) = self.ops.split_first() {
|
||||
self.current_iter = Some(ChangesIter::new(self.old, self.new, first));
|
||||
self.ops = rest;
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "text")]
|
||||
pub use self::text::*;
|
||||
|
|
@ -128,6 +128,7 @@
|
|||
//! in a line diff. This currently also enables the `unicode` feature.
|
||||
#![warn(missing_docs)]
|
||||
pub mod algorithms;
|
||||
pub mod iter;
|
||||
#[cfg(feature = "text")]
|
||||
pub mod udiff;
|
||||
#[cfg(feature = "text")]
|
||||
|
|
|
|||
|
|
@ -318,7 +318,11 @@ mod bytes_support {
|
|||
}
|
||||
|
||||
fn ends_with_newline(&self) -> bool {
|
||||
matches!(self.last_byte(), Some(b'\r') | Some(b'\n'))
|
||||
if let Some(b'\r') | Some(b'\n') = self.last_byte() {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fn len(&self) -> usize {
|
||||
|
|
|
|||
|
|
@ -13,8 +13,9 @@ pub use self::abstraction::{DiffableStr, DiffableStrRef};
|
|||
pub use self::inline::InlineChange;
|
||||
|
||||
use self::utils::{upper_seq_ratio, QuickSeqRatio};
|
||||
use crate::iter::{AllChangesIter, ChangesIter};
|
||||
use crate::udiff::UnifiedDiff;
|
||||
use crate::{capture_diff_slices, get_diff_ratio, group_diff_ops, Algorithm, Change, DiffOp};
|
||||
use crate::{capture_diff_slices, get_diff_ratio, group_diff_ops, Algorithm, DiffOp};
|
||||
|
||||
/// A builder type config for more complex uses of [`TextDiff`].
|
||||
///
|
||||
|
|
@ -437,7 +438,7 @@ impl<'old, 'new, 'bufs, T: DiffableStr + ?Sized + 'old + 'new> TextDiff<'old, 'n
|
|||
pub fn iter_changes<'x, 'slf>(
|
||||
&'slf self,
|
||||
op: &DiffOp,
|
||||
) -> impl Iterator<Item = Change<'x, T>> + '_
|
||||
) -> ChangesIter<'slf, 'x, [&'x T], [&'x T], T>
|
||||
where
|
||||
'x: 'slf,
|
||||
'old: 'x,
|
||||
|
|
@ -462,13 +463,13 @@ impl<'old, 'new, 'bufs, T: DiffableStr + ?Sized + 'old + 'new> TextDiff<'old, 'n
|
|||
///
|
||||
/// This is a shortcut for combining [`TextDiff::ops`] with
|
||||
/// [`TextDiff::iter_changes`].
|
||||
pub fn iter_all_changes<'x, 'slf>(&'slf self) -> impl Iterator<Item = Change<'x, T>> + '_
|
||||
pub fn iter_all_changes<'x, 'slf>(&'slf self) -> AllChangesIter<'slf, 'x, T>
|
||||
where
|
||||
'x: 'slf + 'old + 'new,
|
||||
'old: 'x,
|
||||
'new: 'x,
|
||||
{
|
||||
self.ops().iter().flat_map(move |op| self.iter_changes(&op))
|
||||
AllChangesIter::new(&self.old[..], &self.new[..], self.ops())
|
||||
}
|
||||
|
||||
/// Utility to return a unified diff formatter.
|
||||
|
|
@ -539,7 +540,7 @@ pub fn get_close_matches<'a, T: DiffableStr + ?Sized>(
|
|||
if ratio >= cutoff {
|
||||
// we're putting the word itself in reverse in so that matches with
|
||||
// the same ratio are ordered lexicographically.
|
||||
matches.push(((ratio * u32::MAX as f32) as u32, Reverse(possibility)));
|
||||
matches.push(((ratio * std::u32::MAX as f32) as u32, Reverse(possibility)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -668,6 +669,8 @@ fn test_get_close_matches() {
|
|||
|
||||
#[test]
|
||||
fn test_lifetimes_on_iter() {
|
||||
use crate::Change;
|
||||
|
||||
fn diff_lines<'x, T>(old: &'x T, new: &'x T) -> Vec<Change<'x, T::Output>>
|
||||
where
|
||||
T: DiffableStrRef + ?Sized,
|
||||
|
|
|
|||
83
src/types.rs
83
src/types.rs
|
|
@ -2,6 +2,7 @@ use std::fmt;
|
|||
use std::ops::{Index, Range};
|
||||
|
||||
use crate::algorithms::DiffHook;
|
||||
use crate::iter::ChangesIter;
|
||||
|
||||
/// An enum representing a diffing algorithm.
|
||||
#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord, Debug)]
|
||||
|
|
@ -272,92 +273,14 @@ impl DiffOp {
|
|||
&self,
|
||||
old: &'lookup Old,
|
||||
new: &'lookup New,
|
||||
) -> impl Iterator<Item = Change<'x, T>> + 'lookup
|
||||
) -> ChangesIter<'lookup, 'x, Old, New, T>
|
||||
where
|
||||
Old: Index<usize, Output = &'x T> + ?Sized,
|
||||
New: Index<usize, Output = &'x T> + ?Sized,
|
||||
T: 'x + ?Sized,
|
||||
'x: 'lookup,
|
||||
{
|
||||
let (tag, old_range, new_range) = self.as_tag_tuple();
|
||||
let mut old_index = old_range.start;
|
||||
let mut new_index = new_range.start;
|
||||
let mut old_i = old_range.start;
|
||||
let mut new_i = new_range.start;
|
||||
|
||||
std::iter::from_fn(move || match tag {
|
||||
DiffTag::Equal => {
|
||||
if old_i < old_range.end {
|
||||
let value = old[old_i];
|
||||
old_i += 1;
|
||||
old_index += 1;
|
||||
new_index += 1;
|
||||
Some(Change {
|
||||
tag: ChangeTag::Equal,
|
||||
old_index: Some(old_index - 1),
|
||||
new_index: Some(new_index - 1),
|
||||
value,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
DiffTag::Delete => {
|
||||
if old_i < old_range.end {
|
||||
let value = old[old_i];
|
||||
old_i += 1;
|
||||
old_index += 1;
|
||||
Some(Change {
|
||||
tag: ChangeTag::Delete,
|
||||
old_index: Some(old_index - 1),
|
||||
new_index: None,
|
||||
value,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
DiffTag::Insert => {
|
||||
if new_i < new_range.end {
|
||||
let value = new[new_i];
|
||||
new_i += 1;
|
||||
new_index += 1;
|
||||
Some(Change {
|
||||
tag: ChangeTag::Insert,
|
||||
old_index: None,
|
||||
new_index: Some(new_index - 1),
|
||||
value,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
DiffTag::Replace => {
|
||||
if old_i < old_range.end {
|
||||
let value = old[old_i];
|
||||
old_i += 1;
|
||||
old_index += 1;
|
||||
Some(Change {
|
||||
tag: ChangeTag::Delete,
|
||||
old_index: Some(old_index - 1),
|
||||
new_index: None,
|
||||
value,
|
||||
})
|
||||
} else if new_i < new_range.end {
|
||||
let value = new[new_i];
|
||||
new_i += 1;
|
||||
new_index += 1;
|
||||
Some(Change {
|
||||
tag: ChangeTag::Insert,
|
||||
old_index: None,
|
||||
new_index: Some(new_index - 1),
|
||||
value,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
})
|
||||
ChangesIter::new(old, new, *self)
|
||||
}
|
||||
|
||||
/// Given a diffop yields the changes it encodes against the given slices.
|
||||
|
|
|
|||
13
src/udiff.rs
13
src/udiff.rs
|
|
@ -27,8 +27,9 @@
|
|||
use std::ops::Range;
|
||||
use std::{fmt, io};
|
||||
|
||||
use crate::iter::AllChangesIter;
|
||||
use crate::text::{DiffableStr, TextDiff};
|
||||
use crate::types::{Algorithm, Change, DiffOp};
|
||||
use crate::types::{Algorithm, DiffOp};
|
||||
|
||||
struct MissingNewlineHint(bool);
|
||||
|
||||
|
|
@ -240,13 +241,13 @@ impl<'diff, 'old, 'new, 'bufs, T: DiffableStr + ?Sized>
|
|||
}
|
||||
|
||||
/// Iterates over all changes in a hunk.
|
||||
pub fn iter_changes(&self) -> impl Iterator<Item = Change<'diff, T>> + '_
|
||||
pub fn iter_changes<'x, 'slf>(&'slf self) -> AllChangesIter<'slf, 'x, T>
|
||||
where
|
||||
'diff: 'old + 'new + 'bufs,
|
||||
'x: 'slf + 'old + 'new,
|
||||
'old: 'x,
|
||||
'new: 'x,
|
||||
{
|
||||
self.ops()
|
||||
.iter()
|
||||
.flat_map(move |op| self.diff.iter_changes(op))
|
||||
AllChangesIter::new(self.diff.old_slices(), self.diff.new_slices(), self.ops())
|
||||
}
|
||||
|
||||
/// Write the hunk as bytes to the output stream.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue