Remove break_up_raw_operations

This commit is contained in:
Andras Schmelczer 2025-04-05 13:57:48 +01:00
commit 2b78f0c76f
No known key found for this signature in database
GPG key ID: FC8F2C3D3D1A718C
6 changed files with 61 additions and 52 deletions

View file

@ -1,4 +1,5 @@
//! Taken from <https://github.com/mitsuhiko/similar/blob/7e15c44de11a1cd61e1149189929e189ef977fd8/src/algorithms/myers.rs> //! Taken from <https://github.com/mitsuhiko/similar/blob/7e15c44de11a1cd61e1149189929e189ef977fd8/src/algorithms/myers.rs>
//!
//! Myers' diff algorithm. //! Myers' diff algorithm.
//! //!
//! * time: `O((N+M)D)` //! * time: `O((N+M)D)`
@ -34,8 +35,7 @@ use crate::{
/// Diff `old`, between indices `old_range` and `new` between indices /// Diff `old`, between indices `old_range` and `new` between indices
/// `new_range`. /// `new_range`.
/// ///
/// This diff is done with an optional deadline that defines the maximal /// The returned RawOperations all have a token count of 1.
/// execution time permitted before it bails and falls back to an approximation.
pub fn diff<T>(old: &[Token<T>], new: &[Token<T>]) -> Vec<RawOperation<T>> pub fn diff<T>(old: &[Token<T>], new: &[Token<T>]) -> Vec<RawOperation<T>>
where where
T: PartialEq + Clone + std::fmt::Debug, T: PartialEq + Clone + std::fmt::Debug,
@ -44,6 +44,7 @@ where
let mut vb = V::new(max_d); let mut vb = V::new(max_d);
let mut vf = V::new(max_d); let mut vf = V::new(max_d);
let mut result: Vec<RawOperation<T>> = vec![]; let mut result: Vec<RawOperation<T>> = vec![];
conquer( conquer(
old, old,
0..old.len(), 0..old.len(),
@ -53,6 +54,12 @@ where
&mut vb, &mut vb,
&mut result, &mut result,
); );
debug_assert!(
result.iter().all(|op| op.tokens().len() == 1),
"All operations should be of length 1"
);
result result
} }
@ -234,9 +241,11 @@ fn conquer<T>(
// Check for common prefix // Check for common prefix
let common_prefix_len = common_prefix_len(old, old_range.clone(), new, new_range.clone()); let common_prefix_len = common_prefix_len(old, old_range.clone(), new, new_range.clone());
if common_prefix_len > 0 { if common_prefix_len > 0 {
result.push(RawOperation::Equal( result.extend(
old[old_range.start..old_range.start + common_prefix_len].to_vec(), old[old_range.start..old_range.start + common_prefix_len]
)); .iter()
.map(|token| RawOperation::Equal(vec![token.clone()])),
)
} }
old_range.start += common_prefix_len; old_range.start += common_prefix_len;
new_range.start += common_prefix_len; new_range.start += common_prefix_len;
@ -251,15 +260,19 @@ fn conquer<T>(
new_range.end -= common_suffix_len; new_range.end -= common_suffix_len;
if old_range.is_empty() && new_range.is_empty() { if old_range.is_empty() && new_range.is_empty() {
// Do nothing // do nothing
} else if new_range.is_empty() { } else if new_range.is_empty() {
result.push(RawOperation::Delete( result.extend(
old[old_range.start..old_range.start + old_range.len()].to_vec(), old[old_range.start..old_range.start + old_range.len()]
)); .iter()
.map(|token| RawOperation::Delete(vec![token.clone()])),
)
} else if old_range.is_empty() { } else if old_range.is_empty() {
result.push(RawOperation::Insert( result.extend(
new[new_range.start..new_range.start + new_range.len()].to_vec(), new[new_range.start..new_range.start + new_range.len()]
)); .iter()
.map(|token| RawOperation::Insert(vec![token.clone()])),
)
} else if let Some((x_start, y_start)) = } else if let Some((x_start, y_start)) =
find_middle_snake(old, old_range.clone(), new, new_range.clone(), vf, vb) find_middle_snake(old, old_range.clone(), new, new_range.clone(), vf, vb)
{ {
@ -268,18 +281,24 @@ fn conquer<T>(
conquer(old, old_a, new, new_a, vf, vb, result); conquer(old, old_a, new, new_a, vf, vb, result);
conquer(old, old_b, new, new_b, vf, vb, result); conquer(old, old_b, new, new_b, vf, vb, result);
} else { } else {
result.push(RawOperation::Delete( result.extend(
old[old_range.start..old_range.end].to_vec(), old[old_range.start..old_range.end]
)); .iter()
result.push(RawOperation::Insert( .map(|token| RawOperation::Delete(vec![token.clone()])),
new[new_range.start..new_range.end].to_vec(), );
)); result.extend(
new[new_range.start..new_range.end]
.iter()
.map(|token| RawOperation::Insert(vec![token.clone()])),
);
} }
if common_suffix_len > 0 { if common_suffix_len > 0 {
result.push(RawOperation::Equal( result.extend(
old[common_suffix.0..common_suffix.0 + common_suffix_len].to_vec(), old[common_suffix.0..common_suffix.0 + common_suffix_len]
)); .iter()
.map(|token| RawOperation::Equal(vec![token.clone()])),
);
} }
} }

View file

@ -12,6 +12,10 @@ snapshot_kind: text
is_left_joinable: true, is_left_joinable: true,
is_right_joinable: true, is_right_joinable: true,
}, },
],
),
Delete(
[
Token { Token {
normalised: "b", normalised: "b",
original: "b", original: "b",

View file

@ -12,12 +12,20 @@ snapshot_kind: text
is_left_joinable: true, is_left_joinable: true,
is_right_joinable: true, is_right_joinable: true,
}, },
],
),
Equal(
[
Token { Token {
normalised: "b", normalised: "b",
original: "b", original: "b",
is_left_joinable: true, is_left_joinable: true,
is_right_joinable: true, is_right_joinable: true,
}, },
],
),
Equal(
[
Token { Token {
normalised: "c", normalised: "c",
original: "c", original: "c",

View file

@ -12,6 +12,10 @@ snapshot_kind: text
is_left_joinable: true, is_left_joinable: true,
is_right_joinable: true, is_right_joinable: true,
}, },
],
),
Insert(
[
Token { Token {
normalised: "b", normalised: "b",
original: "b", original: "b",

View file

@ -22,6 +22,10 @@ snapshot_kind: text
is_left_joinable: true, is_left_joinable: true,
is_right_joinable: true, is_right_joinable: true,
}, },
],
),
Delete(
[
Token { Token {
normalised: "c", normalised: "c",
original: "c", original: "c",

View file

@ -63,41 +63,11 @@ where
Self::new( Self::new(
original, original,
Self::cook_operations(Self::elongate_operations(Self::break_up_raw_operations( Self::cook_operations(Self::elongate_operations(diff)).collect(),
diff,
)))
.collect(),
updated.cursors, updated.cursors,
) )
} }
fn break_up_raw_operations<I>(raw_operations: I) -> impl Iterator<Item = RawOperation<T>>
where
I: IntoIterator<Item = RawOperation<T>>,
{
raw_operations.into_iter().flat_map(|raw_operation| {
let mut result: Vec<RawOperation<T>> = Vec::new();
match raw_operation {
RawOperation::Insert(tokens) => {
for token in tokens {
result.push(RawOperation::Insert(vec![token]));
}
}
RawOperation::Delete(tokens) => {
for token in tokens {
result.push(RawOperation::Delete(vec![token]));
}
}
RawOperation::Equal(tokens) => {
for token in tokens {
result.push(RawOperation::Equal(vec![token]));
}
}
}
result.into_iter()
})
}
fn elongate_operations<I>(raw_operations: I) -> Vec<RawOperation<T>> fn elongate_operations<I>(raw_operations: I) -> Vec<RawOperation<T>>
where where
I: IntoIterator<Item = RawOperation<T>>, I: IntoIterator<Item = RawOperation<T>>,