123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617 |
- use crate::{
- core::{attributes::*, operation::*, Interval},
- errors::{ErrorBuilder, OTError, OTErrorCode},
- };
- use bytecount::num_chars;
- use std::{
- cmp::{max, min, Ordering},
- fmt,
- iter::FromIterator,
- str::FromStr,
- };
- #[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,
- }
- }
- }
- 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 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()))?;
- // for op in &self.ops {
- // f.write_fmt(format_args!("{}", op));
- // }
- Ok(())
- }
- }
- 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
- }
- }
- impl Delta {
- pub fn new() -> Self { Self::default() }
- #[inline]
- pub fn with_capacity(capacity: usize) -> Self {
- Self {
- ops: Vec::with_capacity(capacity),
- base_len: 0,
- target_len: 0,
- }
- }
- pub fn add(&mut self, op: Operation) {
- match op {
- Operation::Delete(i) => self.delete(i),
- Operation::Insert(i) => self.insert(&i.s, i.attributes),
- Operation::Retain(r) => self.retain(r.n, r.attributes),
- }
- }
- pub fn delete(&mut self, n: usize) {
- if n == 0 {
- return;
- }
- self.base_len += n as usize;
- if let Some(Operation::Delete(n_last)) = self.ops.last_mut() {
- *n_last += n;
- } else {
- self.ops.push(OpBuilder::delete(n).build());
- }
- }
- pub fn insert(&mut self, s: &str, attrs: Attributes) {
- if s.is_empty() {
- return;
- }
- self.target_len += num_chars(s.as_bytes());
- let new_last = match self.ops.as_mut_slice() {
- [.., Operation::Insert(insert)] => {
- //
- insert.merge_or_new_op(s, attrs)
- },
- [.., Operation::Insert(pre_insert), Operation::Delete(_)] => {
- //
- pre_insert.merge_or_new_op(s, attrs)
- },
- [.., op_last @ Operation::Delete(_)] => {
- let new_last = op_last.clone();
- *op_last = OpBuilder::insert(s).attributes(attrs).build();
- Some(new_last)
- },
- _ => Some(OpBuilder::insert(s).attributes(attrs).build()),
- };
- match new_last {
- None => {},
- Some(new_last) => self.ops.push(new_last),
- }
- }
- pub fn retain(&mut self, n: usize, attrs: Attributes) {
- 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() {
- if let Some(new_op) = retain.merge_or_new_op(n, attrs) {
- self.ops.push(new_op);
- }
- } else {
- self.ops
- .push(OpBuilder::retain(n).attributes(attrs).build());
- }
- }
- /// 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(ErrorBuilder::new(OTErrorCode::IncompatibleLength).build());
- }
- let mut new_delta = Delta::default();
- let mut ops1 = self.ops.iter().cloned();
- let mut ops2 = other.ops.iter().cloned();
- let mut next_op1 = ops1.next();
- let mut next_op2 = ops2.next();
- loop {
- match (&next_op1, &next_op2) {
- (None, None) => break,
- (Some(Operation::Delete(i)), _) => {
- new_delta.delete(*i);
- next_op1 = ops1.next();
- },
- (_, Some(Operation::Insert(o_insert))) => {
- new_delta.insert(&o_insert.s, o_insert.attributes.clone());
- next_op2 = ops2.next();
- },
- (None, _) | (_, None) => {
- return Err(ErrorBuilder::new(OTErrorCode::IncompatibleLength).build());
- },
- (Some(Operation::Retain(retain)), Some(Operation::Retain(o_retain))) => {
- let composed_attrs = compose_operation(&next_op1, &next_op2);
- log::debug!(
- "[retain:{} - retain:{}]: {:?}",
- retain.n,
- o_retain.n,
- composed_attrs
- );
- match retain.cmp(&o_retain) {
- Ordering::Less => {
- new_delta.retain(retain.n, composed_attrs);
- next_op2 = Some(OpBuilder::retain(o_retain.n - retain.n).build());
- next_op1 = ops1.next();
- },
- std::cmp::Ordering::Equal => {
- new_delta.retain(retain.n, composed_attrs);
- next_op1 = ops1.next();
- next_op2 = ops2.next();
- },
- std::cmp::Ordering::Greater => {
- new_delta.retain(o_retain.n, composed_attrs);
- next_op1 = Some(OpBuilder::retain(retain.n - o_retain.n).build());
- next_op2 = ops2.next();
- },
- }
- },
- (Some(Operation::Insert(insert)), Some(Operation::Delete(o_num))) => {
- match (num_chars(insert.as_bytes()) as usize).cmp(o_num) {
- Ordering::Less => {
- next_op2 = Some(
- OpBuilder::delete(*o_num - num_chars(insert.as_bytes()) as usize)
- .attributes(insert.attributes.clone())
- .build(),
- );
- next_op1 = ops1.next();
- },
- Ordering::Equal => {
- next_op1 = ops1.next();
- next_op2 = ops2.next();
- },
- Ordering::Greater => {
- next_op1 = Some(
- OpBuilder::insert(
- &insert.chars().skip(*o_num as usize).collect::<String>(),
- )
- .build(),
- );
- next_op2 = ops2.next();
- },
- }
- },
- (Some(Operation::Insert(insert)), Some(Operation::Retain(o_retain))) => {
- let composed_attrs = compose_operation(&next_op1, &next_op2);
- log::debug!(
- "[insert:{} - retain:{}]: {:?}",
- insert.s,
- o_retain.n,
- composed_attrs
- );
- match (insert.num_chars()).cmp(o_retain) {
- Ordering::Less => {
- new_delta.insert(&insert.s, composed_attrs.clone());
- next_op2 = Some(
- OpBuilder::retain(o_retain.n - insert.num_chars())
- .attributes(o_retain.attributes.clone())
- .build(),
- );
- next_op1 = ops1.next();
- },
- Ordering::Equal => {
- new_delta.insert(&insert.s, composed_attrs);
- next_op1 = ops1.next();
- next_op2 = ops2.next();
- },
- Ordering::Greater => {
- let chars = &mut insert.chars();
- new_delta.insert(
- &chars.take(o_retain.n as usize).collect::<String>(),
- composed_attrs,
- );
- next_op1 = Some(
- OpBuilder::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.
- .attributes(Attributes::Empty)
- .build(),
- );
- next_op2 = ops2.next();
- },
- }
- },
- (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();
- },
- }
- },
- };
- }
- 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(ErrorBuilder::new(OTErrorCode::IncompatibleLength).build());
- }
- 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();
- let mut next_op1 = ops1.next();
- let mut next_op2 = ops2.next();
- loop {
- match (&next_op1, &next_op2) {
- (None, None) => break,
- (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());
- next_op1 = ops1.next();
- },
- (_, Some(Operation::Insert(o_insert))) => {
- let composed_attrs = transform_operation(&next_op1, &next_op2);
- a_prime.retain(o_insert.num_chars(), composed_attrs.clone());
- b_prime.insert(&o_insert.s, composed_attrs);
- next_op2 = ops2.next();
- },
- (None, _) => {
- return Err(ErrorBuilder::new(OTErrorCode::IncompatibleLength).build());
- },
- (_, None) => {
- return Err(ErrorBuilder::new(OTErrorCode::IncompatibleLength).build());
- },
- (Some(Operation::Retain(retain)), Some(Operation::Retain(o_retain))) => {
- let composed_attrs = transform_operation(&next_op1, &next_op2);
- match retain.cmp(&o_retain) {
- Ordering::Less => {
- a_prime.retain(retain.n, composed_attrs.clone());
- b_prime.retain(retain.n, composed_attrs.clone());
- next_op2 = Some(OpBuilder::retain(o_retain.n - retain.n).build());
- next_op1 = ops1.next();
- },
- Ordering::Equal => {
- a_prime.retain(retain.n, composed_attrs.clone());
- b_prime.retain(retain.n, composed_attrs.clone());
- next_op1 = ops1.next();
- next_op2 = ops2.next();
- },
- Ordering::Greater => {
- a_prime.retain(o_retain.n, composed_attrs.clone());
- b_prime.retain(o_retain.n, composed_attrs.clone());
- next_op1 = Some(OpBuilder::retain(retain.n - o_retain.n).build());
- next_op2 = ops2.next();
- },
- };
- },
- (Some(Operation::Delete(i)), Some(Operation::Delete(j))) => match i.cmp(&j) {
- Ordering::Less => {
- next_op2 = Some(OpBuilder::delete(*j - *i).build());
- next_op1 = ops1.next();
- },
- Ordering::Equal => {
- next_op1 = ops1.next();
- next_op2 = ops2.next();
- },
- Ordering::Greater => {
- next_op1 = Some(OpBuilder::delete(*i - *j).build());
- next_op2 = ops2.next();
- },
- },
- (Some(Operation::Delete(i)), Some(Operation::Retain(o_retain))) => {
- match i.cmp(&o_retain) {
- Ordering::Less => {
- a_prime.delete(*i);
- next_op2 = Some(OpBuilder::retain(o_retain.n - *i).build());
- next_op1 = ops1.next();
- },
- Ordering::Equal => {
- a_prime.delete(*i);
- next_op1 = ops1.next();
- next_op2 = ops2.next();
- },
- Ordering::Greater => {
- a_prime.delete(o_retain.n);
- next_op1 = Some(OpBuilder::delete(*i - o_retain.n).build());
- next_op2 = ops2.next();
- },
- };
- },
- (Some(Operation::Retain(retain)), Some(Operation::Delete(j))) => {
- match retain.cmp(&j) {
- Ordering::Less => {
- b_prime.delete(retain.n);
- next_op2 = Some(OpBuilder::delete(*j - retain.n).build());
- next_op1 = ops1.next();
- },
- Ordering::Equal => {
- b_prime.delete(retain.n);
- next_op1 = ops1.next();
- next_op2 = ops2.next();
- },
- Ordering::Greater => {
- b_prime.delete(*j);
- next_op1 = Some(OpBuilder::retain(retain.n - *j).build());
- next_op2 = ops2.next();
- },
- };
- },
- }
- }
- 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(ErrorBuilder::new(OTErrorCode::IncompatibleLength).build());
- }
- let mut new_s = String::new();
- let chars = &mut s.chars();
- for op in &self.ops {
- match &op {
- Operation::Retain(retain) => {
- for c in chars.take(retain.n as usize) {
- new_s.push(c);
- }
- },
- Operation::Delete(delete) => {
- for _ in 0..*delete {
- chars.next();
- }
- },
- Operation::Insert(insert) => {
- new_s += &insert.s;
- },
- }
- }
- 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_str(&self, s: &str) -> Self {
- let mut inverted = Delta::default();
- let chars = &mut s.chars();
- for op in &self.ops {
- match &op {
- Operation::Retain(retain) => {
- 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 {
- chars.next();
- }
- },
- Operation::Insert(insert) => {
- inverted.delete(insert.num_chars());
- },
- Operation::Delete(delete) => {
- inverted.insert(
- &chars.take(*delete as usize).collect::<String>(),
- op.get_attributes(),
- );
- },
- }
- }
- inverted
- }
- pub fn invert(&self, other: &Delta) -> Delta {
- let mut inverted = Delta::default();
- if other.is_empty() {
- return inverted;
- }
- let inverted_from_other =
- |inverted: &mut Delta, operation: &Operation, start: usize, end: usize| {
- let ops = other.ops_in_interval(Interval::new(start, end));
- ops.into_iter().for_each(|other_op| {
- match operation {
- Operation::Delete(_) => {
- inverted.add(other_op);
- },
- Operation::Retain(_) => {
- log::debug!(
- "Start invert attributes: {:?}, {:?}",
- operation.get_attributes(),
- other_op.get_attributes()
- );
- let inverted_attrs = invert_attributes(
- operation.get_attributes(),
- other_op.get_attributes(),
- );
- log::debug!("End invert attributes: {:?}", inverted_attrs);
- inverted.retain(other_op.length(), inverted_attrs);
- },
- Operation::Insert(_) => {
- // Impossible to here
- panic!()
- },
- }
- });
- };
- let mut index = 0;
- for op in &self.ops {
- let len: usize = op.length() as usize;
- log::info!("{:?}", op);
- match op {
- Operation::Delete(_) => {
- inverted_from_other(&mut inverted, op, index, index + len);
- index += len;
- },
- Operation::Retain(_) => {
- match op.has_attribute() {
- true => inverted_from_other(&mut inverted, op, index, index + len),
- false => inverted.retain(len as usize, op.get_attributes()),
- }
- index += len;
- },
- Operation::Insert(_) => {
- inverted.delete(len as usize);
- },
- }
- }
- inverted
- }
- /// Checks if this operation has no effect.
- #[inline]
- pub fn is_noop(&self) -> bool {
- match self.ops.as_slice() {
- [] => true,
- [Operation::Retain(_)] => true,
- _ => false,
- }
- }
- pub fn is_empty(&self) -> bool { self.ops.is_empty() }
- pub fn ops_in_interval(&self, interval: Interval) -> Vec<Operation> {
- let mut ops: Vec<Operation> = Vec::with_capacity(self.ops.len());
- let mut offset: usize = 0;
- let mut ops_iter = self.ops.iter();
- let mut next_op = ops_iter.next();
- while offset < interval.end && next_op.is_some() {
- let op = next_op.take().unwrap();
- let len = offset + op.length() as usize;
- // log::info!("{:?}", op);
- while offset < len {
- if offset < interval.start {
- offset += min(interval.start, op.length() as usize);
- } else {
- if interval.contains(offset) {
- ops.push(op.shrink_to_interval(interval));
- offset += min(op.length() as usize, interval.size());
- } else {
- break;
- }
- }
- }
- next_op = ops_iter.next();
- }
- ops
- }
- pub fn get_attributes(&self, interval: Interval) -> Attributes {
- 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 => {},
- // }
- // }
- },
- 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);
- attributes_data.extend(Some(data.clone()), false);
- }
- },
- Attributes::Empty => {},
- }
- offset += end
- },
- });
- attributes_data.into_attributes()
- }
- pub fn to_json(&self) -> String { serde_json::to_string(self).unwrap_or("".to_owned()) }
- }
|