fix: pass delta test

This commit is contained in:
leeeon233 2023-03-05 17:11:48 +08:00
parent 0f2333b182
commit 344bbb1e34
2 changed files with 312 additions and 63 deletions

View file

@ -25,14 +25,24 @@ pub enum DeltaItem<Value, Meta> {
Delete(usize),
}
pub trait Meta: Debug + Default + Clone + PartialEq {
pub trait Meta: Debug + Clone + PartialEq {
fn none() -> Self;
fn empty() -> Self;
fn is_empty(&self) -> bool;
fn is_meta_none(&self) -> bool;
fn compose(self, other: Self) -> Self;
}
impl Meta for () {
fn none() -> Self {}
fn empty() -> Self {}
fn is_empty(&self) -> bool {
true
}
fn is_meta_none(&self) -> bool {
true
}
fn compose(self, _other: Self) -> Self {}
}
pub trait DeltaValue: Debug + HasLength + Sliceable + Clone + PartialEq {
@ -40,7 +50,7 @@ pub trait DeltaValue: Debug + HasLength + Sliceable + Clone + PartialEq {
}
impl<Value: DeltaValue, M: Meta> DeltaItem<Value, M> {
pub fn meta(&self) -> Option<&M> {
pub fn get_meta(&self) -> Option<&M> {
match self {
DeltaItem::Insert { meta, .. } => Some(meta),
DeltaItem::Retain { meta, .. } => Some(meta),
@ -48,6 +58,14 @@ impl<Value: DeltaValue, M: Meta> DeltaItem<Value, M> {
}
}
pub fn meta(&mut self, meta: M) {
match self {
DeltaItem::Insert { meta: m, .. } => *m = meta,
DeltaItem::Retain { meta: m, .. } => *m = meta,
_ => {}
}
}
pub fn is_retain(&self) -> bool {
matches!(self, Self::Retain { .. })
}
@ -102,26 +120,27 @@ impl<V: DeltaValue, M: Meta> DeltaIterator<V, M> {
if next_op.is_none() {
return DeltaItem::Retain {
len: usize::MAX,
meta: Default::default(),
meta: M::none(),
};
}
}
// TODO: Maybe can avoid cloning
let op = self.peek().unwrap().clone();
let op = self.peek().unwrap();
let op_length = op.content_len();
let offset = self.offset;
if length >= op_length - offset {
length = op_length - offset;
self.index += 1;
self.offset = 0;
} else {
self.offset += length;
}
let (index_delta, offset_delta) = {
if length >= op_length - offset {
length = op_length - offset;
(1, -(offset as isize))
} else {
(0, length as isize)
}
};
if op.is_delete() {
let ans = if op.is_delete() {
DeltaItem::Delete(length)
} else {
let mut ans_op = op;
let mut ans_op = op.clone();
if ans_op.is_retain() {
*ans_op.as_retain_mut().unwrap().0 = length;
} else if ans_op.is_insert() {
@ -129,7 +148,11 @@ impl<V: DeltaValue, M: Meta> DeltaIterator<V, M> {
*v = v.slice(offset, offset + length);
}
ans_op
}
};
self.index += index_delta;
self.offset = (self.offset as isize + offset_delta) as usize;
ans
}
fn rest(&mut self) -> SmallVec<[DeltaItem<V, M>; 2]> {
@ -212,12 +235,15 @@ impl<Value: DeltaValue, M: Meta> SeqDelta<Value, M> {
}
pub fn retain_with_meta(mut self, len: usize, meta: M) -> Self {
self.vec.push(DeltaItem::Retain { len, meta });
self.push(DeltaItem::Retain { len, meta });
self
}
pub fn insert_with_meta(mut self, value: Value, meta: M) -> Self {
self.vec.push(DeltaItem::Insert { value, meta });
pub fn insert_with_meta<V: Into<Value>>(mut self, value: V, meta: M) -> Self {
self.push(DeltaItem::Insert {
value: value.into(),
meta,
});
self
}
@ -225,7 +251,26 @@ impl<Value: DeltaValue, M: Meta> SeqDelta<Value, M> {
if len == 0 {
return self;
}
self.vec.push(DeltaItem::Delete(len));
self.push(DeltaItem::Delete(len));
self
}
pub fn retain(mut self, len: usize) -> Self {
if len == 0 {
return self;
}
self.push(DeltaItem::Retain {
len,
meta: M::none(),
});
self
}
pub fn insert<V: Into<Value>>(mut self, value: V) -> Self {
self.push(DeltaItem::Insert {
value: value.into(),
meta: M::none(),
});
self
}
@ -242,6 +287,10 @@ impl<Value: DeltaValue, M: Meta> SeqDelta<Value, M> {
// always prefer to insert first
if last_op.is_delete() && new_op.is_insert() {
index -= 1;
if index == 0 {
self.vec.insert(0, new_op);
return;
}
let _last_op = self.vec.get_mut(index - 1);
if let Some(_last_op_inner) = _last_op {
last_op = _last_op_inner;
@ -250,20 +299,20 @@ impl<Value: DeltaValue, M: Meta> SeqDelta<Value, M> {
return;
}
}
if new_op.meta() == last_op.meta() {
if new_op.get_meta() == last_op.get_meta() {
if new_op.is_insert() && last_op.is_insert() {
// TODO avoid cloning
let mut value = last_op.as_insert_mut().unwrap().0.clone();
value.extend(new_op.as_insert().unwrap().0.clone());
self.vec[index - 1] = DeltaItem::Insert {
value,
meta: new_op.meta().unwrap().clone(),
meta: new_op.get_meta().unwrap().clone(),
};
return;
} else if new_op.is_retain() && last_op.is_retain() {
self.vec[index - 1] = DeltaItem::Retain {
len: last_op.content_len() + new_op.content_len(),
meta: new_op.meta().unwrap().clone(),
meta: new_op.get_meta().unwrap().clone(),
};
return;
}
@ -303,9 +352,7 @@ impl<Value: DeltaValue, M: Meta> SeqDelta<Value, M> {
let mut ops = smallvec![];
let first_other = other_iter.peek();
if let Some(first_other) = first_other {
if first_other.is_retain()
&& (first_other.meta().is_none() || first_other.meta().unwrap().is_empty())
{
if first_other.is_retain() && first_other.get_meta().is_none() {
let mut first_left = first_other.content_len();
let mut first_this = this_iter.peek();
while let Some(first_this_inner) = first_this {
@ -334,29 +381,31 @@ impl<Value: DeltaValue, M: Meta> SeqDelta<Value, M> {
let this_op = this_iter.next(length);
let other_op = other_iter.next(length);
if other_op.is_retain() {
let new_op = if this_op.is_retain() {
let mut new_op = if this_op.is_retain() {
DeltaItem::Retain {
len: length,
meta: M::default(),
meta: M::none(),
}
} else {
this_op.clone()
};
// TODO: Meta compose
let meta = this_op
.get_meta()
.unwrap()
.clone()
.compose(other_op.get_meta().unwrap().clone());
new_op.meta(meta);
delta.push(new_op.clone());
if !other_iter.has_next() && delta.vec[delta.vec.len() - 1].eq(&new_op) {
let rest = SeqDelta {
vec: this_iter.rest(),
};
if !other_iter.has_next() && delta.vec.last().unwrap().eq(&new_op) {
let vec = this_iter.rest();
if vec.is_empty() {
return delta.chop();
}
let rest = SeqDelta { vec };
return delta.concat(rest).chop();
}
} else if other_op.is_delete() {
if this_op.is_retain() {
delta.push(other_op);
} else {
// this op is insert
continue;
}
} else if other_op.is_delete() && this_op.is_retain() {
delta.push(other_op);
}
}
}
@ -379,7 +428,7 @@ impl<Value: DeltaValue, M: Meta> SeqDelta<Value, M> {
fn chop(mut self) -> Self {
let last_op = self.vec.last();
if let Some(last_op) = last_op {
if last_op.is_retain() && last_op.meta().unwrap().is_empty() {
if last_op.is_retain() && last_op.get_meta().unwrap().is_meta_none() {
self.vec.pop();
}
}
@ -393,28 +442,6 @@ impl<Value: DeltaValue, M: Meta> Default for SeqDelta<Value, M> {
}
}
impl<Value: HasLength, M: Default + Meta> SeqDelta<Value, M> {
pub fn retain(mut self, len: usize) -> Self {
if len == 0 {
return self;
}
self.vec.push(DeltaItem::Retain {
len,
meta: Default::default(),
});
self
}
pub fn insert(mut self, value: Value) -> Self {
self.vec.push(DeltaItem::Insert {
value,
meta: Default::default(),
});
self
}
}
impl<T: Clone + PartialEq + Debug> DeltaValue for Vec<T> {
fn extend(&mut self, other: Self) {
<Vec<_> as std::iter::Extend<_>>::extend(self, other)
@ -429,7 +456,65 @@ impl DeltaValue for String {
#[cfg(test)]
mod test {
use super::{DeltaItem, SeqDelta};
use super::{DeltaItem, Meta, SeqDelta};
#[derive(Debug, PartialEq, Clone, Default)]
struct M {
bold: Option<bool>,
color: Option<()>,
}
type TestMeta = Option<M>;
impl Meta for TestMeta {
fn none() -> Self {
None
}
fn is_meta_none(&self) -> bool {
self.is_none()
}
fn empty() -> Self {
Some(M {
bold: None,
color: None,
})
}
fn is_empty(&self) -> bool {
self.is_some()
&& self.as_ref().unwrap().bold.is_none()
&& self.as_ref().unwrap().color.is_none()
}
fn compose(self, other: Self) -> Self {
if other.is_empty() {
None
} else if other.is_none() {
self
} else {
other
}
}
}
type TestDelta = SeqDelta<String, TestMeta>;
const BOLD_META: TestMeta = Some(M {
bold: Some(true),
color: None,
});
const COLOR_META: TestMeta = Some(M {
bold: None,
color: Some(()),
});
const EMPTY_META: TestMeta = Some(M {
bold: None,
color: None,
});
// const ALL_META: TestMeta = Some(M {
// bold: Some(true),
// color: Some(()),
// });
#[test]
fn delta_push() {
@ -454,4 +539,168 @@ mod test {
let b = SeqDelta::new().retain(1).insert("123".to_string());
assert_eq!(a.compose(b), SeqDelta::new().insert("112323".to_string()));
}
#[test]
fn insert_insert() {
let a = TestDelta::new().insert("a");
let b = TestDelta::new().insert("b");
assert_eq!(a.compose(b), TestDelta::new().insert("b").insert("a"));
}
#[test]
fn insert_retain() {
let a = TestDelta::new().insert("a");
let b = TestDelta::new().retain_with_meta(1, BOLD_META);
assert_eq!(
a.compose(b),
TestDelta::new().insert_with_meta("a", BOLD_META)
);
}
#[test]
fn insert_delete() {
let a = TestDelta::new().insert("a");
let b = TestDelta::new().delete(1);
assert_eq!(a.compose(b), TestDelta::new());
}
#[test]
fn delete_insert() {
let a = TestDelta::new().delete(1);
let b = TestDelta::new().insert("b");
assert_eq!(a.compose(b), TestDelta::new().insert("b").delete(1));
}
#[test]
fn delete_retain() {
let a = TestDelta::new().delete(1);
let b = TestDelta::new().retain_with_meta(1, BOLD_META);
assert_eq!(
a.compose(b),
TestDelta::new().delete(1).retain_with_meta(1, BOLD_META)
);
}
#[test]
fn delete_delete() {
let a = TestDelta::new().delete(1);
let b = TestDelta::new().delete(1);
assert_eq!(a.compose(b), TestDelta::new().delete(2));
}
#[test]
fn retain_insert() {
let a = TestDelta::new().retain_with_meta(1, BOLD_META);
let b = TestDelta::new().insert("b");
assert_eq!(
a.compose(b),
TestDelta::new().insert("b").retain_with_meta(1, BOLD_META)
);
}
#[test]
fn retain_retain() {
let a = TestDelta::new().retain_with_meta(1, BOLD_META);
let b = TestDelta::new().retain_with_meta(1, COLOR_META);
assert_eq!(
a.compose(b),
TestDelta::new().retain_with_meta(1, COLOR_META)
);
}
#[test]
fn retain_delete() {
let a = TestDelta::new().retain_with_meta(1, BOLD_META);
let b = TestDelta::new().delete(1);
assert_eq!(a.compose(b), TestDelta::new().delete(1));
}
#[test]
fn delete_entire() {
let a = TestDelta::new().retain(4).insert("abcde");
let b = TestDelta::new().delete(9);
assert_eq!(a.compose(b), TestDelta::new().delete(4));
}
#[test]
fn retain_more() {
let a = TestDelta::new().insert("abcde");
let b = TestDelta::new().retain(10);
assert_eq!(a.compose(b), TestDelta::new().insert("abcde"));
}
#[test]
fn remove_meta() {
let a = TestDelta::new().insert_with_meta("a", BOLD_META);
let b = TestDelta::new().retain_with_meta(1, EMPTY_META);
assert_eq!(a.compose(b), TestDelta::new().insert("a"));
}
#[test]
fn retain_start_opt() {
let a = TestDelta::new()
.insert_with_meta("a", BOLD_META)
.insert("b")
.insert_with_meta("c", BOLD_META)
.delete(1);
let b = TestDelta::new().retain(3).insert("d");
let expect = TestDelta::new()
.insert_with_meta("a", BOLD_META)
.insert("b")
.insert_with_meta("c", BOLD_META)
.insert("d")
.delete(1);
assert_eq!(a.compose(b), expect);
}
#[test]
fn retain_start_opt_split() {
let a = TestDelta::new()
.insert_with_meta("a", BOLD_META)
.insert("b")
.insert_with_meta("c", BOLD_META)
.retain(5)
.delete(1);
let b = TestDelta::new().retain(4).insert("d");
let expect = TestDelta::new()
.insert_with_meta("a", BOLD_META)
.insert("b")
.insert_with_meta("c", BOLD_META)
.retain(1)
.insert("d")
.retain(4)
.delete(1);
assert_eq!(a.compose(b), expect);
}
#[test]
fn retain_end_opt() {
let a = TestDelta::new()
.insert_with_meta("a", BOLD_META)
.insert("b")
.insert_with_meta("c", BOLD_META);
let b = TestDelta::new().delete(1);
let expect = TestDelta::new()
.insert("b")
.insert_with_meta("c", BOLD_META);
assert_eq!(a.compose(b), expect);
}
#[test]
fn retain_end_opt_join() {
let a = TestDelta::new()
.insert_with_meta("a", BOLD_META)
.insert("b")
.insert_with_meta("c", BOLD_META)
.insert("d")
.insert_with_meta("e", BOLD_META)
.insert("f");
let b = TestDelta::new().retain(1).delete(1);
let expect = TestDelta::new()
.insert_with_meta("ac", BOLD_META)
.insert("d")
.insert_with_meta("e", BOLD_META)
.insert("f");
assert_eq!(a.compose(b), expect);
}
}

View file

@ -187,7 +187,7 @@ impl TransactionOp {
container,
ops: SeqDelta::new()
.retain(pos)
.insert(values.into_iter().map(|v| v.into()).collect()),
.insert(values.into_iter().map(Value::Value).collect::<Vec<_>>()),
}
}