670 lines
26 KiB
Rust
Raw Normal View History

2021-08-04 07:55:54 +08:00
use crate::{
2021-08-04 15:09:04 +08:00
core::{attributes::*, operation::*, Interval},
2021-08-05 22:52:19 +08:00
errors::{ErrorBuilder, OTError, OTErrorCode},
2021-08-04 07:55:54 +08:00
};
2021-07-31 20:53:45 +08:00
use bytecount::num_chars;
2021-08-06 22:25:09 +08:00
use std::{
cmp::{max, min, Ordering},
fmt,
iter::FromIterator,
str::FromStr,
};
2021-07-31 20:53:45 +08:00
#[derive(Clone, Debug, PartialEq)]
pub struct Delta {
pub ops: Vec<Operation>,
pub base_len: usize,
pub target_len: usize,
}
impl Default for Delta {
fn default() -> Self {
Self {
ops: Vec::new(),
base_len: 0,
target_len: 0,
}
}
}
2021-08-01 10:45:15 +08:00
impl FromStr for Delta {
type Err = ();
fn from_str(s: &str) -> Result<Delta, Self::Err> {
let mut delta = Delta::with_capacity(1);
delta.add(Operation::Insert(s.into()));
Ok(delta)
}
}
impl<T: AsRef<str>> From<T> for Delta {
fn from(s: T) -> Delta { Delta::from_str(s.as_ref()).unwrap() }
}
2021-08-03 23:13:20 +08:00
impl fmt::Display for Delta {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// f.write_str(&serde_json::to_string(self).unwrap_or("".to_owned()))?;
f.write_str("[ ")?;
for op in &self.ops {
f.write_fmt(format_args!("{} ", op));
}
f.write_str("]")?;
2021-08-03 23:13:20 +08:00
Ok(())
}
}
2021-08-01 10:45:15 +08:00
impl FromIterator<Operation> for Delta {
fn from_iter<T: IntoIterator<Item = Operation>>(ops: T) -> Self {
let mut operations = Delta::default();
for op in ops {
operations.add(op);
}
operations
}
}
2021-07-31 20:53:45 +08:00
impl Delta {
pub fn new() -> Self { Self::default() }
2021-07-31 20:53:45 +08:00
#[inline]
pub fn with_capacity(capacity: usize) -> Self {
Self {
ops: Vec::with_capacity(capacity),
base_len: 0,
target_len: 0,
}
}
2021-08-01 14:39:30 +08:00
pub fn add(&mut self, op: Operation) {
2021-08-01 10:45:15 +08:00
match op {
Operation::Delete(i) => self.delete(i),
2021-08-01 14:39:30 +08:00
Operation::Insert(i) => self.insert(&i.s, i.attributes),
2021-08-04 15:09:04 +08:00
Operation::Retain(r) => self.retain(r.n, r.attributes),
2021-08-01 10:45:15 +08:00
}
}
2021-07-31 20:53:45 +08:00
2021-08-06 23:06:27 +08:00
pub fn delete(&mut self, n: usize) {
2021-07-31 20:53:45 +08:00
if n == 0 {
return;
}
self.base_len += n as usize;
2021-08-01 10:45:15 +08:00
if let Some(Operation::Delete(n_last)) = self.ops.last_mut() {
*n_last += n;
} else {
2021-08-08 22:29:16 +08:00
self.ops.push(Builder::delete(n).build());
2021-07-31 20:53:45 +08:00
}
}
2021-08-03 16:20:25 +08:00
pub fn insert(&mut self, s: &str, attrs: Attributes) {
2021-07-31 20:53:45 +08:00
if s.is_empty() {
return;
}
2021-08-01 10:45:15 +08:00
2021-08-01 16:39:32 +08:00
self.target_len += num_chars(s.as_bytes());
2021-08-01 10:45:15 +08:00
let new_last = match self.ops.as_mut_slice() {
[.., Operation::Insert(insert)] => {
2021-08-01 16:39:32 +08:00
//
2021-08-04 15:09:04 +08:00
insert.merge_or_new_op(s, attrs)
2021-07-31 20:53:45 +08:00
},
[.., Operation::Insert(pre_insert), Operation::Delete(_)] => {
2021-08-01 16:39:32 +08:00
//
2021-08-04 15:09:04 +08:00
pre_insert.merge_or_new_op(s, attrs)
2021-07-31 20:53:45 +08:00
},
2021-08-01 10:45:15 +08:00
[.., op_last @ Operation::Delete(_)] => {
2021-07-31 20:53:45 +08:00
let new_last = op_last.clone();
2021-08-08 22:29:16 +08:00
*op_last = Builder::insert(s).attributes(attrs).build();
2021-08-01 16:39:32 +08:00
Some(new_last)
2021-07-31 20:53:45 +08:00
},
2021-08-08 22:29:16 +08:00
_ => Some(Builder::insert(s).attributes(attrs).build()),
2021-07-31 20:53:45 +08:00
};
2021-08-01 16:39:32 +08:00
match new_last {
None => {},
Some(new_last) => self.ops.push(new_last),
}
2021-07-31 20:53:45 +08:00
}
2021-08-06 23:06:27 +08:00
pub fn retain(&mut self, n: usize, attrs: Attributes) {
2021-07-31 20:53:45 +08:00
if n == 0 {
return;
}
self.base_len += n as usize;
self.target_len += n as usize;
if let Some(Operation::Retain(retain)) = self.ops.last_mut() {
2021-08-04 15:09:04 +08:00
if let Some(new_op) = retain.merge_or_new_op(n, attrs) {
self.ops.push(new_op);
2021-08-01 16:39:32 +08:00
}
2021-08-01 10:45:15 +08:00
} else {
2021-08-08 22:29:16 +08:00
self.ops.push(Builder::retain(n).attributes(attrs).build());
2021-07-31 20:53:45 +08:00
}
}
/// Merges the operation with `other` into one operation while preserving
/// the changes of both. Or, in other words, for each input string S and a
/// pair of consecutive operations A and B.
/// `apply(apply(S, A), B) = apply(S, compose(A, B))`
/// must hold.
///
/// # Error
///
/// Returns an `OTError` if the operations are not composable due to length
/// conflicts.
pub fn compose(&self, other: &Self) -> Result<Self, OTError> {
if self.target_len != other.base_len {
2021-08-05 22:52:19 +08:00
return Err(ErrorBuilder::new(OTErrorCode::IncompatibleLength).build());
2021-07-31 20:53:45 +08:00
}
let mut new_delta = Delta::default();
let mut ops1 = self.ops.iter().cloned();
let mut ops2 = other.ops.iter().cloned();
2021-08-01 10:45:15 +08:00
let mut next_op1 = ops1.next();
let mut next_op2 = ops2.next();
2021-07-31 20:53:45 +08:00
loop {
2021-08-01 10:45:15 +08:00
match (&next_op1, &next_op2) {
2021-07-31 20:53:45 +08:00
(None, None) => break,
2021-08-01 10:45:15 +08:00
(Some(Operation::Delete(i)), _) => {
2021-07-31 20:53:45 +08:00
new_delta.delete(*i);
2021-08-01 10:45:15 +08:00
next_op1 = ops1.next();
2021-07-31 20:53:45 +08:00
},
(_, Some(Operation::Insert(o_insert))) => {
new_delta.insert(&o_insert.s, o_insert.attributes.clone());
2021-08-01 10:45:15 +08:00
next_op2 = ops2.next();
2021-07-31 20:53:45 +08:00
},
(None, _) | (_, None) => {
2021-08-05 22:52:19 +08:00
return Err(ErrorBuilder::new(OTErrorCode::IncompatibleLength).build());
2021-07-31 20:53:45 +08:00
},
(Some(Operation::Retain(retain)), Some(Operation::Retain(o_retain))) => {
let composed_attrs = compose_operation(&next_op1, &next_op2);
2021-08-02 23:08:24 +08:00
log::debug!(
"[retain:{} - retain:{}]: {:?}",
2021-08-04 15:09:04 +08:00
retain.n,
o_retain.n,
2021-08-02 23:08:24 +08:00
composed_attrs
);
match retain.cmp(&o_retain) {
2021-07-31 23:22:17 +08:00
Ordering::Less => {
2021-08-04 15:09:04 +08:00
new_delta.retain(retain.n, composed_attrs);
next_op2 = Some(
Builder::retain(o_retain.n - retain.n)
.attributes(o_retain.attributes.clone())
.build(),
);
2021-08-01 10:45:15 +08:00
next_op1 = ops1.next();
2021-07-31 23:22:17 +08:00
},
std::cmp::Ordering::Equal => {
2021-08-04 15:09:04 +08:00
new_delta.retain(retain.n, composed_attrs);
2021-08-01 10:45:15 +08:00
next_op1 = ops1.next();
next_op2 = ops2.next();
2021-07-31 23:22:17 +08:00
},
std::cmp::Ordering::Greater => {
2021-08-04 15:09:04 +08:00
new_delta.retain(o_retain.n, composed_attrs);
2021-08-08 22:29:16 +08:00
next_op1 = Some(Builder::retain(retain.n - o_retain.n).build());
2021-08-01 10:45:15 +08:00
next_op2 = ops2.next();
2021-07-31 23:22:17 +08:00
},
}
2021-07-31 20:53:45 +08:00
},
(Some(Operation::Insert(insert)), Some(Operation::Delete(o_num))) => {
2021-08-06 23:06:27 +08:00
match (num_chars(insert.as_bytes()) as usize).cmp(o_num) {
2021-07-31 20:53:45 +08:00
Ordering::Less => {
2021-08-01 10:45:15 +08:00
next_op2 = Some(
2021-08-08 22:29:16 +08:00
Builder::delete(*o_num - num_chars(insert.as_bytes()) as usize)
2021-08-03 16:20:25 +08:00
.attributes(insert.attributes.clone())
.build(),
2021-07-31 20:53:45 +08:00
);
2021-08-01 10:45:15 +08:00
next_op1 = ops1.next();
2021-07-31 20:53:45 +08:00
},
Ordering::Equal => {
2021-08-01 10:45:15 +08:00
next_op1 = ops1.next();
next_op2 = ops2.next();
2021-07-31 20:53:45 +08:00
},
Ordering::Greater => {
2021-08-01 10:45:15 +08:00
next_op1 = Some(
2021-08-08 22:29:16 +08:00
Builder::insert(
&insert.chars().skip(*o_num as usize).collect::<String>(),
2021-08-01 16:39:32 +08:00
)
.build(),
2021-07-31 20:53:45 +08:00
);
2021-08-01 10:45:15 +08:00
next_op2 = ops2.next();
2021-07-31 20:53:45 +08:00
},
}
},
(Some(Operation::Insert(insert)), Some(Operation::Retain(o_retain))) => {
let mut composed_attrs = compose_operation(&next_op1, &next_op2);
composed_attrs = composed_attrs.apply_rule();
2021-08-02 23:08:24 +08:00
log::debug!(
"compose: [{} - {}], composed_attrs: {}",
insert,
o_retain,
2021-08-02 23:08:24 +08:00
composed_attrs
);
match (insert.num_chars()).cmp(o_retain) {
2021-07-31 20:53:45 +08:00
Ordering::Less => {
new_delta.insert(&insert.s, composed_attrs.clone());
next_op2 = Some(
2021-08-08 22:29:16 +08:00
Builder::retain(o_retain.n - insert.num_chars())
.attributes(o_retain.attributes.clone())
.build(),
);
2021-08-01 10:45:15 +08:00
next_op1 = ops1.next();
2021-07-31 20:53:45 +08:00
},
Ordering::Equal => {
new_delta.insert(&insert.s, composed_attrs);
2021-08-01 10:45:15 +08:00
next_op1 = ops1.next();
next_op2 = ops2.next();
2021-07-31 20:53:45 +08:00
},
Ordering::Greater => {
2021-08-01 10:45:15 +08:00
let chars = &mut insert.chars();
new_delta.insert(
2021-08-04 15:09:04 +08:00
&chars.take(o_retain.n as usize).collect::<String>(),
composed_attrs,
);
2021-08-03 16:20:25 +08:00
next_op1 = Some(
2021-08-08 22:29:16 +08:00
Builder::insert(&chars.collect::<String>())
// consider this situation:
// [insert:12345678 - retain:4],
// the attributes of "5678" should be empty and the following
// retain will bringing the attributes.
2021-08-03 16:20:25 +08:00
.attributes(Attributes::Empty)
.build(),
);
2021-08-01 10:45:15 +08:00
next_op2 = ops2.next();
2021-07-31 20:53:45 +08:00
},
}
},
(Some(Operation::Retain(retain)), Some(Operation::Delete(o_num))) => {
match retain.cmp(&o_num) {
Ordering::Less => {
2021-08-04 15:09:04 +08:00
new_delta.delete(retain.n);
2021-08-08 22:29:16 +08:00
next_op2 = Some(Builder::delete(*o_num - retain.n).build());
next_op1 = ops1.next();
},
Ordering::Equal => {
new_delta.delete(*o_num);
next_op2 = ops2.next();
next_op1 = ops1.next();
},
Ordering::Greater => {
new_delta.delete(*o_num);
2021-08-08 22:29:16 +08:00
next_op1 = Some(Builder::retain(retain.n - *o_num).build());
next_op2 = ops2.next();
},
}
2021-07-31 20:53:45 +08:00
},
};
}
Ok(new_delta)
}
/// Transforms two operations A and B that happened concurrently and
/// produces two operations A' and B' (in an array) such that
/// `apply(apply(S, A), B') = apply(apply(S, B), A')`.
/// This function is the heart of OT.
///
/// # Error
///
/// Returns an `OTError` if the operations cannot be transformed due to
/// length conflicts.
pub fn transform(&self, other: &Self) -> Result<(Self, Self), OTError> {
if self.base_len != other.base_len {
2021-08-05 22:52:19 +08:00
return Err(ErrorBuilder::new(OTErrorCode::IncompatibleLength).build());
2021-07-31 20:53:45 +08:00
}
let mut a_prime = Delta::default();
let mut b_prime = Delta::default();
let mut ops1 = self.ops.iter().cloned();
let mut ops2 = other.ops.iter().cloned();
2021-08-01 10:45:15 +08:00
let mut next_op1 = ops1.next();
let mut next_op2 = ops2.next();
2021-07-31 20:53:45 +08:00
loop {
2021-08-01 10:45:15 +08:00
match (&next_op1, &next_op2) {
2021-07-31 20:53:45 +08:00
(None, None) => break,
2021-08-01 10:45:15 +08:00
(Some(Operation::Insert(insert)), _) => {
// let composed_attrs = transform_attributes(&next_op1, &next_op2, true);
a_prime.insert(&insert.s, insert.attributes.clone());
b_prime.retain(insert.num_chars(), insert.attributes.clone());
2021-08-01 10:45:15 +08:00
next_op1 = ops1.next();
2021-07-31 20:53:45 +08:00
},
(_, Some(Operation::Insert(o_insert))) => {
let composed_attrs = transform_operation(&next_op1, &next_op2);
a_prime.retain(o_insert.num_chars(), composed_attrs.clone());
2021-08-03 16:20:25 +08:00
b_prime.insert(&o_insert.s, composed_attrs);
2021-08-01 10:45:15 +08:00
next_op2 = ops2.next();
2021-07-31 20:53:45 +08:00
},
(None, _) => {
2021-08-05 22:52:19 +08:00
return Err(ErrorBuilder::new(OTErrorCode::IncompatibleLength).build());
2021-07-31 20:53:45 +08:00
},
(_, None) => {
2021-08-05 22:52:19 +08:00
return Err(ErrorBuilder::new(OTErrorCode::IncompatibleLength).build());
2021-07-31 20:53:45 +08:00
},
(Some(Operation::Retain(retain)), Some(Operation::Retain(o_retain))) => {
let composed_attrs = transform_operation(&next_op1, &next_op2);
match retain.cmp(&o_retain) {
2021-07-31 20:53:45 +08:00
Ordering::Less => {
2021-08-04 15:09:04 +08:00
a_prime.retain(retain.n, composed_attrs.clone());
b_prime.retain(retain.n, composed_attrs.clone());
2021-08-08 22:29:16 +08:00
next_op2 = Some(Builder::retain(o_retain.n - retain.n).build());
2021-08-01 10:45:15 +08:00
next_op1 = ops1.next();
2021-07-31 20:53:45 +08:00
},
Ordering::Equal => {
2021-08-04 15:09:04 +08:00
a_prime.retain(retain.n, composed_attrs.clone());
b_prime.retain(retain.n, composed_attrs.clone());
2021-08-01 10:45:15 +08:00
next_op1 = ops1.next();
next_op2 = ops2.next();
2021-07-31 20:53:45 +08:00
},
Ordering::Greater => {
2021-08-04 15:09:04 +08:00
a_prime.retain(o_retain.n, composed_attrs.clone());
b_prime.retain(o_retain.n, composed_attrs.clone());
2021-08-08 22:29:16 +08:00
next_op1 = Some(Builder::retain(retain.n - o_retain.n).build());
2021-08-01 10:45:15 +08:00
next_op2 = ops2.next();
2021-07-31 20:53:45 +08:00
},
};
},
2021-08-01 10:45:15 +08:00
(Some(Operation::Delete(i)), Some(Operation::Delete(j))) => match i.cmp(&j) {
2021-07-31 20:53:45 +08:00
Ordering::Less => {
2021-08-08 22:29:16 +08:00
next_op2 = Some(Builder::delete(*j - *i).build());
2021-08-01 10:45:15 +08:00
next_op1 = ops1.next();
2021-07-31 20:53:45 +08:00
},
Ordering::Equal => {
2021-08-01 10:45:15 +08:00
next_op1 = ops1.next();
next_op2 = ops2.next();
2021-07-31 20:53:45 +08:00
},
Ordering::Greater => {
2021-08-08 22:29:16 +08:00
next_op1 = Some(Builder::delete(*i - *j).build());
2021-08-01 10:45:15 +08:00
next_op2 = ops2.next();
2021-07-31 20:53:45 +08:00
},
},
(Some(Operation::Delete(i)), Some(Operation::Retain(o_retain))) => {
match i.cmp(&o_retain) {
2021-07-31 20:53:45 +08:00
Ordering::Less => {
a_prime.delete(*i);
2021-08-08 22:29:16 +08:00
next_op2 = Some(Builder::retain(o_retain.n - *i).build());
2021-08-01 10:45:15 +08:00
next_op1 = ops1.next();
2021-07-31 20:53:45 +08:00
},
Ordering::Equal => {
a_prime.delete(*i);
2021-08-01 10:45:15 +08:00
next_op1 = ops1.next();
next_op2 = ops2.next();
2021-07-31 20:53:45 +08:00
},
Ordering::Greater => {
2021-08-04 15:09:04 +08:00
a_prime.delete(o_retain.n);
2021-08-08 22:29:16 +08:00
next_op1 = Some(Builder::delete(*i - o_retain.n).build());
2021-08-01 10:45:15 +08:00
next_op2 = ops2.next();
2021-07-31 20:53:45 +08:00
},
};
},
(Some(Operation::Retain(retain)), Some(Operation::Delete(j))) => {
match retain.cmp(&j) {
2021-07-31 20:53:45 +08:00
Ordering::Less => {
2021-08-04 15:09:04 +08:00
b_prime.delete(retain.n);
2021-08-08 22:29:16 +08:00
next_op2 = Some(Builder::delete(*j - retain.n).build());
2021-08-01 10:45:15 +08:00
next_op1 = ops1.next();
2021-07-31 20:53:45 +08:00
},
Ordering::Equal => {
2021-08-04 15:09:04 +08:00
b_prime.delete(retain.n);
2021-08-01 10:45:15 +08:00
next_op1 = ops1.next();
next_op2 = ops2.next();
2021-07-31 20:53:45 +08:00
},
Ordering::Greater => {
b_prime.delete(*j);
2021-08-08 22:29:16 +08:00
next_op1 = Some(Builder::retain(retain.n - *j).build());
2021-08-01 10:45:15 +08:00
next_op2 = ops2.next();
2021-07-31 20:53:45 +08:00
},
};
},
}
}
Ok((a_prime, b_prime))
}
/// Applies an operation to a string, returning a new string.
///
/// # Error
///
/// Returns an error if the operation cannot be applied due to length
/// conflicts.
pub fn apply(&self, s: &str) -> Result<String, OTError> {
if num_chars(s.as_bytes()) != self.base_len {
2021-08-05 22:52:19 +08:00
return Err(ErrorBuilder::new(OTErrorCode::IncompatibleLength).build());
2021-07-31 20:53:45 +08:00
}
let mut new_s = String::new();
let chars = &mut s.chars();
for op in &self.ops {
2021-08-01 10:45:15 +08:00
match &op {
Operation::Retain(retain) => {
2021-08-04 15:09:04 +08:00
for c in chars.take(retain.n as usize) {
2021-07-31 20:53:45 +08:00
new_s.push(c);
}
},
2021-08-01 10:45:15 +08:00
Operation::Delete(delete) => {
2021-07-31 20:53:45 +08:00
for _ in 0..*delete {
chars.next();
}
},
2021-08-01 10:45:15 +08:00
Operation::Insert(insert) => {
new_s += &insert.s;
2021-07-31 20:53:45 +08:00
},
}
}
Ok(new_s)
}
/// Computes the inverse of an operation. The inverse of an operation is the
/// operation that reverts the effects of the operation
2021-08-06 22:25:09 +08:00
pub fn invert_str(&self, s: &str) -> Self {
2021-08-01 10:45:15 +08:00
let mut inverted = Delta::default();
2021-07-31 20:53:45 +08:00
let chars = &mut s.chars();
for op in &self.ops {
2021-08-01 10:45:15 +08:00
match &op {
Operation::Retain(retain) => {
2021-08-04 15:09:04 +08:00
inverted.retain(retain.n, Attributes::Follow);
// TODO: use advance_by instead, but it's unstable now
// chars.advance_by(retain.num)
for _ in 0..retain.n {
2021-07-31 20:53:45 +08:00
chars.next();
}
},
2021-08-01 10:45:15 +08:00
Operation::Insert(insert) => {
inverted.delete(insert.num_chars());
2021-07-31 20:53:45 +08:00
},
2021-08-01 10:45:15 +08:00
Operation::Delete(delete) => {
inverted.insert(
2021-07-31 23:22:17 +08:00
&chars.take(*delete as usize).collect::<String>(),
op.get_attributes(),
2021-07-31 23:22:17 +08:00
);
2021-07-31 20:53:45 +08:00
},
}
}
2021-08-01 10:45:15 +08:00
inverted
2021-07-31 20:53:45 +08:00
}
2021-08-06 22:25:09 +08:00
pub fn invert(&self, other: &Delta) -> Delta {
2021-08-04 15:09:04 +08:00
let mut inverted = Delta::default();
if other.is_empty() {
return inverted;
}
log::debug!("🌜Calculate invert delta");
log::debug!("current: {}", self);
log::debug!("other: {}", other);
2021-08-04 15:09:04 +08:00
let mut index = 0;
for op in &self.ops {
2021-08-04 22:33:16 +08:00
let len: usize = op.length() as usize;
2021-08-04 15:09:04 +08:00
match op {
2021-08-08 22:29:16 +08:00
Operation::Delete(n) => {
invert_from_other(&mut inverted, other, op, index, index + *n);
2021-08-04 22:33:16 +08:00
index += len;
2021-08-04 15:09:04 +08:00
},
Operation::Retain(_) => {
2021-08-05 11:30:29 +08:00
match op.has_attribute() {
true => invert_from_other(&mut inverted, other, op, index, index + len),
2021-08-08 22:29:16 +08:00
false => {
log::debug!(
"invert retain: {} by retain {} {}",
op,
len,
op.get_attributes()
);
2021-08-08 22:29:16 +08:00
inverted.retain(len as usize, op.get_attributes())
},
2021-08-04 15:09:04 +08:00
}
2021-08-04 22:33:16 +08:00
index += len;
2021-08-04 15:09:04 +08:00
},
Operation::Insert(_) => {
log::debug!("invert insert: {} by delete {}", op, len);
2021-08-06 23:06:27 +08:00
inverted.delete(len as usize);
2021-08-04 15:09:04 +08:00
},
}
}
log::debug!("🌛invert result: {}", inverted);
2021-08-04 15:09:04 +08:00
inverted
}
2021-07-31 20:53:45 +08:00
/// Checks if this operation has no effect.
#[inline]
pub fn is_noop(&self) -> bool {
2021-08-01 10:45:15 +08:00
match self.ops.as_slice() {
2021-07-31 20:53:45 +08:00
[] => true,
2021-08-01 10:45:15 +08:00
[Operation::Retain(_)] => true,
2021-07-31 20:53:45 +08:00
_ => false,
}
}
2021-08-01 10:45:15 +08:00
pub fn is_empty(&self) -> bool { self.ops.is_empty() }
2021-07-31 23:22:17 +08:00
2021-08-08 22:29:16 +08:00
pub fn ops_in_interval(&self, mut interval: Interval) -> Vec<Operation> {
log::debug!("try get ops in delta: {} at {}", self, interval);
2021-08-04 15:09:04 +08:00
let mut ops: Vec<Operation> = Vec::with_capacity(self.ops.len());
let mut ops_iter = self.ops.iter();
2021-08-08 22:29:16 +08:00
let mut maybe_next_op = ops_iter.next();
let mut offset: usize = 0;
while maybe_next_op.is_some() {
let next_op = maybe_next_op.take().unwrap();
if offset < interval.start {
let next_op_i = Interval::new(offset, offset + next_op.length());
let intersect = next_op_i.intersect(interval);
if intersect.is_empty() {
offset += next_op_i.size();
} else {
if let Some(new_op) = next_op.shrink(intersect.translate_neg(offset)) {
// shrink the op to fit the intersect range
// ┌──────────────┐
// │ 1 2 3 4 5 6 │
// └───────▲───▲──┘
// │ │
// [3, 5)
// op = "45"
2021-08-08 22:29:16 +08:00
ops.push(new_op);
2021-08-06 22:25:09 +08:00
}
offset = intersect.end;
interval = Interval::new(offset, interval.end);
2021-08-08 22:29:16 +08:00
}
} else {
// the interval passed in the shrink function is base on the op not the delta.
if let Some(new_op) = next_op.shrink(interval.translate_neg(offset)) {
ops.push(new_op);
2021-08-04 15:09:04 +08:00
}
// for example: extract the ops from three insert ops with interval [2,5). the
// interval size is larger than the op. Moving the offset to extract each part.
// Each step would be the small value between interval.size() and
// next_op.length(). Checkout the delta_get_ops_in_interval_4 for more details.
//
// ┌──────┐ ┌──────┐ ┌──────┐
// │ 1 2 │ │ 3 4 │ │ 5 6 │
// └──────┘ └─▲────┘ └───▲──┘
// │ [2, 5) │
//
2021-08-08 22:29:16 +08:00
offset += min(interval.size(), next_op.length());
interval = Interval::new(offset, interval.end);
2021-08-03 16:20:25 +08:00
}
2021-08-08 22:29:16 +08:00
maybe_next_op = ops_iter.next();
2021-08-04 15:09:04 +08:00
}
log::debug!("did get ops : {:?}", ops);
2021-08-04 15:09:04 +08:00
ops
2021-08-01 16:39:32 +08:00
}
pub fn get_attributes(&self, interval: Interval) -> Attributes {
2021-08-04 15:09:04 +08:00
let mut attributes_data = AttributesData::new();
let mut offset: usize = 0;
self.ops.iter().for_each(|op| match op {
Operation::Delete(_n) => {},
Operation::Retain(_retain) => {
unimplemented!()
// if interval.contains(retain.n as usize) {
// match &retain.attributes {
// Attributes::Follow => {},
// Attributes::Custom(data) => {
// attributes_data.extend(data.clone());
// },
// Attributes::Empty => {},
// }
// }
},
2021-08-04 22:33:16 +08:00
Operation::Insert(insert) => {
let end = insert.num_chars() as usize;
match &insert.attributes {
Attributes::Follow => {},
Attributes::Custom(data) => {
if interval.contains_range(offset, offset + end) {
log::debug!("Get attributes from op: {:?} at {:?}", op, interval);
2021-08-07 09:19:18 +08:00
attributes_data.extend(Some(data.clone()), false);
2021-08-04 22:33:16 +08:00
}
},
Attributes::Empty => {},
}
offset += end
2021-08-04 15:09:04 +08:00
},
});
2021-08-05 11:30:29 +08:00
attributes_data.into_attributes()
2021-07-31 23:22:17 +08:00
}
pub fn to_json(&self) -> String { serde_json::to_string(self).unwrap_or("".to_owned()) }
2021-07-31 23:22:17 +08:00
}
fn invert_from_other(
base: &mut Delta,
other: &Delta,
operation: &Operation,
start: usize,
end: usize,
) {
log::debug!("invert op: {} [{}:{}]", operation, start, end);
let other_ops = other.ops_in_interval(Interval::new(start, end));
other_ops.into_iter().for_each(|other_op| match operation {
Operation::Delete(n) => {
log::debug!("invert delete: {} by add {}", n, other_op);
base.add(other_op);
},
Operation::Retain(retain) => {
log::debug!(
"invert attributes: {:?}, {:?}",
operation.get_attributes(),
other_op.get_attributes()
);
let inverted_attrs =
invert_attributes(operation.get_attributes(), other_op.get_attributes());
log::debug!("invert result: {:?}", inverted_attrs);
log::debug!(
"invert retain: {} by retain len: {}, {}",
retain,
other_op.length(),
inverted_attrs
);
base.retain(other_op.length(), inverted_attrs);
},
Operation::Insert(_) => {
log::error!("Impossible to here. Insert operation should be treated as delete")
},
});
}