on master help sign in
Remove ExactSizeIterator requirement on Transaction::change

Size hint is enough.

commitbf43fabf65fe4062f582e59fe21e92a0b0f48cb8 authorBlaž Hrastnik <blaz@mxxn.io> dateMon 19 Jul 2021, 11:19 (5 years ago) parentcd65a48
2 files changed+31−31
helix-core/src/diff.rs+27−29 helix-core/src/transaction.rs+4−2
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};
42
53/// Compares `old` and `new` to generate a [`Transaction`] describing
64/// the steps required to get from `old` to `new`.
@@ -25,34 +23,34 @@ pub fn compare_ropes(old: &Rope, new: &Rope) -> Transaction {
2523 // The current position of the change needs to be tracked to
2624 // construct the `Change`s.
2725 let mut pos = 0;
28− let changes: Vec<Change> = diff
29− .ops()
30− .iter()
31− .map(|op| op.as_tag_tuple())
32− .filter_map(|(tag, old_range, new_range)| {
33− // `old_pos..pos` is equivalent to `start..end` for where
34− // the change should be applied.
35− let old_pos = pos;
36− pos += old_range.end - old_range.start;
26+ Transaction::change(
27+ old,
28+ diff.ops()
29+ .iter()
30+ .map(|op| op.as_tag_tuple())
31+ .filter_map(|(tag, old_range, new_range)| {
32+ // `old_pos..pos` is equivalent to `start..end` for where
33+ // the change should be applied.
34+ let old_pos = pos;
35+ pos += old_range.end - old_range.start;
3736
38− match tag {
39− // Semantically, inserts and replacements are the same thing.
40− similar::DiffTag::Insert | similar::DiffTag::Replace => {
41− // This is the text from the `new` rope that should be
42− // inserted into `old`.
43− let text: &str = {
44− let start = new.char_to_byte(new_range.start);
45− let end = new.char_to_byte(new_range.end);
46− &new_converted[start..end]
47− };
48− Some((old_pos, pos, Some(text.into())))
37+ match tag {
38+ // Semantically, inserts and replacements are the same thing.
39+ similar::DiffTag::Insert | similar::DiffTag::Replace => {
40+ // This is the text from the `new` rope that should be
41+ // inserted into `old`.
42+ let text: &str = {
43+ let start = new.char_to_byte(new_range.start);
44+ let end = new.char_to_byte(new_range.end);
45+ &new_converted[start..end]
46+ };
47+ Some((old_pos, pos, Some(text.into())))
48+ }
49+ similar::DiffTag::Delete => Some((old_pos, pos, None)),
50+ similar::DiffTag::Equal => None,
4951 }
50− similar::DiffTag::Delete => Some((old_pos, pos, None)),
51− similar::DiffTag::Equal => None,
52− }
53− })
54− .collect();
55− Transaction::change(old, changes.into_iter())
52+ }),
53+ )
5654}
5755
5856#[cfg(test)]
helix-core/src/transaction.rs+4−2
@@ -473,11 +473,13 @@ impl Transaction {
473473 /// Generate a transaction from a set of changes.
474474 pub fn change<I>(doc: &Rope, changes: I) -> Self
475475 where
476− I: IntoIterator<Item = Change> + ExactSizeIterator,
476+ I: IntoIterator<Item = Change> + Iterator,
477477 {
478478 let len = doc.len_chars();
479479
480− let mut changeset = ChangeSet::with_capacity(2 * changes.len() + 1); // rough estimate
480+ let (lower, upper) = changes.size_hint();
481+ let size = upper.unwrap_or(lower);
482+ let mut changeset = ChangeSet::with_capacity(2 * size + 1); // rough estimate
481483
482484 // TODO: verify ranges are ordered and not overlapping or change will panic.
483485