2021-08-04 07:55:54 +08:00
|
|
|
use crate::{
|
2021-08-14 16:44:39 +08:00
|
|
|
core::{attributes::*, operation::*, DeltaIter, Interval, MAX_IV_LEN},
|
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-09-21 16:21:35 +08:00
|
|
|
use bytes::Bytes;
|
|
|
|
use serde::__private::TryFrom;
|
2021-08-13 18:16:52 +08:00
|
|
|
use std::{
|
|
|
|
cmp::{min, Ordering},
|
|
|
|
fmt,
|
|
|
|
iter::FromIterator,
|
2021-09-14 16:22:44 +08:00
|
|
|
str,
|
2021-08-13 18:16:52 +08:00
|
|
|
str::FromStr,
|
|
|
|
};
|
2021-07-31 20:53:45 +08:00
|
|
|
|
2021-09-14 16:22:44 +08:00
|
|
|
// Opti: optimize the memory usage with Arc_mut or Cow
|
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)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-14 16:22:44 +08:00
|
|
|
impl std::convert::TryFrom<Vec<u8>> for Delta {
|
|
|
|
type Error = OTError;
|
|
|
|
fn try_from(bytes: Vec<u8>) -> Result<Self, Self::Error> { Delta::from_bytes(bytes) }
|
2021-08-01 10:45:15 +08:00
|
|
|
}
|
|
|
|
|
2021-09-21 16:21:35 +08:00
|
|
|
impl std::convert::TryFrom<Bytes> for Delta {
|
|
|
|
type Error = OTError;
|
|
|
|
|
|
|
|
fn try_from(value: Bytes) -> Result<Self, Self::Error> {
|
|
|
|
let bytes = value.to_vec();
|
|
|
|
Delta::from_bytes(bytes)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-14 16:22:44 +08:00
|
|
|
// impl<T: AsRef<Vec<u8>>> std::convert::From<T> for Delta {
|
|
|
|
// fn from(bytes: T) -> Self {
|
|
|
|
// Delta::from_bytes(bytes.as_ref().to_vec()).unwrap() } }
|
|
|
|
|
2021-08-03 23:13:20 +08:00
|
|
|
impl fmt::Display for Delta {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
2021-08-10 11:22:57 +08:00
|
|
|
// f.write_str(&serde_json::to_string(self).unwrap_or("".to_owned()))?;
|
|
|
|
f.write_str("[ ")?;
|
|
|
|
for op in &self.ops {
|
2021-08-10 17:08:47 +08:00
|
|
|
f.write_fmt(format_args!("{} ", op))?;
|
2021-08-10 11:22:57 +08:00
|
|
|
}
|
|
|
|
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 {
|
2021-08-05 19:55:28 +08:00
|
|
|
pub fn new() -> Self { Self::default() }
|
|
|
|
|
2021-09-12 22:19:59 +08:00
|
|
|
pub fn to_json(&self) -> String { serde_json::to_string(self).unwrap_or("".to_owned()) }
|
|
|
|
|
|
|
|
pub fn from_json(json: &str) -> Result<Self, OTError> {
|
2021-09-14 16:22:44 +08:00
|
|
|
let delta: Delta = serde_json::from_str(json).map_err(|e| {
|
2021-09-15 15:01:24 +08:00
|
|
|
log::trace!("Deserialize failed: {:?}", e);
|
|
|
|
log::trace!("{:?}", json);
|
2021-09-14 16:22:44 +08:00
|
|
|
e
|
|
|
|
})?;
|
2021-09-12 22:19:59 +08:00
|
|
|
Ok(delta)
|
|
|
|
}
|
|
|
|
|
2021-09-14 16:22:44 +08:00
|
|
|
pub fn from_bytes(bytes: Vec<u8>) -> Result<Self, OTError> {
|
|
|
|
let json = str::from_utf8(&bytes)?;
|
|
|
|
Self::from_json(json)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn into_bytes(self) -> Vec<u8> {
|
|
|
|
let json = self.to_json();
|
|
|
|
json.into_bytes()
|
|
|
|
}
|
|
|
|
|
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-13 18:16:52 +08:00
|
|
|
self.ops.push(OpBuilder::delete(n).build());
|
2021-07-31 20:53:45 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-13 15:51:13 +08:00
|
|
|
pub fn insert(&mut self, s: &str, attributes: 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() {
|
2021-08-02 18:35:25 +08:00
|
|
|
[.., Operation::Insert(insert)] => {
|
2021-08-01 16:39:32 +08:00
|
|
|
//
|
2021-09-13 15:51:13 +08:00
|
|
|
insert.merge_or_new_op(s, attributes)
|
2021-07-31 20:53:45 +08:00
|
|
|
},
|
2021-08-02 18:35:25 +08:00
|
|
|
[.., Operation::Insert(pre_insert), Operation::Delete(_)] => {
|
2021-08-01 16:39:32 +08:00
|
|
|
//
|
2021-09-13 15:51:13 +08:00
|
|
|
pre_insert.merge_or_new_op(s, attributes)
|
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-09-13 15:51:13 +08:00
|
|
|
*op_last = OpBuilder::insert(s).attributes(attributes).build();
|
2021-08-01 16:39:32 +08:00
|
|
|
Some(new_last)
|
2021-07-31 20:53:45 +08:00
|
|
|
},
|
2021-09-13 15:51:13 +08:00
|
|
|
_ => Some(OpBuilder::insert(s).attributes(attributes).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-09-13 15:51:13 +08:00
|
|
|
pub fn retain(&mut self, n: usize, attributes: 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;
|
|
|
|
|
2021-08-02 18:35:25 +08:00
|
|
|
if let Some(Operation::Retain(retain)) = self.ops.last_mut() {
|
2021-09-13 15:51:13 +08:00
|
|
|
if let Some(new_op) = retain.merge_or_new(n, attributes) {
|
2021-08-04 15:09:04 +08:00
|
|
|
self.ops.push(new_op);
|
2021-08-01 16:39:32 +08:00
|
|
|
}
|
2021-08-01 10:45:15 +08:00
|
|
|
} else {
|
2021-09-13 15:51:13 +08:00
|
|
|
self.ops.push(OpBuilder::retain(n).attributes(attributes).build());
|
2021-07-31 20:53:45 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-14 16:44:39 +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.
|
|
|
|
pub fn compose(&self, other: &Self) -> Result<Self, OTError> {
|
2021-08-13 18:16:52 +08:00
|
|
|
let mut new_delta = Delta::default();
|
2021-08-14 16:44:39 +08:00
|
|
|
let mut iter = DeltaIter::new(self);
|
|
|
|
let mut other_iter = DeltaIter::new(other);
|
2021-08-13 18:16:52 +08:00
|
|
|
|
2021-08-14 16:44:39 +08:00
|
|
|
while iter.has_next() || other_iter.has_next() {
|
|
|
|
if other_iter.is_next_insert() {
|
|
|
|
new_delta.add(other_iter.next_op().unwrap());
|
2021-08-13 18:16:52 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2021-08-14 16:44:39 +08:00
|
|
|
if iter.is_next_delete() {
|
|
|
|
new_delta.add(iter.next_op().unwrap());
|
2021-08-13 18:16:52 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2021-08-14 16:44:39 +08:00
|
|
|
let length = min(
|
|
|
|
iter.next_op_len().unwrap_or(MAX_IV_LEN),
|
|
|
|
other_iter.next_op_len().unwrap_or(MAX_IV_LEN),
|
|
|
|
);
|
|
|
|
|
2021-09-12 22:19:59 +08:00
|
|
|
let op = iter.next_op_with_len(length).unwrap_or(OpBuilder::retain(length).build());
|
2021-08-14 16:44:39 +08:00
|
|
|
|
2021-09-12 22:19:59 +08:00
|
|
|
let other_op = other_iter.next_op_with_len(length).unwrap_or(OpBuilder::retain(length).build());
|
2021-08-13 18:16:52 +08:00
|
|
|
|
2021-08-15 22:08:03 +08:00
|
|
|
debug_assert_eq!(op.len(), other_op.len());
|
2021-08-14 16:44:39 +08:00
|
|
|
|
|
|
|
match (&op, &other_op) {
|
|
|
|
(Operation::Retain(retain), Operation::Retain(other_retain)) => {
|
2021-09-12 22:19:59 +08:00
|
|
|
let composed_attrs = compose_attributes(retain.attributes.clone(), other_retain.attributes.clone());
|
|
|
|
new_delta.add(OpBuilder::retain(retain.n).attributes(composed_attrs).build())
|
2021-08-14 16:44:39 +08:00
|
|
|
},
|
|
|
|
(Operation::Insert(insert), Operation::Retain(other_retain)) => {
|
2021-09-12 22:19:59 +08:00
|
|
|
let mut composed_attrs = compose_attributes(insert.attributes.clone(), other_retain.attributes.clone());
|
2021-08-17 11:23:28 +08:00
|
|
|
composed_attrs.remove_empty();
|
2021-09-12 22:19:59 +08:00
|
|
|
new_delta.add(OpBuilder::insert(op.get_data()).attributes(composed_attrs).build())
|
2021-08-14 16:44:39 +08:00
|
|
|
},
|
|
|
|
(Operation::Retain(_), Operation::Delete(_)) => {
|
|
|
|
new_delta.add(other_op);
|
|
|
|
},
|
|
|
|
(a, b) => {
|
|
|
|
debug_assert_eq!(a.is_insert(), true);
|
|
|
|
debug_assert_eq!(b.is_delete(), true);
|
|
|
|
continue;
|
|
|
|
},
|
|
|
|
}
|
2021-08-13 18:16:52 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
Ok(new_delta)
|
|
|
|
}
|
|
|
|
|
2021-09-12 22:19:59 +08:00
|
|
|
#[deprecated(note = "The same as compose except it requires the target_len of self must equal to other's base_len")]
|
2021-08-14 16:44:39 +08:00
|
|
|
pub fn compose2(&self, other: &Self) -> Result<Self, OTError> {
|
2021-07-31 20:53:45 +08:00
|
|
|
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
|
|
|
},
|
2021-08-02 18:35:25 +08:00
|
|
|
(_, Some(Operation::Insert(o_insert))) => {
|
2021-08-04 16:59:21 +08:00
|
|
|
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
|
|
|
},
|
2021-08-02 18:35:25 +08:00
|
|
|
(Some(Operation::Retain(retain)), Some(Operation::Retain(o_retain))) => {
|
2021-08-05 15:05:20 +08:00
|
|
|
let composed_attrs = compose_operation(&next_op1, &next_op2);
|
2021-09-15 16:35:40 +08:00
|
|
|
log::trace!("[retain:{} - retain:{}]: {:?}", retain.n, o_retain.n, composed_attrs);
|
2021-08-02 18:35:25 +08:00
|
|
|
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);
|
2021-08-10 11:22:57 +08:00
|
|
|
next_op2 = Some(
|
2021-08-13 18:16:52 +08:00
|
|
|
OpBuilder::retain(o_retain.n - retain.n)
|
2021-08-10 11:22:57 +08:00
|
|
|
.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-13 18:16:52 +08:00
|
|
|
next_op1 = Some(OpBuilder::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
|
|
|
},
|
2021-08-02 18:35:25 +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-13 18:16:52 +08:00
|
|
|
OpBuilder::delete(*o_num - num_chars(insert.as_bytes()) as usize)
|
2021-08-03 16:20:25 +08:00
|
|
|
.attributes(insert.attributes.clone())
|
2021-08-02 18:35:25 +08:00
|
|
|
.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-09-12 22:19:59 +08:00
|
|
|
next_op1 = Some(OpBuilder::insert(&insert.chars().skip(*o_num as usize).collect::<String>()).build());
|
2021-08-01 10:45:15 +08:00
|
|
|
next_op2 = ops2.next();
|
2021-07-31 20:53:45 +08:00
|
|
|
},
|
|
|
|
}
|
|
|
|
},
|
2021-08-02 18:35:25 +08:00
|
|
|
(Some(Operation::Insert(insert)), Some(Operation::Retain(o_retain))) => {
|
2021-08-10 11:22:57 +08:00
|
|
|
let mut composed_attrs = compose_operation(&next_op1, &next_op2);
|
2021-08-17 11:23:28 +08:00
|
|
|
composed_attrs.remove_empty();
|
2021-08-10 11:22:57 +08:00
|
|
|
|
2021-09-15 16:35:40 +08:00
|
|
|
log::trace!("compose: [{} - {}], composed_attrs: {}", insert, o_retain, composed_attrs);
|
2021-08-02 18:35:25 +08:00
|
|
|
match (insert.num_chars()).cmp(o_retain) {
|
2021-07-31 20:53:45 +08:00
|
|
|
Ordering::Less => {
|
2021-08-02 18:35:25 +08:00
|
|
|
new_delta.insert(&insert.s, composed_attrs.clone());
|
|
|
|
next_op2 = Some(
|
2021-08-13 18:16:52 +08:00
|
|
|
OpBuilder::retain(o_retain.n - insert.num_chars())
|
2021-08-05 15:05:20 +08:00
|
|
|
.attributes(o_retain.attributes.clone())
|
2021-08-02 18:35:25 +08:00
|
|
|
.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-02 18:35:25 +08:00
|
|
|
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();
|
2021-09-12 22:19:59 +08:00
|
|
|
new_delta.insert(&chars.take(o_retain.n as usize).collect::<String>(), composed_attrs);
|
2021-08-13 18:16:52 +08:00
|
|
|
next_op1 = Some(OpBuilder::insert(&chars.collect::<String>()).build());
|
2021-08-01 10:45:15 +08:00
|
|
|
next_op2 = ops2.next();
|
2021-07-31 20:53:45 +08:00
|
|
|
},
|
|
|
|
}
|
|
|
|
},
|
2021-09-12 22:19:59 +08:00
|
|
|
(Some(Operation::Retain(retain)), Some(Operation::Delete(o_num))) => match retain.cmp(&o_num) {
|
|
|
|
Ordering::Less => {
|
|
|
|
new_delta.delete(retain.n);
|
|
|
|
next_op2 = Some(OpBuilder::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);
|
|
|
|
next_op1 = Some(OpBuilder::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)), _) => {
|
2021-08-02 18:35:25 +08:00
|
|
|
// 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
|
|
|
},
|
2021-08-02 18:35:25 +08:00
|
|
|
(_, Some(Operation::Insert(o_insert))) => {
|
2021-08-05 15:05:20 +08:00
|
|
|
let composed_attrs = transform_operation(&next_op1, &next_op2);
|
2021-08-02 18:35:25 +08:00
|
|
|
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
|
|
|
},
|
2021-08-02 18:35:25 +08:00
|
|
|
(Some(Operation::Retain(retain)), Some(Operation::Retain(o_retain))) => {
|
2021-08-05 15:05:20 +08:00
|
|
|
let composed_attrs = transform_operation(&next_op1, &next_op2);
|
2021-08-02 18:35:25 +08:00
|
|
|
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-13 18:16:52 +08:00
|
|
|
next_op2 = Some(OpBuilder::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-13 18:16:52 +08:00
|
|
|
next_op1 = Some(OpBuilder::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-13 18:16:52 +08:00
|
|
|
next_op2 = Some(OpBuilder::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-13 18:16:52 +08:00
|
|
|
next_op1 = Some(OpBuilder::delete(*i - *j).build());
|
2021-08-01 10:45:15 +08:00
|
|
|
next_op2 = ops2.next();
|
2021-07-31 20:53:45 +08:00
|
|
|
},
|
|
|
|
},
|
2021-08-02 18:35:25 +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-13 18:16:52 +08:00
|
|
|
next_op2 = Some(OpBuilder::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-13 18:16:52 +08:00
|
|
|
next_op1 = Some(OpBuilder::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
|
|
|
},
|
|
|
|
};
|
|
|
|
},
|
2021-08-02 18:35:25 +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-13 18:16:52 +08:00
|
|
|
next_op2 = Some(OpBuilder::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-13 18:16:52 +08:00
|
|
|
next_op1 = Some(OpBuilder::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-11 17:18:10 +08:00
|
|
|
inverted.retain(retain.n, Attributes::default());
|
2021-08-04 15:09:04 +08:00
|
|
|
|
|
|
|
// 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) => {
|
2021-09-12 22:19:59 +08:00
|
|
|
inverted.insert(&chars.take(*delete as usize).collect::<String>(), op.get_attributes());
|
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;
|
|
|
|
}
|
2021-09-15 16:35:40 +08:00
|
|
|
log::trace!("🌜Calculate invert delta");
|
|
|
|
log::trace!("current: {}", self);
|
|
|
|
log::trace!("other: {}", other);
|
2021-08-04 15:09:04 +08:00
|
|
|
let mut index = 0;
|
|
|
|
for op in &self.ops {
|
2021-08-15 22:08:03 +08:00
|
|
|
let len: usize = op.len() as usize;
|
2021-08-04 15:09:04 +08:00
|
|
|
match op {
|
2021-08-08 22:29:16 +08:00
|
|
|
Operation::Delete(n) => {
|
2021-08-09 11:29:37 +08:00
|
|
|
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() {
|
2021-08-09 11:29:37 +08:00
|
|
|
true => invert_from_other(&mut inverted, other, op, index, index + len),
|
2021-08-08 22:29:16 +08:00
|
|
|
false => {
|
2021-09-15 16:35:40 +08:00
|
|
|
log::trace!("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
|
|
|
},
|
2021-08-09 11:29:37 +08:00
|
|
|
Operation::Insert(_) => {
|
2021-09-15 16:35:40 +08:00
|
|
|
log::trace!("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
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-15 16:35:40 +08:00
|
|
|
log::trace!("🌛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-15 21:11:48 +08:00
|
|
|
pub fn extend(&mut self, other: Self) { other.ops.into_iter().for_each(|op| self.add(op)); }
|
2021-07-31 23:22:17 +08:00
|
|
|
}
|
2021-08-09 11:29:37 +08:00
|
|
|
|
2021-09-12 22:19:59 +08:00
|
|
|
fn invert_from_other(base: &mut Delta, other: &Delta, operation: &Operation, start: usize, end: usize) {
|
2021-09-15 16:35:40 +08:00
|
|
|
log::trace!("invert op: {} [{}:{}]", operation, start, end);
|
2021-08-11 11:42:46 +08:00
|
|
|
let other_ops = DeltaIter::from_interval(other, Interval::new(start, end)).ops();
|
2021-08-10 11:22:57 +08:00
|
|
|
other_ops.into_iter().for_each(|other_op| match operation {
|
|
|
|
Operation::Delete(n) => {
|
2021-09-15 16:35:40 +08:00
|
|
|
log::trace!("invert delete: {} by add {}", n, other_op);
|
2021-08-10 11:22:57 +08:00
|
|
|
base.add(other_op);
|
|
|
|
},
|
|
|
|
Operation::Retain(retain) => {
|
2021-09-15 16:35:40 +08:00
|
|
|
log::trace!(
|
2021-08-10 11:22:57 +08:00
|
|
|
"invert attributes: {:?}, {:?}",
|
|
|
|
operation.get_attributes(),
|
|
|
|
other_op.get_attributes()
|
|
|
|
);
|
2021-09-12 22:19:59 +08:00
|
|
|
let inverted_attrs = invert_attributes(operation.get_attributes(), other_op.get_attributes());
|
2021-09-15 16:35:40 +08:00
|
|
|
log::trace!("invert attributes result: {:?}", inverted_attrs);
|
|
|
|
log::trace!("invert retain: {} by retain len: {}, {}", retain, other_op.len(), inverted_attrs);
|
2021-08-15 22:08:03 +08:00
|
|
|
base.retain(other_op.len(), inverted_attrs);
|
2021-08-10 11:22:57 +08:00
|
|
|
},
|
|
|
|
Operation::Insert(_) => {
|
|
|
|
log::error!("Impossible to here. Insert operation should be treated as delete")
|
|
|
|
},
|
2021-08-09 11:29:37 +08:00
|
|
|
});
|
|
|
|
}
|