123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270 |
- use crate::core::{Body, Changeset, NodeData, OperationTransform, Path};
- use crate::errors::OTError;
- use serde::{Deserialize, Serialize};
- use std::sync::Arc;
- #[derive(Debug, Clone, Serialize, Deserialize)]
- #[serde(tag = "op")]
- pub enum NodeOperation {
- #[serde(rename = "insert")]
- Insert { path: Path, nodes: Vec<NodeData> },
- #[serde(rename = "update")]
- Update { path: Path, changeset: Changeset },
- #[serde(rename = "delete")]
- Delete { path: Path, nodes: Vec<NodeData> },
- }
- impl NodeOperation {
- pub fn get_path(&self) -> &Path {
- match self {
- NodeOperation::Insert { path, .. } => path,
- NodeOperation::Delete { path, .. } => path,
- NodeOperation::Update { path, .. } => path,
- }
- }
- pub fn get_mut_path(&mut self) -> &mut Path {
- match self {
- NodeOperation::Insert { path, .. } => path,
- NodeOperation::Delete { path, .. } => path,
- NodeOperation::Update { path, .. } => path,
- }
- }
- pub fn is_update_delta(&self) -> bool {
- match self {
- NodeOperation::Insert { .. } => false,
- NodeOperation::Update { path: _, changeset } => changeset.is_delta(),
- NodeOperation::Delete { .. } => false,
- }
- }
- pub fn is_update_attribute(&self) -> bool {
- match self {
- NodeOperation::Insert { .. } => false,
- NodeOperation::Update { path: _, changeset } => changeset.is_attribute(),
- NodeOperation::Delete { .. } => false,
- }
- }
- pub fn is_insert(&self) -> bool {
- match self {
- NodeOperation::Insert { .. } => true,
- NodeOperation::Update { .. } => false,
- NodeOperation::Delete { .. } => false,
- }
- }
- pub fn can_compose(&self, other: &NodeOperation) -> bool {
- if self.get_path() != other.get_path() {
- return false;
- }
- if self.is_update_delta() && other.is_update_delta() {
- return true;
- }
- if self.is_update_attribute() && other.is_update_attribute() {
- return true;
- }
- if self.is_insert() && other.is_update_delta() {
- return true;
- }
- false
- }
- pub fn compose(&mut self, other: &NodeOperation) -> Result<(), OTError> {
- match (self, other) {
- (
- NodeOperation::Insert { path: _, nodes },
- NodeOperation::Update {
- path: _other_path,
- changeset,
- },
- ) => {
- match changeset {
- Changeset::Delta { delta, inverted: _ } => {
- if let Body::Delta(old_delta) = &mut nodes.last_mut().unwrap().body {
- let new_delta = old_delta.compose(delta)?;
- *old_delta = new_delta;
- }
- },
- Changeset::Attributes { new: _, old: _ } => {
- return Err(OTError::compose().context("Can't compose the attributes changeset"));
- },
- }
- Ok(())
- },
- (
- NodeOperation::Update { path: _, changeset },
- NodeOperation::Update {
- path: _,
- changeset: other_changeset,
- },
- ) => changeset.compose(other_changeset),
- (_left, _right) => Err(OTError::compose().context("Can't compose the operation")),
- }
- }
- pub fn inverted(&self) -> NodeOperation {
- match self {
- NodeOperation::Insert { path, nodes } => NodeOperation::Delete {
- path: path.clone(),
- nodes: nodes.clone(),
- },
- NodeOperation::Delete { path, nodes } => NodeOperation::Insert {
- path: path.clone(),
- nodes: nodes.clone(),
- },
- NodeOperation::Update {
- path,
- changeset: body,
- } => NodeOperation::Update {
- path: path.clone(),
- changeset: body.inverted(),
- },
- }
- }
- /// Make the `other` operation can be applied to the version after applying the `self` operation.
- /// The semantics of transform is used when editing conflicts occur, which is often determined by the version id。
- /// For example, if the inserted position has been acquired by others, then it's needed to do the transform to
- /// make sure the inserted position is right.
- ///
- /// # Arguments
- ///
- /// * `other`: The operation that is going to be transformed
- ///
- /// # Examples
- ///
- /// ```
- /// use lib_ot::core::{NodeDataBuilder, NodeOperation, Path};
- /// let node_1 = NodeDataBuilder::new("text_1").build();
- /// let node_2 = NodeDataBuilder::new("text_2").build();
- ///
- /// let op_1 = NodeOperation::Insert {
- /// path: Path(vec![0, 1]),
- /// nodes: vec![node_1],
- /// };
- ///
- /// let mut op_2 = NodeOperation::Insert {
- /// path: Path(vec![0, 1]),
- /// nodes: vec![node_2],
- /// };
- ///
- /// assert_eq!(serde_json::to_string(&op_2).unwrap(), r#"{"op":"insert","path":[0,1],"nodes":[{"type":"text_2"}]}"#);
- ///
- /// op_1.transform(&mut op_2);
- /// assert_eq!(serde_json::to_string(&op_2).unwrap(), r#"{"op":"insert","path":[0,2],"nodes":[{"type":"text_2"}]}"#);
- /// assert_eq!(serde_json::to_string(&op_1).unwrap(), r#"{"op":"insert","path":[0,1],"nodes":[{"type":"text_1"}]}"#);
- /// ```
- pub fn transform(&self, other: &mut NodeOperation) {
- match self {
- NodeOperation::Insert { path, nodes } => {
- let new_path = path.transform(other.get_path(), nodes.len());
- *other.get_mut_path() = new_path;
- },
- NodeOperation::Delete { path, nodes } => {
- let new_path = path.transform(other.get_path(), nodes.len());
- *other.get_mut_path() = new_path;
- },
- _ => {
- // Only insert/delete will change the path.
- },
- }
- }
- }
- type OperationIndexMap = Vec<Arc<NodeOperation>>;
- #[derive(Debug, Clone, Default)]
- pub struct NodeOperations {
- inner: OperationIndexMap,
- }
- impl NodeOperations {
- pub fn new() -> Self {
- Self::default()
- }
- pub fn from_operations(operations: Vec<NodeOperation>) -> Self {
- let mut ops = Self::new();
- for op in operations {
- ops.push_op(op)
- }
- ops
- }
- pub fn from_bytes(bytes: Vec<u8>) -> Result<Self, OTError> {
- let operation_list =
- serde_json::from_slice(&bytes).map_err(|err| OTError::serde().context(err))?;
- Ok(operation_list)
- }
- pub fn to_bytes(&self) -> Result<Vec<u8>, OTError> {
- let bytes = serde_json::to_vec(self).map_err(|err| OTError::serde().context(err))?;
- Ok(bytes)
- }
- pub fn values(&self) -> &Vec<Arc<NodeOperation>> {
- &self.inner
- }
- pub fn values_mut(&mut self) -> &mut Vec<Arc<NodeOperation>> {
- &mut self.inner
- }
- pub fn len(&self) -> usize {
- self.values().len()
- }
- pub fn is_empty(&self) -> bool {
- self.inner.is_empty()
- }
- pub fn into_inner(self) -> Vec<Arc<NodeOperation>> {
- self.inner
- }
- pub fn push_op<T: Into<Arc<NodeOperation>>>(&mut self, other: T) {
- let other = other.into();
- if let Some(last_operation) = self.inner.last_mut() {
- if last_operation.can_compose(&other) {
- let mut_operation = Arc::make_mut(last_operation);
- if mut_operation.compose(&other).is_ok() {
- return;
- }
- }
- }
- // If the passed-in operation can't be composed, then append it to the end.
- self.inner.push(other);
- }
- pub fn compose(&mut self, other: NodeOperations) {
- for operation in other.values() {
- self.push_op(operation.clone());
- }
- }
- pub fn inverted(&self) -> Self {
- let mut operations = Self::new();
- for operation in self.values() {
- operations.push_op(operation.inverted());
- }
- operations
- }
- }
- impl std::convert::From<Vec<NodeOperation>> for NodeOperations {
- fn from(operations: Vec<NodeOperation>) -> Self {
- Self::from_operations(operations)
- }
- }
- impl std::convert::From<NodeOperation> for NodeOperations {
- fn from(operation: NodeOperation) -> Self {
- Self::from_operations(vec![operation])
- }
- }
|