Remove ExactSizeIterator requirement on Transaction::change

Size hint is enough.
pull/469/head
Blaž Hrastnik 3 years ago
parent cd65a48635
commit bf43fabf65

@ -1,6 +1,4 @@
use ropey::Rope; use crate::{Rope, Transaction};
use crate::{Change, Transaction};
/// Compares `old` and `new` to generate a [`Transaction`] describing /// Compares `old` and `new` to generate a [`Transaction`] describing
/// the steps required to get from `old` to `new`. /// the steps required to get from `old` to `new`.
@ -25,34 +23,34 @@ pub fn compare_ropes(old: &Rope, new: &Rope) -> Transaction {
// The current position of the change needs to be tracked to // The current position of the change needs to be tracked to
// construct the `Change`s. // construct the `Change`s.
let mut pos = 0; let mut pos = 0;
let changes: Vec<Change> = diff Transaction::change(
.ops() old,
.iter() diff.ops()
.map(|op| op.as_tag_tuple()) .iter()
.filter_map(|(tag, old_range, new_range)| { .map(|op| op.as_tag_tuple())
// `old_pos..pos` is equivalent to `start..end` for where .filter_map(|(tag, old_range, new_range)| {
// the change should be applied. // `old_pos..pos` is equivalent to `start..end` for where
let old_pos = pos; // the change should be applied.
pos += old_range.end - old_range.start; let old_pos = pos;
pos += old_range.end - old_range.start;
match tag { match tag {
// Semantically, inserts and replacements are the same thing. // Semantically, inserts and replacements are the same thing.
similar::DiffTag::Insert | similar::DiffTag::Replace => { similar::DiffTag::Insert | similar::DiffTag::Replace => {
// This is the text from the `new` rope that should be // This is the text from the `new` rope that should be
// inserted into `old`. // inserted into `old`.
let text: &str = { let text: &str = {
let start = new.char_to_byte(new_range.start); let start = new.char_to_byte(new_range.start);
let end = new.char_to_byte(new_range.end); let end = new.char_to_byte(new_range.end);
&new_converted[start..end] &new_converted[start..end]
}; };
Some((old_pos, pos, Some(text.into()))) Some((old_pos, pos, Some(text.into())))
}
similar::DiffTag::Delete => Some((old_pos, pos, None)),
similar::DiffTag::Equal => None,
} }
similar::DiffTag::Delete => Some((old_pos, pos, None)), }),
similar::DiffTag::Equal => None, )
}
})
.collect();
Transaction::change(old, changes.into_iter())
} }
#[cfg(test)] #[cfg(test)]

@ -473,11 +473,13 @@ impl Transaction {
/// Generate a transaction from a set of changes. /// Generate a transaction from a set of changes.
pub fn change<I>(doc: &Rope, changes: I) -> Self pub fn change<I>(doc: &Rope, changes: I) -> Self
where where
I: IntoIterator<Item = Change> + ExactSizeIterator, I: IntoIterator<Item = Change> + Iterator,
{ {
let len = doc.len_chars(); let len = doc.len_chars();
let mut changeset = ChangeSet::with_capacity(2 * changes.len() + 1); // rough estimate let (lower, upper) = changes.size_hint();
let size = upper.unwrap_or(lower);
let mut changeset = ChangeSet::with_capacity(2 * size + 1); // rough estimate
// TODO: verify ranges are ordered and not overlapping or change will panic. // TODO: verify ranges are ordered and not overlapping or change will panic.

Loading…
Cancel
Save