2021-07-31 23:22:17 +08:00
|
|
|
use crate::{attributes::*, errors::OTError, operation::*};
|
2021-07-31 20:53:45 +08:00
|
|
|
use bytecount::num_chars;
|
2021-08-01 10:45:15 +08:00
|
|
|
use std::{cmp::Ordering, error::Error, 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() }
|
|
|
|
}
|
|
|
|
|
|
|
|
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 {
|
|
|
|
#[inline]
|
|
|
|
pub fn with_capacity(capacity: usize) -> Self {
|
|
|
|
Self {
|
|
|
|
ops: Vec::with_capacity(capacity),
|
|
|
|
base_len: 0,
|
|
|
|
target_len: 0,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-01 10:45:15 +08:00
|
|
|
fn add(&mut self, op: Operation) {
|
|
|
|
match op {
|
|
|
|
Operation::Delete(i) => self.delete(i),
|
|
|
|
Operation::Insert(i) => self.insert(&i.s, i.attrs),
|
|
|
|
Operation::Retain(r) => self.retain(r.n, r.attrs),
|
|
|
|
}
|
|
|
|
}
|
2021-07-31 20:53:45 +08:00
|
|
|
|
|
|
|
pub fn delete(&mut self, n: u64) {
|
|
|
|
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 {
|
|
|
|
self.ops.push(OpBuilder::delete(n).build());
|
2021-07-31 20:53:45 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-31 23:22:17 +08:00
|
|
|
pub fn insert(&mut self, s: &str, attrs: Option<Attributes>) {
|
2021-07-31 20:53:45 +08:00
|
|
|
if s.is_empty() {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
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(s_last)] => {
|
|
|
|
s_last.s += &s;
|
2021-07-31 20:53:45 +08:00
|
|
|
return;
|
|
|
|
},
|
2021-08-01 10:45:15 +08:00
|
|
|
[.., Operation::Insert(s_pre_last), Operation::Delete(_)] => {
|
|
|
|
s_pre_last.s += s;
|
2021-07-31 20:53:45 +08:00
|
|
|
return;
|
|
|
|
},
|
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-01 10:45:15 +08:00
|
|
|
*op_last = Operation::Insert(s.into());
|
2021-07-31 20:53:45 +08:00
|
|
|
new_last
|
|
|
|
},
|
2021-08-01 10:45:15 +08:00
|
|
|
_ => Operation::Insert(s.into()),
|
2021-07-31 20:53:45 +08:00
|
|
|
};
|
2021-07-31 23:22:17 +08:00
|
|
|
self.ops
|
2021-08-01 10:45:15 +08:00
|
|
|
.push(OpBuilder::new(new_last).with_attrs(attrs).build());
|
2021-07-31 20:53:45 +08:00
|
|
|
}
|
|
|
|
|
2021-07-31 23:22:17 +08:00
|
|
|
pub fn retain(&mut self, n: u64, attrs: Option<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-01 10:45:15 +08:00
|
|
|
if let Some(Operation::Retain(i_last)) = self.ops.last_mut() {
|
|
|
|
i_last.n += n;
|
|
|
|
i_last.attrs = attrs;
|
|
|
|
} else {
|
|
|
|
self.ops
|
|
|
|
.push(OpBuilder::retain(n).with_attrs(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 {
|
|
|
|
return Err(OTError);
|
|
|
|
}
|
|
|
|
|
|
|
|
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-01 10:45:15 +08:00
|
|
|
(_, Some(Operation::Insert(insert))) => {
|
|
|
|
new_delta.insert(&insert.s, get_attrs(&next_op2));
|
|
|
|
next_op2 = ops2.next();
|
2021-07-31 20:53:45 +08:00
|
|
|
},
|
|
|
|
(None, _) | (_, None) => {
|
|
|
|
return Err(OTError);
|
|
|
|
},
|
2021-08-01 10:45:15 +08:00
|
|
|
(Some(Operation::Retain(i)), Some(Operation::Retain(j))) => {
|
|
|
|
let new_attrs =
|
|
|
|
compose_attributes(get_attrs(&next_op1), get_attrs(&next_op2), true);
|
2021-07-31 23:22:17 +08:00
|
|
|
match i.cmp(&j) {
|
|
|
|
Ordering::Less => {
|
2021-08-01 10:45:15 +08:00
|
|
|
new_delta.retain(i.n, new_attrs);
|
|
|
|
next_op2 = Some(OpBuilder::retain(j.n - i.n).build());
|
|
|
|
next_op1 = ops1.next();
|
2021-07-31 23:22:17 +08:00
|
|
|
},
|
|
|
|
std::cmp::Ordering::Equal => {
|
2021-08-01 10:45:15 +08:00
|
|
|
new_delta.retain(i.n, new_attrs);
|
|
|
|
next_op1 = ops1.next();
|
|
|
|
next_op2 = ops2.next();
|
2021-07-31 23:22:17 +08:00
|
|
|
},
|
|
|
|
std::cmp::Ordering::Greater => {
|
2021-08-01 10:45:15 +08:00
|
|
|
new_delta.retain(j.n, new_attrs);
|
|
|
|
next_op1 = Some(OpBuilder::retain(i.n - j.n).build());
|
|
|
|
next_op2 = ops2.next();
|
2021-07-31 23:22:17 +08:00
|
|
|
},
|
|
|
|
}
|
2021-07-31 20:53:45 +08:00
|
|
|
},
|
2021-08-01 10:45:15 +08:00
|
|
|
(Some(Operation::Insert(insert)), Some(Operation::Delete(j))) => {
|
|
|
|
match (num_chars(insert.as_bytes()) as u64).cmp(j) {
|
2021-07-31 20:53:45 +08:00
|
|
|
Ordering::Less => {
|
2021-08-01 10:45:15 +08:00
|
|
|
next_op2 = Some(
|
|
|
|
OpBuilder::delete(*j - num_chars(insert.as_bytes()) as u64).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(
|
|
|
|
OpBuilder::insert(insert.chars().skip(*j as usize).collect())
|
2021-07-31 20:53:45 +08:00
|
|
|
.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::Insert(insert)), Some(Operation::Retain(j))) => {
|
|
|
|
let new_attrs =
|
|
|
|
compose_attributes(get_attrs(&next_op1), get_attrs(&next_op2), false);
|
|
|
|
match (insert.num_chars()).cmp(j) {
|
2021-07-31 20:53:45 +08:00
|
|
|
Ordering::Less => {
|
2021-08-01 10:45:15 +08:00
|
|
|
new_delta.insert(&insert.s, new_attrs);
|
|
|
|
next_op2 = Some(OpBuilder::retain(j.n - insert.num_chars()).build());
|
|
|
|
next_op1 = ops1.next();
|
2021-07-31 20:53:45 +08:00
|
|
|
},
|
|
|
|
Ordering::Equal => {
|
2021-08-01 10:45:15 +08:00
|
|
|
new_delta.insert(&insert.s, new_attrs);
|
|
|
|
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-07-31 23:22:17 +08:00
|
|
|
new_delta
|
2021-08-01 10:45:15 +08:00
|
|
|
.insert(&chars.take(j.n as usize).collect::<String>(), new_attrs);
|
|
|
|
next_op1 = Some(OpBuilder::insert(chars.collect()).build());
|
|
|
|
next_op2 = ops2.next();
|
2021-07-31 20:53:45 +08:00
|
|
|
},
|
|
|
|
}
|
|
|
|
},
|
2021-08-01 10:45:15 +08:00
|
|
|
(Some(Operation::Retain(i)), Some(Operation::Delete(j))) => match i.cmp(&j) {
|
2021-07-31 20:53:45 +08:00
|
|
|
Ordering::Less => {
|
2021-08-01 10:45:15 +08:00
|
|
|
new_delta.delete(i.n);
|
|
|
|
next_op2 = Some(OpBuilder::delete(*j - i.n).build());
|
|
|
|
next_op1 = ops1.next();
|
2021-07-31 20:53:45 +08:00
|
|
|
},
|
|
|
|
Ordering::Equal => {
|
|
|
|
new_delta.delete(*j);
|
2021-08-01 10:45:15 +08:00
|
|
|
next_op2 = ops2.next();
|
|
|
|
next_op1 = ops1.next();
|
2021-07-31 20:53:45 +08:00
|
|
|
},
|
|
|
|
Ordering::Greater => {
|
|
|
|
new_delta.delete(*j);
|
2021-08-01 10:45:15 +08:00
|
|
|
next_op1 = Some(OpBuilder::retain(i.n - *j).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 {
|
|
|
|
return Err(OTError);
|
|
|
|
}
|
|
|
|
|
|
|
|
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 new_attrs =
|
|
|
|
compose_attributes(get_attrs(&next_op1), get_attrs(&next_op2), true);
|
|
|
|
a_prime.insert(&insert.s, new_attrs.clone());
|
|
|
|
b_prime.retain(insert.num_chars(), new_attrs.clone());
|
|
|
|
next_op1 = ops1.next();
|
2021-07-31 20:53:45 +08:00
|
|
|
},
|
2021-08-01 10:45:15 +08:00
|
|
|
(_, Some(Operation::Insert(insert))) => {
|
|
|
|
let new_attrs =
|
|
|
|
compose_attributes(get_attrs(&next_op1), get_attrs(&next_op2), true);
|
|
|
|
a_prime.retain(insert.num_chars(), new_attrs.clone());
|
|
|
|
b_prime.insert(&insert.s, new_attrs.clone());
|
|
|
|
next_op2 = ops2.next();
|
2021-07-31 20:53:45 +08:00
|
|
|
},
|
|
|
|
(None, _) => {
|
|
|
|
return Err(OTError);
|
|
|
|
},
|
|
|
|
(_, None) => {
|
|
|
|
return Err(OTError);
|
|
|
|
},
|
2021-08-01 10:45:15 +08:00
|
|
|
(Some(Operation::Retain(i)), Some(Operation::Retain(j))) => {
|
|
|
|
let new_attrs =
|
|
|
|
compose_attributes(get_attrs(&next_op1), get_attrs(&next_op2), true);
|
2021-07-31 20:53:45 +08:00
|
|
|
match i.cmp(&j) {
|
|
|
|
Ordering::Less => {
|
2021-08-01 10:45:15 +08:00
|
|
|
a_prime.retain(i.n, new_attrs.clone());
|
|
|
|
b_prime.retain(i.n, new_attrs.clone());
|
|
|
|
next_op2 = Some(OpBuilder::retain(j.n - i.n).build());
|
|
|
|
next_op1 = ops1.next();
|
2021-07-31 20:53:45 +08:00
|
|
|
},
|
|
|
|
Ordering::Equal => {
|
2021-08-01 10:45:15 +08:00
|
|
|
a_prime.retain(i.n, new_attrs.clone());
|
|
|
|
b_prime.retain(i.n, new_attrs.clone());
|
|
|
|
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
|
|
|
a_prime.retain(j.n, new_attrs.clone());
|
|
|
|
b_prime.retain(j.n, new_attrs.clone());
|
|
|
|
next_op1 = Some(OpBuilder::retain(i.n - j.n).build());
|
|
|
|
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-01 10:45:15 +08:00
|
|
|
next_op2 = Some(OpBuilder::delete(*j - *i).build());
|
|
|
|
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(OpBuilder::delete(*i - *j).build());
|
|
|
|
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::Retain(j))) => {
|
2021-07-31 20:53:45 +08:00
|
|
|
match i.cmp(&j) {
|
|
|
|
Ordering::Less => {
|
|
|
|
a_prime.delete(*i);
|
2021-08-01 10:45:15 +08:00
|
|
|
next_op2 = Some(OpBuilder::retain(j.n - *i).build());
|
|
|
|
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-01 10:45:15 +08:00
|
|
|
a_prime.delete(j.n);
|
|
|
|
next_op1 = Some(OpBuilder::delete(*i - j.n).build());
|
|
|
|
next_op2 = ops2.next();
|
2021-07-31 20:53:45 +08:00
|
|
|
},
|
|
|
|
};
|
|
|
|
},
|
2021-08-01 10:45:15 +08:00
|
|
|
(Some(Operation::Retain(i)), Some(Operation::Delete(j))) => {
|
2021-07-31 20:53:45 +08:00
|
|
|
match i.cmp(&j) {
|
|
|
|
Ordering::Less => {
|
2021-08-01 10:45:15 +08:00
|
|
|
b_prime.delete(i.n);
|
|
|
|
next_op2 = Some(OpBuilder::delete(*j - i.n).build());
|
|
|
|
next_op1 = ops1.next();
|
2021-07-31 20:53:45 +08:00
|
|
|
},
|
|
|
|
Ordering::Equal => {
|
2021-08-01 10:45:15 +08:00
|
|
|
b_prime.delete(i.n);
|
|
|
|
next_op1 = ops1.next();
|
|
|
|
next_op2 = ops2.next();
|
2021-07-31 20:53:45 +08:00
|
|
|
},
|
|
|
|
Ordering::Greater => {
|
|
|
|
b_prime.delete(*j);
|
2021-08-01 10:45:15 +08:00
|
|
|
next_op1 = Some(OpBuilder::retain(i.n - *j).build());
|
|
|
|
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 {
|
|
|
|
return Err(OTError);
|
|
|
|
}
|
|
|
|
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) => {
|
|
|
|
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
|
|
|
|
pub fn invert(&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) => {
|
|
|
|
inverted.retain(retain.n, None);
|
|
|
|
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>(),
|
2021-08-01 10:45:15 +08:00
|
|
|
op.attrs(),
|
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
|
|
|
}
|
|
|
|
|
|
|
|
/// 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,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the length of a string these operations can be applied to
|
|
|
|
#[inline]
|
|
|
|
pub fn base_len(&self) -> usize { self.base_len }
|
|
|
|
|
|
|
|
/// Returns the length of the resulting string after the operations have
|
|
|
|
/// been applied.
|
|
|
|
#[inline]
|
|
|
|
pub fn target_len(&self) -> usize { self.target_len }
|
|
|
|
|
|
|
|
/// Returns the wrapped sequence of operations.
|
|
|
|
#[inline]
|
|
|
|
pub fn ops(&self) -> &[Operation] { &self.ops }
|
2021-08-01 10:45:15 +08:00
|
|
|
|
|
|
|
pub fn is_empty(&self) -> bool { self.ops.is_empty() }
|
2021-07-31 20:53:45 +08:00
|
|
|
}
|
2021-07-31 23:22:17 +08:00
|
|
|
|
2021-08-01 10:45:15 +08:00
|
|
|
pub fn get_attrs(operation: &Option<Operation>) -> Option<Attributes> {
|
2021-07-31 23:22:17 +08:00
|
|
|
match operation {
|
|
|
|
None => None,
|
2021-08-01 10:45:15 +08:00
|
|
|
Some(operation) => operation.attrs(),
|
2021-07-31 23:22:17 +08:00
|
|
|
}
|
|
|
|
}
|