Added deadlines to all algorithms (#18)

This adds a deadline to all algorithms which lets one bail in a fixed amount of
time to avoid pathological cases.
This commit is contained in:
Armin Ronacher 2021-02-20 10:12:06 +01:00 committed by GitHub
parent 99386e8106
commit 74e2805a95
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 412 additions and 57 deletions

View file

@ -1,13 +1,15 @@
use std::hash::Hash;
use std::ops::{Index, Range};
use std::time::Instant;
use crate::algorithms::{diff, diff_slices, Capture, Replace};
use crate::algorithms::{diff_deadline, diff_slices_deadline, Capture, Replace};
use crate::{Algorithm, DiffOp};
/// Creates a diff between old and new with the given algorithm capturing the ops.
///
/// This is like [`diff`] but instead of using an arbitrary hook this will
/// always use [`Replace`] + [`Capture`] and return the captured [`DiffOp`]s.
/// This is like [`diff`](crate::algorithms::diff) but instead of using an
/// arbitrary hook this will always use [`Replace`] + [`Capture`] and return the
/// captured [`DiffOp`]s.
pub fn capture_diff<Old, New>(
alg: Algorithm,
old: &Old,
@ -15,6 +17,26 @@ pub fn capture_diff<Old, New>(
new: &New,
new_range: Range<usize>,
) -> Vec<DiffOp>
where
Old: Index<usize> + ?Sized,
New: Index<usize> + ?Sized,
Old::Output: Hash + Eq + Ord,
New::Output: PartialEq<Old::Output> + Hash + Eq + Ord,
{
capture_diff_deadline(alg, old, old_range, new, new_range, None)
}
/// Creates a diff between old and new with the given algorithm capturing the ops.
///
/// Works like [`capture_diff`] but with an optional deadline.
pub fn capture_diff_deadline<Old, New>(
alg: Algorithm,
old: &Old,
old_range: Range<usize>,
new: &New,
new_range: Range<usize>,
deadline: Option<Instant>,
) -> Vec<DiffOp>
where
Old: Index<usize> + ?Sized,
New: Index<usize> + ?Sized,
@ -22,17 +44,32 @@ where
New::Output: PartialEq<Old::Output> + Hash + Eq + Ord,
{
let mut d = Replace::new(Capture::new());
diff(alg, &mut d, old, old_range, new, new_range).unwrap();
diff_deadline(alg, &mut d, old, old_range, new, new_range, deadline).unwrap();
d.into_inner().into_ops()
}
/// Creates a diff between old and new with the given algorithm capturing the ops.
pub fn capture_diff_slices<T>(alg: Algorithm, old: &[T], new: &[T]) -> Vec<DiffOp>
where
T: Eq + Hash + Ord,
{
capture_diff_slices_deadline(alg, old, new, None)
}
/// Creates a diff between old and new with the given algorithm capturing the ops.
///
/// Works like [`capture_diff_slices`] but with an optional deadline.
pub fn capture_diff_slices_deadline<T>(
alg: Algorithm,
old: &[T],
new: &[T],
deadline: Option<Instant>,
) -> Vec<DiffOp>
where
T: Eq + Hash + Ord,
{
let mut d = Replace::new(Capture::new());
diff_slices(alg, &mut d, old, new).unwrap();
diff_slices_deadline(alg, &mut d, old, new, deadline).unwrap();
d.into_inner().into_ops()
}