on master help sign in
Remove ExactSizeIterator requirement on Transaction::change
bf43fabBlaž Hrastnik
helix-core/src/diff.rs+27−29
@@ -1,6 +1,4 @@
1−use ropey::Rope;
2−
3−use crate::{Change, Transaction};
1+use crate::{Rope, Transaction};
4
2
5/// Compares `old` and `new` to generate a [`Transaction`] describing
3/// Compares `old` and `new` to generate a [`Transaction`] describing
6/// the steps required to get from `old` to `new`.
4/// the steps required to get from `old` to `new`.
@@ -25,34 +23,34 @@ pub fn compare_ropes(old: &Rope, new: &Rope) -> Transaction {
25 // The current position of the change needs to be tracked to
23 // The current position of the change needs to be tracked to
26 // construct the `Change`s.
24 // construct the `Change`s.
27 let mut pos = 0;
25 let mut pos = 0;
28− let changes: Vec<Change> = diff
26+ Transaction::change(
27+ old,
29− .ops()
28+ diff.ops()
30− .iter()
29+ .iter()
31− .map(|op| op.as_tag_tuple())
30+ .map(|op| op.as_tag_tuple())
32− .filter_map(|(tag, old_range, new_range)| {
31+ .filter_map(|(tag, old_range, new_range)| {
33− // `old_pos..pos` is equivalent to `start..end` for where
32+ // `old_pos..pos` is equivalent to `start..end` for where
34− // the change should be applied.
33+ // the change should be applied.
35− let old_pos = pos;
34+ let old_pos = pos;
36− pos += old_range.end - old_range.start;
35+ pos += old_range.end - old_range.start;
37
36
38− match tag {
37+ match tag {
39− // Semantically, inserts and replacements are the same thing.
38+ // Semantically, inserts and replacements are the same thing.
40− similar::DiffTag::Insert | similar::DiffTag::Replace => {
39+ similar::DiffTag::Insert | similar::DiffTag::Replace => {
41− // This is the text from the `new` rope that should be
40+ // This is the text from the `new` rope that should be
42− // inserted into `old`.
41+ // inserted into `old`.
43− let text: &str = {
42+ let text: &str = {
44− let start = new.char_to_byte(new_range.start);
43+ let start = new.char_to_byte(new_range.start);
45− let end = new.char_to_byte(new_range.end);
44+ let end = new.char_to_byte(new_range.end);
46− &new_converted[start..end]
45+ &new_converted[start..end]
47− };
46+ };
48− Some((old_pos, pos, Some(text.into())))
47+ Some((old_pos, pos, Some(text.into())))
48+ }
49+ similar::DiffTag::Delete => Some((old_pos, pos, None)),
50+ similar::DiffTag::Equal => None,
49 }
51 }
50− similar::DiffTag::Delete => Some((old_pos, pos, None)),
51− similar::DiffTag::Equal => None,
52− }
52+ }),
53− })
53+ )
54− .collect();
55− Transaction::change(old, changes.into_iter())
56}
54}
57
55
58#[cfg(test)]
56#[cfg(test)]
helix-core/src/transaction.rs+4−2
@@ -473,11 +473,13 @@ impl Transaction {
473 /// Generate a transaction from a set of changes.
473 /// Generate a transaction from a set of changes.
474 pub fn change<I>(doc: &Rope, changes: I) -> Self
474 pub fn change<I>(doc: &Rope, changes: I) -> Self
475 where
475 where
476− I: IntoIterator<Item = Change> + ExactSizeIterator,
476+ I: IntoIterator<Item = Change> + Iterator,
477 {
477 {
478 let len = doc.len_chars();
478 let len = doc.len_chars();
479
479
480+ let (lower, upper) = changes.size_hint();
481+ let size = upper.unwrap_or(lower);
480− let mut changeset = ChangeSet::with_capacity(2 * changes.len() + 1); // rough estimate
482+ let mut changeset = ChangeSet::with_capacity(2 * size + 1); // rough estimate
481
483
482 // TODO: verify ranges are ordered and not overlapping or change will panic.
484 // TODO: verify ranges are ordered and not overlapping or change will panic.
483
485