|
@@ -5,7 +5,7 @@ use crate::{
|
|
|
use std::{cmp::min, iter::Enumerate, slice::Iter};
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
-pub struct Cursor<'a> {
|
|
|
+pub struct OpCursor<'a> {
|
|
|
pub(crate) delta: &'a Delta,
|
|
|
pub(crate) origin_iv: Interval,
|
|
|
pub(crate) consume_iv: Interval,
|
|
@@ -15,8 +15,8 @@ pub struct Cursor<'a> {
|
|
|
next_op: Option<Operation>,
|
|
|
}
|
|
|
|
|
|
-impl<'a> Cursor<'a> {
|
|
|
- pub fn new(delta: &'a Delta, interval: Interval) -> Cursor<'a> {
|
|
|
+impl<'a> OpCursor<'a> {
|
|
|
+ pub fn new(delta: &'a Delta, interval: Interval) -> OpCursor<'a> {
|
|
|
// debug_assert!(interval.start <= delta.target_len);
|
|
|
let mut cursor = Self {
|
|
|
delta,
|
|
@@ -32,51 +32,56 @@ impl<'a> Cursor<'a> {
|
|
|
}
|
|
|
|
|
|
// get the next operation interval
|
|
|
- pub fn next_iv(&self) -> Interval { self.next_iv_before(None) }
|
|
|
+ pub fn next_iv(&self) -> Interval { self.next_iv_before(None).unwrap_or(Interval::new(0, 0)) }
|
|
|
|
|
|
- pub fn next_op(&mut self) -> Option<Operation> { self.last_op_before_index(None) }
|
|
|
+ pub fn next(&mut self) -> Option<Operation> { self.next_with_len(None) }
|
|
|
|
|
|
- // get the last operation before the index
|
|
|
- pub fn last_op_before_index(&mut self, index: Option<usize>) -> Option<Operation> {
|
|
|
+ // get the last operation before the end.
|
|
|
+ // checkout the delta_next_op_with_len_cross_op_return_last test for more detail
|
|
|
+ pub fn next_with_len(&mut self, force_end: Option<usize>) -> Option<Operation> {
|
|
|
let mut find_op = None;
|
|
|
let holder = self.next_op.clone();
|
|
|
let mut next_op = holder.as_ref();
|
|
|
|
|
|
if next_op.is_none() {
|
|
|
- next_op = find_next_op(self);
|
|
|
+ next_op = find_next(self);
|
|
|
}
|
|
|
|
|
|
- let mut pos = 0;
|
|
|
+ let mut consume_len = 0;
|
|
|
while find_op.is_none() && next_op.is_some() {
|
|
|
let op = next_op.take().unwrap();
|
|
|
- let interval = self.next_iv_before(index);
|
|
|
+ let interval = self
|
|
|
+ .next_iv_before(force_end)
|
|
|
+ .unwrap_or(Interval::new(0, 0));
|
|
|
+
|
|
|
+ // cache the op if the interval is empty. e.g. last_op_before(Some(0))
|
|
|
if interval.is_empty() {
|
|
|
self.next_op = Some(op.clone());
|
|
|
break;
|
|
|
}
|
|
|
-
|
|
|
find_op = op.shrink(interval);
|
|
|
- self.next_op = None;
|
|
|
-
|
|
|
let suffix = Interval::new(0, op.len()).suffix(interval);
|
|
|
- if !suffix.is_empty() {
|
|
|
+ if suffix.is_empty() {
|
|
|
+ self.next_op = None;
|
|
|
+ } else {
|
|
|
self.next_op = op.shrink(suffix);
|
|
|
}
|
|
|
|
|
|
- pos += interval.end;
|
|
|
+ consume_len += interval.end;
|
|
|
self.consume_count += interval.end;
|
|
|
self.consume_iv.start = self.consume_count;
|
|
|
|
|
|
+ // continue to find the op in next iteration
|
|
|
if find_op.is_none() {
|
|
|
- next_op = find_next_op(self);
|
|
|
+ next_op = find_next(self);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if find_op.is_some() && index.is_some() {
|
|
|
- // try to find the next op before the index if iter_char_count less than index
|
|
|
- let end = index.unwrap();
|
|
|
- if end > pos && self.has_next() {
|
|
|
- return self.last_op_before_index(Some(end - pos));
|
|
|
+ if find_op.is_some() && force_end.is_some() {
|
|
|
+ // try to find the next op before the index if consume_len less than index
|
|
|
+ let end = force_end.unwrap();
|
|
|
+ if end > consume_len && self.has_next() {
|
|
|
+ return self.next_with_len(Some(end - consume_len));
|
|
|
}
|
|
|
}
|
|
|
return find_op;
|
|
@@ -104,6 +109,19 @@ impl<'a> Cursor<'a> {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ fn next_iv_before(&self, force_end: Option<usize>) -> Option<Interval> {
|
|
|
+ let op = self.next_iter_op()?;
|
|
|
+ let start = self.consume_count;
|
|
|
+ let end = match force_end {
|
|
|
+ None => self.consume_count + op.len(),
|
|
|
+ Some(index) => self.consume_count + min(index, op.len()),
|
|
|
+ };
|
|
|
+
|
|
|
+ let intersect = Interval::new(start, end).intersect(self.consume_iv);
|
|
|
+ let interval = intersect.translate_neg(start);
|
|
|
+ Some(interval)
|
|
|
+ }
|
|
|
+
|
|
|
pub fn next_iter_op(&self) -> Option<&Operation> {
|
|
|
let mut next_op = self.next_op.as_ref();
|
|
|
if next_op.is_none() {
|
|
@@ -118,27 +136,9 @@ impl<'a> Cursor<'a> {
|
|
|
}
|
|
|
next_op
|
|
|
}
|
|
|
-
|
|
|
- fn next_iv_before(&self, index: Option<usize>) -> Interval {
|
|
|
- let next_op = self.next_iter_op();
|
|
|
- if next_op.is_none() {
|
|
|
- return Interval::new(0, 0);
|
|
|
- }
|
|
|
-
|
|
|
- let op = next_op.unwrap();
|
|
|
- let start = self.consume_count;
|
|
|
- let end = match index {
|
|
|
- None => self.consume_count + op.len(),
|
|
|
- Some(index) => self.consume_count + min(index, op.len()),
|
|
|
- };
|
|
|
-
|
|
|
- let intersect = Interval::new(start, end).intersect(self.consume_iv);
|
|
|
- let interval = intersect.translate_neg(start);
|
|
|
- interval
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
-fn find_next_op<'a>(cursor: &mut Cursor<'a>) -> Option<&'a Operation> {
|
|
|
+fn find_next<'a>(cursor: &mut OpCursor<'a>) -> Option<&'a Operation> {
|
|
|
match cursor.iter.next() {
|
|
|
None => None,
|
|
|
Some((o_index, op)) => {
|
|
@@ -150,15 +150,15 @@ fn find_next_op<'a>(cursor: &mut Cursor<'a>) -> Option<&'a Operation> {
|
|
|
|
|
|
type SeekResult = Result<(), OTError>;
|
|
|
pub trait Metric {
|
|
|
- fn seek(cursor: &mut Cursor, index: usize) -> SeekResult;
|
|
|
+ fn seek(cursor: &mut OpCursor, index: usize) -> SeekResult;
|
|
|
}
|
|
|
|
|
|
pub struct OpMetric {}
|
|
|
|
|
|
impl Metric for OpMetric {
|
|
|
- fn seek(cursor: &mut Cursor, index: usize) -> SeekResult {
|
|
|
+ fn seek(cursor: &mut OpCursor, index: usize) -> SeekResult {
|
|
|
let _ = check_bound(cursor.op_index, index)?;
|
|
|
- let mut seek_cursor = Cursor::new(cursor.delta, cursor.origin_iv);
|
|
|
+ let mut seek_cursor = OpCursor::new(cursor.delta, cursor.origin_iv);
|
|
|
let mut offset = 0;
|
|
|
while let Some((_, op)) = seek_cursor.iter.next() {
|
|
|
offset += op.len();
|
|
@@ -174,9 +174,9 @@ impl Metric for OpMetric {
|
|
|
pub struct CharMetric {}
|
|
|
|
|
|
impl Metric for CharMetric {
|
|
|
- fn seek(cursor: &mut Cursor, index: usize) -> SeekResult {
|
|
|
+ fn seek(cursor: &mut OpCursor, index: usize) -> SeekResult {
|
|
|
let _ = check_bound(cursor.consume_count, index)?;
|
|
|
- let _ = cursor.last_op_before_index(Some(index));
|
|
|
+ let _ = cursor.next_with_len(Some(index));
|
|
|
|
|
|
Ok(())
|
|
|
}
|