get next op length without consume it

This commit is contained in:
appflowy 2021-08-13 16:39:32 +08:00
parent 93cf9712dc
commit cd751a7b15
6 changed files with 95 additions and 39 deletions

View File

@ -50,8 +50,10 @@ impl Document {
// .view
// .format(&self.delta, attribute.clone(), interval)
// .unwrap();
// let a = self.delta.compose(&format_delta).unwrap();
// println!("{:?}", a);
//
// self.delta = self.record_change(&format_delta)?;
// Ok(())
self.update_with_attribute(attribute, interval)
}

View File

@ -86,7 +86,7 @@ impl FormatExt for ResolveInlineFormatExt {
let len = interval.size();
while cur < len && iter.has_next() {
let some_op = iter.next_op_with_length(len - cur);
let some_op = iter.next_op_with_len(len - cur);
if some_op.is_none() {
return Some(new_delta);
}

View File

@ -2,7 +2,7 @@ use crate::{
core::{Delta, Interval, Operation},
errors::{ErrorBuilder, OTError, OTErrorCode},
};
use std::{cmp::min, slice::Iter};
use std::{cmp::min, iter::Enumerate, slice::Iter};
#[derive(Debug)]
pub struct Cursor<'a> {
@ -11,7 +11,7 @@ pub struct Cursor<'a> {
pub(crate) next_iv: Interval,
pub(crate) c_index: usize,
pub(crate) o_index: usize,
iter: Iter<'a, Operation>,
iter: Enumerate<Iter<'a, Operation>>,
next_op: Option<Operation>,
}
@ -24,7 +24,7 @@ impl<'a> Cursor<'a> {
next_iv: interval,
c_index: 0,
o_index: 0,
iter: delta.ops.iter(),
iter: delta.ops.iter().enumerate(),
next_op: None,
};
cursor.descend(0);
@ -33,12 +33,12 @@ impl<'a> Cursor<'a> {
fn descend(&mut self, index: usize) {
self.next_iv.start += index;
if self.c_index >= self.next_iv.start {
return;
}
while let Some(op) = self.iter.next() {
self.o_index += 1;
while let Some((o_index, op)) = self.iter.next() {
self.o_index = o_index;
let start = self.c_index;
let end = start + op.length();
let intersect = Interval::new(start, end).intersect(self.next_iv);
@ -51,50 +51,69 @@ impl<'a> Cursor<'a> {
}
}
pub fn next_op_with_length(&mut self, length: Option<usize>) -> Option<Operation> {
let mut find_op = None;
let next_op = self.next_op.take();
let mut next_op = next_op.as_ref();
if next_op.is_none() {
next_op = self.iter.next();
self.o_index += 1;
}
pub fn next_interval(&self) -> Interval { self.next_op_interval_with_len(None) }
fn next_op_interval_with_len(&self, force_len: Option<usize>) -> Interval {
let op = self
.next_op
.as_ref()
.unwrap_or(&self.delta.ops[self.o_index]);
while find_op.is_none() && next_op.is_some() {
let op = next_op.unwrap();
let start = self.c_index;
let end = match length {
let end = match force_len {
None => self.c_index + op.length(),
Some(length) => self.c_index + min(length, op.length()),
Some(force_len) => self.c_index + min(force_len, op.length()),
};
let intersect = Interval::new(start, end).intersect(self.next_iv);
let interval = intersect.translate_neg(start);
interval
}
let op_interval = Interval::new(0, op.length());
let suffix = op_interval.suffix(interval);
pub fn next_op_with_len(&mut self, force_len: Option<usize>) -> Option<Operation> {
let mut find_op = None;
let next_op = self.next_op.take();
let mut next_op = next_op.as_ref();
if next_op.is_none() {
next_op = find_next_op(self);
}
while find_op.is_none() && next_op.is_some() {
let op = next_op.take().unwrap();
let interval = self.next_op_interval_with_len(force_len);
find_op = op.shrink(interval);
let suffix = Interval::new(0, op.length()).suffix(interval);
if !suffix.is_empty() {
self.next_op = op.shrink(suffix);
}
self.c_index = intersect.end;
self.next_iv.start = intersect.end;
self.c_index += interval.end;
self.next_iv.start = self.c_index;
if find_op.is_none() {
next_op = self.iter.next();
next_op = find_next_op(self);
}
}
find_op
}
pub fn next_op(&mut self) -> Option<Operation> { self.next_op_with_length(None) }
pub fn next_op(&mut self) -> Option<Operation> { self.next_op_with_len(None) }
pub fn has_next(&self) -> bool { self.c_index < self.next_iv.end }
}
fn find_next_op<'a>(cursor: &mut Cursor<'a>) -> Option<&'a Operation> {
match cursor.iter.next() {
None => None,
Some((o_index, op)) => {
cursor.o_index = o_index;
Some(op)
},
}
}
type SeekResult = Result<(), OTError>;
pub trait Metric {
fn seek(cursor: &mut Cursor, index: usize) -> SeekResult;
@ -107,7 +126,7 @@ impl Metric for OpMetric {
let _ = check_bound(cursor.o_index, index)?;
let mut temp_cursor = Cursor::new(cursor.delta, cursor.origin_iv);
let mut offset = 0;
while let Some(op) = temp_cursor.iter.next() {
while let Some((_, op)) = temp_cursor.iter.next() {
offset += op.length();
if offset > index {
break;
@ -123,7 +142,7 @@ pub struct CharMetric {}
impl Metric for CharMetric {
fn seek(cursor: &mut Cursor, index: usize) -> SeekResult {
let _ = check_bound(cursor.c_index, index)?;
let _ = cursor.next_op_with_length(Some(index));
let _ = cursor.next_op_with_len(Some(index));
Ok(())
}
}

View File

@ -25,8 +25,10 @@ impl<'a> DeltaIter<'a> {
pub fn next_op(&mut self) -> Option<Operation> { self.cursor.next_op() }
pub fn next_op_with_length(&mut self, length: usize) -> Option<Operation> {
self.cursor.next_op_with_length(Some(length))
pub fn next_op_len(&self) -> usize { self.cursor.next_interval().size() }
pub fn next_op_with_len(&mut self, length: usize) -> Option<Operation> {
self.cursor.next_op_with_len(Some(length))
}
pub fn seek<M: Metric>(&mut self, index: usize) -> Result<(), OTError> {

View File

@ -52,6 +52,23 @@ fn delta_insert_text_with_attr() {
OpTester::new().run_script(ops);
}
#[test]
fn delta_add_bold() {
let ops = vec![
Insert(0, "123456", 0),
Bold(0, Interval::new(3, 5), true),
AssertOpsJson(
0,
r#"[
{"insert":"123"},
{"insert":"45","attributes":{"bold":"true"}},
{"insert":"6"}
]"#,
),
];
OpTester::new().run_script(ops);
}
#[test]
fn delta_add_bold_and_invert_all() {
let ops = vec![

View File

@ -148,7 +148,7 @@ fn delta_get_ops_in_interval_7() {
let mut iter_2 = DeltaIter::new(&delta);
assert_eq!(
iter_2.next_op_with_length(2).unwrap(),
iter_2.next_op_with_len(2).unwrap(),
Builder::insert("12").build()
);
assert_eq!(iter_2.next_op().unwrap(), Builder::insert("345").build());
@ -175,7 +175,7 @@ fn delta_seek_2() {
let mut iter = DeltaIter::new(&delta);
assert_eq!(
iter.next_op_with_length(1).unwrap(),
iter.next_op_with_len(1).unwrap(),
Builder::insert("1").build()
);
}
@ -187,21 +187,21 @@ fn delta_seek_3() {
let mut iter = DeltaIter::new(&delta);
assert_eq!(
iter.next_op_with_length(2).unwrap(),
iter.next_op_with_len(2).unwrap(),
Builder::insert("12").build()
);
assert_eq!(
iter.next_op_with_length(2).unwrap(),
iter.next_op_with_len(2).unwrap(),
Builder::insert("34").build()
);
assert_eq!(
iter.next_op_with_length(2).unwrap(),
iter.next_op_with_len(2).unwrap(),
Builder::insert("5").build()
);
assert_eq!(iter.next_op_with_length(1), None);
assert_eq!(iter.next_op_with_len(1), None);
}
#[test]
@ -212,11 +212,27 @@ fn delta_seek_4() {
let mut iter = DeltaIter::new(&delta);
iter.seek::<CharMetric>(3);
assert_eq!(
iter.next_op_with_length(2).unwrap(),
iter.next_op_with_len(2).unwrap(),
Builder::insert("45").build()
);
}
#[test]
fn delta_next_op_len_test() {
let mut delta = Delta::default();
delta.add(Builder::insert("12345").build());
let mut iter = DeltaIter::new(&delta);
iter.seek::<CharMetric>(3);
assert_eq!(iter.next_op_len(), 2);
assert_eq!(
iter.next_op_with_len(1).unwrap(),
Builder::insert("4").build()
);
assert_eq!(iter.next_op_len(), 1);
assert_eq!(iter.next_op().unwrap(), Builder::insert("5").build());
}
#[test]
fn lengths() {
let mut delta = Delta::default();