diff --git a/frontend/rust-lib/flowy-folder/src/manager.rs b/frontend/rust-lib/flowy-folder/src/manager.rs index 3a62924e83..3df48e428e 100644 --- a/frontend/rust-lib/flowy-folder/src/manager.rs +++ b/frontend/rust-lib/flowy-folder/src/manager.rs @@ -16,7 +16,7 @@ use flowy_error::FlowyError; use flowy_folder_data_model::user_default; use flowy_revision::disk::SQLiteTextBlockRevisionPersistence; use flowy_revision::{RevisionManager, RevisionPersistence, RevisionWebSocket, SQLiteRevisionSnapshotPersistence}; -use flowy_sync::client_document::default::{initial_quill_delta_string, initial_read_me}; +use flowy_sync::client_document::default::{initial_document_str, initial_read_me}; use flowy_sync::{client_folder::FolderPad, entities::ws_data::ServerRevisionWSData}; use lazy_static::lazy_static; use lib_infra::future::FutureResult; @@ -218,7 +218,7 @@ impl DefaultFolderBuilder { let view_data = if index == 0 { initial_read_me().json_str() } else { - initial_quill_delta_string() + initial_document_str() }; let _ = view_controller.set_latest_view(&view.id); let layout_type = ViewLayoutTypePB::from(view.layout.clone()); diff --git a/frontend/rust-lib/flowy-folder/src/services/folder_editor.rs b/frontend/rust-lib/flowy-folder/src/services/folder_editor.rs index 6f68497edd..a8c54fd0ad 100644 --- a/frontend/rust-lib/flowy-folder/src/services/folder_editor.rs +++ b/frontend/rust-lib/flowy-folder/src/services/folder_editor.rs @@ -4,13 +4,14 @@ use flowy_error::{FlowyError, FlowyResult}; use flowy_revision::{ RevisionCloudService, RevisionCompactor, RevisionManager, RevisionObjectBuilder, RevisionWebSocket, }; -use flowy_sync::util::make_text_delta_from_revisions; +use flowy_sync::util::make_operations_from_revisions; use flowy_sync::{ client_folder::{FolderChangeset, FolderPad}, entities::{revision::Revision, ws_data::ServerRevisionWSData}, }; use lib_infra::future::FutureResult; +use lib_ot::core::EmptyAttributes; use parking_lot::RwLock; use std::sync::Arc; @@ -77,7 +78,7 @@ impl FolderEditor { } pub(crate) fn apply_change(&self, change: FolderChangeset) -> FlowyResult<()> { - let FolderChangeset { delta, md5 } = change; + let FolderChangeset { operations: delta, md5 } = change; let (base_rev_id, rev_id) = self.rev_manager.next_rev_id_pair(); let delta_data = delta.json_bytes(); let revision = Revision::new( @@ -131,7 +132,7 @@ impl FolderEditor { pub struct FolderRevisionCompactor(); impl RevisionCompactor for FolderRevisionCompactor { fn bytes_from_revisions(&self, revisions: Vec) -> FlowyResult { - let delta = make_text_delta_from_revisions(revisions)?; - Ok(delta.json_bytes()) + let operations = make_operations_from_revisions::(revisions)?; + Ok(operations.json_bytes()) } } diff --git a/frontend/rust-lib/flowy-folder/src/services/web_socket.rs b/frontend/rust-lib/flowy-folder/src/services/web_socket.rs index 40eeb77177..ce122073eb 100644 --- a/frontend/rust-lib/flowy-folder/src/services/web_socket.rs +++ b/frontend/rust-lib/flowy-folder/src/services/web_socket.rs @@ -52,10 +52,10 @@ struct FolderConflictResolver { } impl ConflictResolver for FolderConflictResolver { - fn compose_delta(&self, delta: Delta) -> BoxResultFuture { + fn compose_delta(&self, delta: Delta) -> BoxResultFuture { let folder_pad = self.folder_pad.clone(); Box::pin(async move { - let md5 = folder_pad.write().compose_remote_delta(delta)?; + let md5 = folder_pad.write().compose_remote_operations(delta)?; Ok(md5) }) } @@ -70,7 +70,7 @@ impl ConflictResolver for FolderConflictResolver { // Do nothing client_prime = delta; } else { - let (s_prime, c_prime) = read_guard.delta().transform(&delta)?; + let (s_prime, c_prime) = read_guard.get_operations().transform(&delta)?; client_prime = c_prime; server_prime = Some(s_prime); } @@ -82,7 +82,7 @@ impl ConflictResolver for FolderConflictResolver { }) } - fn reset_delta(&self, delta: Delta) -> BoxResultFuture { + fn reset_delta(&self, delta: Delta) -> BoxResultFuture { let folder_pad = self.folder_pad.clone(); Box::pin(async move { let md5 = folder_pad.write().reset_folder(delta)?; diff --git a/frontend/rust-lib/flowy-grid/src/manager.rs b/frontend/rust-lib/flowy-grid/src/manager.rs index 3e7b97f50b..24811ca889 100644 --- a/frontend/rust-lib/flowy-grid/src/manager.rs +++ b/frontend/rust-lib/flowy-grid/src/manager.rs @@ -14,7 +14,7 @@ use flowy_error::{FlowyError, FlowyResult}; use flowy_grid_data_model::revision::{BuildGridContext, GridRevision, GridViewRevision}; use flowy_revision::disk::{SQLiteGridBlockRevisionPersistence, SQLiteGridRevisionPersistence}; use flowy_revision::{RevisionManager, RevisionPersistence, RevisionWebSocket, SQLiteRevisionSnapshotPersistence}; -use flowy_sync::client_grid::{make_grid_block_delta, make_grid_delta, make_grid_view_delta}; +use flowy_sync::client_grid::{make_grid_block_operations, make_grid_operations, make_grid_view_operations}; use flowy_sync::entities::revision::{RepeatedRevision, Revision}; use std::sync::Arc; use tokio::sync::RwLock; @@ -198,7 +198,7 @@ pub async fn make_grid_view_data( }); // Create grid's block - let grid_block_delta = make_grid_block_delta(block_meta_data); + let grid_block_delta = make_grid_block_operations(block_meta_data); let block_delta_data = grid_block_delta.json_bytes(); let repeated_revision: RepeatedRevision = Revision::initial_revision(user_id, block_id, block_delta_data).into(); @@ -210,7 +210,7 @@ pub async fn make_grid_view_data( let grid_rev = GridRevision::from_build_context(&grid_id, field_revs, block_metas); // Create grid - let grid_rev_delta = make_grid_delta(&grid_rev); + let grid_rev_delta = make_grid_operations(&grid_rev); let grid_rev_delta_bytes = grid_rev_delta.json_bytes(); let repeated_revision: RepeatedRevision = Revision::initial_revision(user_id, &grid_id, grid_rev_delta_bytes.clone()).into(); @@ -222,7 +222,7 @@ pub async fn make_grid_view_data( } else { GridViewRevision::from_json(grid_view_revision_data)? }; - let grid_view_delta = make_grid_view_delta(&grid_view); + let grid_view_delta = make_grid_view_operations(&grid_view); let grid_view_delta_bytes = grid_view_delta.json_bytes(); let repeated_revision: RepeatedRevision = Revision::initial_revision(user_id, view_id, grid_view_delta_bytes).into(); diff --git a/frontend/rust-lib/flowy-grid/src/services/block_editor.rs b/frontend/rust-lib/flowy-grid/src/services/block_editor.rs index f576742c90..0c313a869f 100644 --- a/frontend/rust-lib/flowy-grid/src/services/block_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/block_editor.rs @@ -5,9 +5,10 @@ use flowy_grid_data_model::revision::{CellRevision, GridBlockRevision, RowChange use flowy_revision::{RevisionCloudService, RevisionCompactor, RevisionManager, RevisionObjectBuilder}; use flowy_sync::client_grid::{GridBlockRevisionChangeset, GridBlockRevisionPad}; use flowy_sync::entities::revision::Revision; -use flowy_sync::util::make_text_delta_from_revisions; +use flowy_sync::util::make_operations_from_revisions; use lib_infra::future::FutureResult; +use lib_ot::core::EmptyAttributes; use std::borrow::Cow; use std::sync::Arc; use tokio::sync::RwLock; @@ -162,7 +163,7 @@ impl GridBlockRevisionEditor { } async fn apply_change(&self, change: GridBlockRevisionChangeset) -> FlowyResult<()> { - let GridBlockRevisionChangeset { delta, md5 } = change; + let GridBlockRevisionChangeset { operations: delta, md5 } = change; let user_id = self.user_id.clone(); let (base_rev_id, rev_id) = self.rev_manager.next_rev_id_pair(); let delta_data = delta.json_bytes(); @@ -204,7 +205,7 @@ impl RevisionObjectBuilder for GridBlockRevisionPadBuilder { pub struct GridBlockRevisionCompactor(); impl RevisionCompactor for GridBlockRevisionCompactor { fn bytes_from_revisions(&self, revisions: Vec) -> FlowyResult { - let delta = make_text_delta_from_revisions(revisions)?; - Ok(delta.json_bytes()) + let operations = make_operations_from_revisions::(revisions)?; + Ok(operations.json_bytes()) } } diff --git a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs index 3607a1ce74..bbcdb56e1b 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -17,9 +17,10 @@ use flowy_revision::{RevisionCloudService, RevisionCompactor, RevisionManager, R use flowy_sync::client_grid::{GridRevisionChangeset, GridRevisionPad, JsonDeserializer}; use flowy_sync::entities::revision::Revision; use flowy_sync::errors::CollaborateResult; -use flowy_sync::util::make_text_delta_from_revisions; +use flowy_sync::util::make_operations_from_revisions; use lib_infra::future::{wrap_future, FutureResult}; +use lib_ot::core::EmptyAttributes; use std::collections::HashMap; use std::sync::Arc; use tokio::sync::RwLock; @@ -147,7 +148,7 @@ impl GridRevisionEditor { } pub async fn next_field_rev(&self, field_type: &FieldType) -> FlowyResult { - let name = format!("Property {}", self.grid_pad.read().await.fields().len() + 1); + let name = format!("Property {}", self.grid_pad.read().await.get_fields().len() + 1); let field_rev = FieldBuilder::from_field_type(field_type).name(&name).build(); Ok(field_rev) } @@ -675,10 +676,6 @@ impl GridRevisionEditor { Ok(()) } - pub async fn delta_bytes(&self) -> Bytes { - self.grid_pad.read().await.delta_bytes() - } - pub async fn duplicate_grid(&self) -> FlowyResult { let grid_pad = self.grid_pad.read().await; let grid_view_revision_data = self.view_manager.duplicate_grid_view().await?; @@ -750,7 +747,7 @@ impl GridRevisionEditor { } async fn apply_change(&self, change: GridRevisionChangeset) -> FlowyResult<()> { - let GridRevisionChangeset { delta, md5 } = change; + let GridRevisionChangeset { operations: delta, md5 } = change; let user_id = self.user.user_id()?; let (base_rev_id, rev_id) = self.rev_manager.next_rev_id_pair(); let delta_data = delta.json_bytes(); @@ -844,8 +841,8 @@ impl RevisionCloudService for GridRevisionCloudService { pub struct GridRevisionCompactor(); impl RevisionCompactor for GridRevisionCompactor { fn bytes_from_revisions(&self, revisions: Vec) -> FlowyResult { - let delta = make_text_delta_from_revisions(revisions)?; - Ok(delta.json_bytes()) + let operations = make_operations_from_revisions::(revisions)?; + Ok(operations.json_bytes()) } } diff --git a/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs b/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs index ce0edbef6f..d9f245c8b9 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_view_editor.rs @@ -435,7 +435,7 @@ async fn apply_change( rev_manager: Arc, change: GridViewRevisionChangeset, ) -> FlowyResult<()> { - let GridViewRevisionChangeset { delta, md5 } = change; + let GridViewRevisionChangeset { operations: delta, md5 } = change; let (base_rev_id, rev_id) = rev_manager.next_rev_id_pair(); let delta_data = delta.json_bytes(); let revision = Revision::new(&rev_manager.object_id, base_rev_id, rev_id, delta_data, user_id, md5); diff --git a/frontend/rust-lib/flowy-grid/src/services/grid_view_manager.rs b/frontend/rust-lib/flowy-grid/src/services/grid_view_manager.rs index 65ed1af6c5..c57dbda2f2 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_view_manager.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_view_manager.rs @@ -12,8 +12,9 @@ use flowy_grid_data_model::revision::{FieldRevision, RowChangeset, RowRevision}; use flowy_revision::disk::SQLiteGridViewRevisionPersistence; use flowy_revision::{RevisionCompactor, RevisionManager, RevisionPersistence, SQLiteRevisionSnapshotPersistence}; use flowy_sync::entities::revision::Revision; -use flowy_sync::util::make_text_delta_from_revisions; +use flowy_sync::util::make_operations_from_revisions; use lib_infra::future::AFFuture; +use lib_ot::core::EmptyAttributes; use std::sync::Arc; type ViewId = String; @@ -262,7 +263,7 @@ pub async fn make_grid_view_rev_manager(user: &Arc, view_id: &str) pub struct GridViewRevisionCompactor(); impl RevisionCompactor for GridViewRevisionCompactor { fn bytes_from_revisions(&self, revisions: Vec) -> FlowyResult { - let delta = make_text_delta_from_revisions(revisions)?; - Ok(delta.json_bytes()) + let operations = make_operations_from_revisions::(revisions)?; + Ok(operations.json_bytes()) } } diff --git a/frontend/rust-lib/flowy-net/src/local_server/server.rs b/frontend/rust-lib/flowy-net/src/local_server/server.rs index 060abf08bf..fbdba41098 100644 --- a/frontend/rust-lib/flowy-net/src/local_server/server.rs +++ b/frontend/rust-lib/flowy-net/src/local_server/server.rs @@ -4,7 +4,7 @@ use bytes::Bytes; use flowy_error::{internal_error, FlowyError}; use flowy_folder::event_map::FolderCouldServiceV1; use flowy_sync::{ - client_document::default::initial_quill_delta_string, + client_document::default::initial_document_str, entities::{ text_block::{CreateTextBlockParams, DocumentPB, ResetTextBlockParams, TextBlockIdPB}, ws_data::{ClientRevisionWSData, ClientRevisionWSDataType}, @@ -422,7 +422,7 @@ impl TextEditorCloudService for LocalServer { fn read_text_block(&self, _token: &str, params: TextBlockIdPB) -> FutureResult, FlowyError> { let doc = DocumentPB { block_id: params.value, - text: initial_quill_delta_string(), + text: initial_document_str(), rev_id: 0, base_rev_id: 0, }; diff --git a/frontend/rust-lib/flowy-revision/src/cache/disk/document_impl.rs b/frontend/rust-lib/flowy-revision/src/cache/disk/document_impl.rs index 31b69e0291..a220f0e625 100644 --- a/frontend/rust-lib/flowy-revision/src/cache/disk/document_impl.rs +++ b/frontend/rust-lib/flowy-revision/src/cache/disk/document_impl.rs @@ -109,7 +109,7 @@ impl TextRevisionSql { dsl::doc_id.eq(record.revision.object_id), dsl::base_rev_id.eq(record.revision.base_rev_id), dsl::rev_id.eq(record.revision.rev_id), - dsl::data.eq(record.revision.delta_data), + dsl::data.eq(record.revision.bytes), dsl::state.eq(rev_state), dsl::ty.eq(RevTableType::Local), ) diff --git a/frontend/rust-lib/flowy-revision/src/cache/disk/grid_block_impl.rs b/frontend/rust-lib/flowy-revision/src/cache/disk/grid_block_impl.rs index 2fcdb7e748..a12c5c1ad5 100644 --- a/frontend/rust-lib/flowy-revision/src/cache/disk/grid_block_impl.rs +++ b/frontend/rust-lib/flowy-revision/src/cache/disk/grid_block_impl.rs @@ -108,7 +108,7 @@ impl GridMetaRevisionSql { dsl::object_id.eq(record.revision.object_id), dsl::base_rev_id.eq(record.revision.base_rev_id), dsl::rev_id.eq(record.revision.rev_id), - dsl::data.eq(record.revision.delta_data), + dsl::data.eq(record.revision.bytes), dsl::state.eq(rev_state), ) }) diff --git a/frontend/rust-lib/flowy-revision/src/cache/disk/grid_impl.rs b/frontend/rust-lib/flowy-revision/src/cache/disk/grid_impl.rs index bb6e561c91..aef127baea 100644 --- a/frontend/rust-lib/flowy-revision/src/cache/disk/grid_impl.rs +++ b/frontend/rust-lib/flowy-revision/src/cache/disk/grid_impl.rs @@ -107,7 +107,7 @@ impl GridRevisionSql { dsl::object_id.eq(record.revision.object_id), dsl::base_rev_id.eq(record.revision.base_rev_id), dsl::rev_id.eq(record.revision.rev_id), - dsl::data.eq(record.revision.delta_data), + dsl::data.eq(record.revision.bytes), dsl::state.eq(rev_state), ) }) diff --git a/frontend/rust-lib/flowy-revision/src/cache/disk/grid_view_impl.rs b/frontend/rust-lib/flowy-revision/src/cache/disk/grid_view_impl.rs index 2d7cbd59b2..71d923e046 100644 --- a/frontend/rust-lib/flowy-revision/src/cache/disk/grid_view_impl.rs +++ b/frontend/rust-lib/flowy-revision/src/cache/disk/grid_view_impl.rs @@ -106,7 +106,7 @@ impl GridViewRevisionSql { dsl::object_id.eq(record.revision.object_id), dsl::base_rev_id.eq(record.revision.base_rev_id), dsl::rev_id.eq(record.revision.rev_id), - dsl::data.eq(record.revision.delta_data), + dsl::data.eq(record.revision.bytes), dsl::state.eq(rev_state), ) }) diff --git a/frontend/rust-lib/flowy-revision/src/conflict_resolve.rs b/frontend/rust-lib/flowy-revision/src/conflict_resolve.rs index 51e37a363c..d51e503a59 100644 --- a/frontend/rust-lib/flowy-revision/src/conflict_resolve.rs +++ b/frontend/rust-lib/flowy-revision/src/conflict_resolve.rs @@ -6,23 +6,23 @@ use flowy_sync::{ revision::{RepeatedRevision, Revision, RevisionRange}, ws_data::ServerRevisionWSDataType, }, - util::make_delta_from_revisions, + util::make_operations_from_revisions, }; use lib_infra::future::BoxResultFuture; -use lib_ot::core::{Attributes, EmptyAttributes, OperationAttributes, Operations}; +use lib_ot::core::{AttributeHashMap, DeltaOperations, EmptyAttributes, OperationAttributes}; use serde::de::DeserializeOwned; use std::{convert::TryFrom, sync::Arc}; -pub type DeltaMD5 = String; +pub type OperationsMD5 = String; pub trait ConflictResolver where T: OperationAttributes + Send + Sync, { - fn compose_delta(&self, delta: Operations) -> BoxResultFuture; - fn transform_delta(&self, delta: Operations) -> BoxResultFuture, FlowyError>; - fn reset_delta(&self, delta: Operations) -> BoxResultFuture; + fn compose_delta(&self, delta: DeltaOperations) -> BoxResultFuture; + fn transform_delta(&self, delta: DeltaOperations) -> BoxResultFuture, FlowyError>; + fn reset_delta(&self, delta: DeltaOperations) -> BoxResultFuture; } pub trait ConflictRevisionSink: Send + Sync + 'static { @@ -30,7 +30,7 @@ pub trait ConflictRevisionSink: Send + Sync + 'static { fn ack(&self, rev_id: String, ty: ServerRevisionWSDataType) -> BoxResultFuture<(), FlowyError>; } -pub type RichTextConflictController = ConflictController; +pub type RichTextConflictController = ConflictController; pub type PlainTextConflictController = ConflictController; pub struct ConflictController @@ -103,7 +103,7 @@ where } } - let new_delta = make_delta_from_revisions(revisions.clone())?; + let new_delta = make_operations_from_revisions(revisions.clone())?; let TransformDeltas { client_prime, @@ -142,8 +142,8 @@ where fn make_client_and_server_revision( user_id: &str, rev_manager: &Arc, - client_delta: Operations, - server_delta: Option>, + client_delta: DeltaOperations, + server_delta: Option>, md5: String, ) -> (Revision, Option) where @@ -175,12 +175,12 @@ where } } -pub type RichTextTransformDeltas = TransformDeltas; +pub type RichTextTransformDeltas = TransformDeltas; pub struct TransformDeltas where T: OperationAttributes, { - pub client_prime: Operations, - pub server_prime: Option>, + pub client_prime: DeltaOperations, + pub server_prime: Option>, } diff --git a/frontend/rust-lib/flowy-revision/src/rev_manager.rs b/frontend/rust-lib/flowy-revision/src/rev_manager.rs index bd4d01740d..73592cad85 100644 --- a/frontend/rust-lib/flowy-revision/src/rev_manager.rs +++ b/frontend/rust-lib/flowy-revision/src/rev_manager.rs @@ -9,6 +9,8 @@ use flowy_sync::{ use lib_infra::future::FutureResult; use std::sync::Arc; +pub type SyncObject = lib_ot::text_delta::TextOperations; + pub trait RevisionCloudService: Send + Sync { fn fetch_object(&self, user_id: &str, object_id: &str) -> FutureResult, FlowyError>; } @@ -33,8 +35,8 @@ pub trait RevisionCompactor: Send + Sync { let (base_rev_id, rev_id) = first_revision.pair_rev_id(); let md5 = last_revision.md5.clone(); - let delta_data = self.bytes_from_revisions(revisions)?; - Ok(Revision::new(object_id, base_rev_id, rev_id, delta_data, user_id, md5)) + let bytes = self.bytes_from_revisions(revisions)?; + Ok(Revision::new(object_id, base_rev_id, rev_id, bytes, user_id, md5)) } fn bytes_from_revisions(&self, revisions: Vec) -> FlowyResult; @@ -113,7 +115,7 @@ impl RevisionManager { #[tracing::instrument(level = "debug", skip(self, revision), err)] pub async fn add_remote_revision(&self, revision: &Revision) -> Result<(), FlowyError> { - if revision.delta_data.is_empty() { + if revision.bytes.is_empty() { return Err(FlowyError::internal().context("Delta data should be empty")); } @@ -125,7 +127,7 @@ impl RevisionManager { #[tracing::instrument(level = "debug", skip_all, err)] pub async fn add_local_revision(&self, revision: &Revision) -> Result<(), FlowyError> { - if revision.delta_data.is_empty() { + if revision.bytes.is_empty() { return Err(FlowyError::internal().context("Delta data should be empty")); } let rev_id = self diff --git a/frontend/rust-lib/flowy-sdk/src/deps_resolve/folder_deps.rs b/frontend/rust-lib/flowy-sdk/src/deps_resolve/folder_deps.rs index f9eac21ba0..c2730afe4e 100644 --- a/frontend/rust-lib/flowy-sdk/src/deps_resolve/folder_deps.rs +++ b/frontend/rust-lib/flowy-sdk/src/deps_resolve/folder_deps.rs @@ -16,7 +16,7 @@ use flowy_net::{ http_server::folder::FolderHttpCloudService, local_server::LocalServer, ws::connection::FlowyWebSocketConnect, }; use flowy_revision::{RevisionWebSocket, WSStateReceiver}; -use flowy_sync::client_document::default::initial_quill_delta_string; +use flowy_sync::client_document::default::initial_document_str; use flowy_sync::entities::revision::{RepeatedRevision, Revision}; use flowy_sync::entities::ws_data::ClientRevisionWSData; use flowy_text_block::TextEditorManager; @@ -191,7 +191,7 @@ impl ViewDataProcessor for TextBlockViewDataProcessor { let view_id = view_id.to_string(); let manager = self.0.clone(); FutureResult::new(async move { - let view_data = initial_quill_delta_string(); + let view_data = initial_document_str(); let delta_data = Bytes::from(view_data); let repeated_revision: RepeatedRevision = Revision::initial_revision(&user_id, &view_id, delta_data.clone()).into(); diff --git a/frontend/rust-lib/flowy-text-block/src/editor.rs b/frontend/rust-lib/flowy-text-block/src/editor.rs index 8698cebc7f..6e57b281f5 100644 --- a/frontend/rust-lib/flowy-text-block/src/editor.rs +++ b/frontend/rust-lib/flowy-text-block/src/editor.rs @@ -11,12 +11,12 @@ use flowy_sync::entities::ws_data::ServerRevisionWSData; use flowy_sync::{ entities::{revision::Revision, text_block::DocumentPB}, errors::CollaborateResult, - util::make_delta_from_revisions, + util::make_operations_from_revisions, }; use lib_ot::core::AttributeEntry; use lib_ot::{ - core::{Interval, Operation}, - text_delta::TextDelta, + core::{DeltaOperation, Interval}, + text_delta::TextOperations, }; use lib_ws::WSConnectState; use std::sync::Arc; @@ -150,7 +150,7 @@ impl TextBlockEditor { #[tracing::instrument(level = "trace", skip(self, data), err)] pub(crate) async fn compose_local_delta(&self, data: Bytes) -> Result<(), FlowyError> { - let delta = TextDelta::from_bytes(&data)?; + let delta = TextOperations::from_bytes(&data)?; let (ret, rx) = oneshot::channel::>(); let msg = EditorCommand::ComposeLocalDelta { delta: delta.clone(), @@ -196,7 +196,7 @@ impl std::ops::Drop for TextBlockEditor { fn spawn_edit_queue( user: Arc, rev_manager: Arc, - delta: TextDelta, + delta: TextOperations, ) -> EditorCommandSender { let (sender, receiver) = mpsc::channel(1000); let edit_queue = EditBlockQueue::new(user, rev_manager, delta, receiver); @@ -215,8 +215,8 @@ fn spawn_edit_queue( #[cfg(feature = "flowy_unit_test")] impl TextBlockEditor { - pub async fn text_block_delta(&self) -> FlowyResult { - let (ret, rx) = oneshot::channel::>(); + pub async fn text_block_delta(&self) -> FlowyResult { + let (ret, rx) = oneshot::channel::>(); let msg = EditorCommand::ReadDelta { ret }; let _ = self.edit_cmd_tx.send(msg).await; let delta = rx.await.map_err(internal_error)??; @@ -234,7 +234,7 @@ impl RevisionObjectBuilder for TextBlockInfoBuilder { fn build_object(object_id: &str, revisions: Vec) -> FlowyResult { let (base_rev_id, rev_id) = revisions.last().unwrap().pair_rev_id(); - let mut delta = make_delta_from_revisions(revisions)?; + let mut delta = make_operations_from_revisions(revisions)?; correct_delta(&mut delta); Result::::Ok(DocumentPB { @@ -248,12 +248,12 @@ impl RevisionObjectBuilder for TextBlockInfoBuilder { // quill-editor requires the delta should end with '\n' and only contains the // insert operation. The function, correct_delta maybe be removed in the future. -fn correct_delta(delta: &mut TextDelta) { +fn correct_delta(delta: &mut TextOperations) { if let Some(op) = delta.ops.last() { let op_data = op.get_data(); if !op_data.ends_with('\n') { tracing::warn!("The document must end with newline. Correcting it by inserting newline op"); - delta.ops.push(Operation::Insert("\n".into())); + delta.ops.push(DeltaOperation::Insert("\n".into())); } } diff --git a/frontend/rust-lib/flowy-text-block/src/queue.rs b/frontend/rust-lib/flowy-text-block/src/queue.rs index 510205c1ba..f6dd5f56b1 100644 --- a/frontend/rust-lib/flowy-text-block/src/queue.rs +++ b/frontend/rust-lib/flowy-text-block/src/queue.rs @@ -3,18 +3,18 @@ use crate::TextEditorUser; use async_stream::stream; use bytes::Bytes; use flowy_error::{FlowyError, FlowyResult}; -use flowy_revision::{DeltaMD5, RevisionCompactor, RevisionManager, RichTextTransformDeltas, TransformDeltas}; -use flowy_sync::util::make_delta_from_revisions; +use flowy_revision::{OperationsMD5, RevisionCompactor, RevisionManager, RichTextTransformDeltas, TransformDeltas}; +use flowy_sync::util::make_operations_from_revisions; use flowy_sync::{ client_document::{history::UndoResult, ClientDocument}, entities::revision::{RevId, Revision}, errors::CollaborateError, }; use futures::stream::StreamExt; -use lib_ot::core::{AttributeEntry, Attributes}; +use lib_ot::core::{AttributeEntry, AttributeHashMap}; use lib_ot::{ core::{Interval, OperationTransform}, - text_delta::TextDelta, + text_delta::TextOperations, }; use std::sync::Arc; use tokio::sync::{oneshot, RwLock}; @@ -32,10 +32,10 @@ impl EditBlockQueue { pub(crate) fn new( user: Arc, rev_manager: Arc, - delta: TextDelta, + delta: TextOperations, receiver: EditorCommandReceiver, ) -> Self { - let document = Arc::new(RwLock::new(ClientDocument::from_delta(delta))); + let document = Arc::new(RwLock::new(ClientDocument::from_operations(delta))); Self { document, user, @@ -69,7 +69,7 @@ impl EditBlockQueue { match command { EditorCommand::ComposeLocalDelta { delta, ret } => { let mut document = self.document.write().await; - let _ = document.compose_delta(delta.clone())?; + let _ = document.compose_operations(delta.clone())?; let md5 = document.md5(); drop(document); let _ = self.save_local_delta(delta, md5).await?; @@ -77,14 +77,14 @@ impl EditBlockQueue { } EditorCommand::ComposeRemoteDelta { client_delta, ret } => { let mut document = self.document.write().await; - let _ = document.compose_delta(client_delta.clone())?; + let _ = document.compose_operations(client_delta.clone())?; let md5 = document.md5(); drop(document); let _ = ret.send(Ok(md5)); } EditorCommand::ResetDelta { delta, ret } => { let mut document = self.document.write().await; - let _ = document.set_delta(delta); + let _ = document.set_operations(delta); let md5 = document.md5(); drop(document); let _ = ret.send(Ok(md5)); @@ -92,14 +92,14 @@ impl EditBlockQueue { EditorCommand::TransformDelta { delta, ret } => { let f = || async { let read_guard = self.document.read().await; - let mut server_prime: Option = None; - let client_prime: TextDelta; + let mut server_prime: Option = None; + let client_prime: TextOperations; if read_guard.is_empty() { // Do nothing client_prime = delta; } else { - let (s_prime, c_prime) = read_guard.delta().transform(&delta)?; + let (s_prime, c_prime) = read_guard.get_operations().transform(&delta)?; client_prime = c_prime; server_prime = Some(s_prime); } @@ -151,31 +151,31 @@ impl EditBlockQueue { } EditorCommand::Undo { ret } => { let mut write_guard = self.document.write().await; - let UndoResult { delta } = write_guard.undo()?; + let UndoResult { operations: delta } = write_guard.undo()?; let md5 = write_guard.md5(); let _ = self.save_local_delta(delta, md5).await?; let _ = ret.send(Ok(())); } EditorCommand::Redo { ret } => { let mut write_guard = self.document.write().await; - let UndoResult { delta } = write_guard.redo()?; + let UndoResult { operations: delta } = write_guard.redo()?; let md5 = write_guard.md5(); let _ = self.save_local_delta(delta, md5).await?; let _ = ret.send(Ok(())); } EditorCommand::ReadDeltaStr { ret } => { - let data = self.document.read().await.delta_str(); + let data = self.document.read().await.get_operations_json(); let _ = ret.send(Ok(data)); } EditorCommand::ReadDelta { ret } => { - let delta = self.document.read().await.delta().clone(); + let delta = self.document.read().await.get_operations().clone(); let _ = ret.send(Ok(delta)); } } Ok(()) } - async fn save_local_delta(&self, delta: TextDelta, md5: String) -> Result { + async fn save_local_delta(&self, delta: TextOperations, md5: String) -> Result { let delta_data = delta.json_bytes(); let (base_rev_id, rev_id) = self.rev_manager.next_rev_id_pair(); let user_id = self.user.user_id()?; @@ -195,7 +195,7 @@ impl EditBlockQueue { pub(crate) struct TextBlockRevisionCompactor(); impl RevisionCompactor for TextBlockRevisionCompactor { fn bytes_from_revisions(&self, revisions: Vec) -> FlowyResult { - let delta = make_delta_from_revisions::(revisions)?; + let delta = make_operations_from_revisions::(revisions)?; Ok(delta.json_bytes()) } } @@ -204,19 +204,19 @@ pub(crate) type Ret = oneshot::Sender>; pub(crate) enum EditorCommand { ComposeLocalDelta { - delta: TextDelta, + delta: TextOperations, ret: Ret<()>, }, ComposeRemoteDelta { - client_delta: TextDelta, - ret: Ret, + client_delta: TextOperations, + ret: Ret, }, ResetDelta { - delta: TextDelta, - ret: Ret, + delta: TextOperations, + ret: Ret, }, TransformDelta { - delta: TextDelta, + delta: TextOperations, ret: Ret, }, Insert { @@ -255,7 +255,7 @@ pub(crate) enum EditorCommand { }, #[allow(dead_code)] ReadDelta { - ret: Ret, + ret: Ret, }, } diff --git a/frontend/rust-lib/flowy-text-block/src/web_socket.rs b/frontend/rust-lib/flowy-text-block/src/web_socket.rs index 06b2791664..742962dd4d 100644 --- a/frontend/rust-lib/flowy-text-block/src/web_socket.rs +++ b/frontend/rust-lib/flowy-text-block/src/web_socket.rs @@ -10,9 +10,9 @@ use flowy_sync::{ errors::CollaborateResult, }; use lib_infra::future::{BoxResultFuture, FutureResult}; -use lib_ot::core::Attributes; +use lib_ot::core::AttributeHashMap; -use lib_ot::text_delta::TextDelta; +use lib_ot::text_delta::TextOperations; use lib_ws::WSConnectState; use std::{sync::Arc, time::Duration}; use tokio::sync::{ @@ -112,8 +112,8 @@ struct TextBlockConflictResolver { edit_cmd_tx: EditorCommandSender, } -impl ConflictResolver for TextBlockConflictResolver { - fn compose_delta(&self, delta: TextDelta) -> BoxResultFuture { +impl ConflictResolver for TextBlockConflictResolver { + fn compose_delta(&self, delta: TextOperations) -> BoxResultFuture { let tx = self.edit_cmd_tx.clone(); Box::pin(async move { let (ret, rx) = oneshot::channel(); @@ -132,7 +132,7 @@ impl ConflictResolver for TextBlockConflictResolver { fn transform_delta( &self, - delta: TextDelta, + delta: TextOperations, ) -> BoxResultFuture { let tx = self.edit_cmd_tx.clone(); Box::pin(async move { @@ -147,7 +147,7 @@ impl ConflictResolver for TextBlockConflictResolver { }) } - fn reset_delta(&self, delta: TextDelta) -> BoxResultFuture { + fn reset_delta(&self, delta: TextOperations) -> BoxResultFuture { let tx = self.edit_cmd_tx.clone(); Box::pin(async move { let (ret, rx) = oneshot::channel(); diff --git a/frontend/rust-lib/flowy-text-block/tests/document/script.rs b/frontend/rust-lib/flowy-text-block/tests/document/script.rs index ae3209020a..8157debd16 100644 --- a/frontend/rust-lib/flowy-text-block/tests/document/script.rs +++ b/frontend/rust-lib/flowy-text-block/tests/document/script.rs @@ -2,7 +2,7 @@ use flowy_revision::disk::RevisionState; use flowy_test::{helper::ViewTest, FlowySDKTest}; use flowy_text_block::editor::TextBlockEditor; use flowy_text_block::TEXT_BLOCK_SYNC_INTERVAL_IN_MILLIS; -use lib_ot::{core::Interval, text_delta::TextDelta}; +use lib_ot::{core::Interval, text_delta::TextOperations}; use std::sync::Arc; use tokio::time::{sleep, Duration}; @@ -71,7 +71,7 @@ impl TextBlockEditorTest { assert_eq!(next_revision.rev_id, rev_id.unwrap()); } EditorScript::AssertJson(expected) => { - let expected_delta: TextDelta = serde_json::from_str(expected).unwrap(); + let expected_delta: TextOperations = serde_json::from_str(expected).unwrap(); let delta = self.editor.text_block_delta().await.unwrap(); if expected_delta != delta { eprintln!("✅ expect: {}", expected,); diff --git a/frontend/rust-lib/flowy-text-block/tests/editor/attribute_test.rs b/frontend/rust-lib/flowy-text-block/tests/editor/attribute_test.rs index 16dc3a69a9..44016fee15 100644 --- a/frontend/rust-lib/flowy-text-block/tests/editor/attribute_test.rs +++ b/frontend/rust-lib/flowy-text-block/tests/editor/attribute_test.rs @@ -3,7 +3,7 @@ use crate::editor::{TestBuilder, TestOp::*}; use flowy_sync::client_document::{NewlineDoc, EmptyDoc}; use lib_ot::core::{Interval, OperationTransform, NEW_LINE, WHITESPACE, OTString}; use unicode_segmentation::UnicodeSegmentation; -use lib_ot::text_delta::TextDelta; +use lib_ot::text_delta::TextOperations; #[test] fn attributes_bold_added() { @@ -762,12 +762,12 @@ fn attributes_preserve_list_format_on_merge() { #[test] fn delta_compose() { - let mut delta = TextDelta::from_json(r#"[{"insert":"\n"}]"#).unwrap(); + let mut delta = TextOperations::from_json(r#"[{"insert":"\n"}]"#).unwrap(); let deltas = vec![ - TextDelta::from_json(r#"[{"retain":1,"attributes":{"list":"unchecked"}}]"#).unwrap(), - TextDelta::from_json(r#"[{"insert":"a"}]"#).unwrap(), - TextDelta::from_json(r#"[{"retain":1},{"insert":"\n","attributes":{"list":"unchecked"}}]"#).unwrap(), - TextDelta::from_json(r#"[{"retain":2},{"retain":1,"attributes":{"list":""}}]"#).unwrap(), + TextOperations::from_json(r#"[{"retain":1,"attributes":{"list":"unchecked"}}]"#).unwrap(), + TextOperations::from_json(r#"[{"insert":"a"}]"#).unwrap(), + TextOperations::from_json(r#"[{"retain":1},{"insert":"\n","attributes":{"list":"unchecked"}}]"#).unwrap(), + TextOperations::from_json(r#"[{"retain":2},{"retain":1,"attributes":{"list":""}}]"#).unwrap(), ]; for d in deltas { diff --git a/frontend/rust-lib/flowy-text-block/tests/editor/mod.rs b/frontend/rust-lib/flowy-text-block/tests/editor/mod.rs index c2eb30e3f4..1cce5aaeca 100644 --- a/frontend/rust-lib/flowy-text-block/tests/editor/mod.rs +++ b/frontend/rust-lib/flowy-text-block/tests/editor/mod.rs @@ -5,10 +5,10 @@ mod serde_test; mod undo_redo_test; use derive_more::Display; -use flowy_sync::client_document::{ClientDocument, InitialDocumentText}; +use flowy_sync::client_document::{ClientDocument, InitialDocumentContent}; use lib_ot::{ core::*, - text_delta::{BuildInTextAttribute, TextDelta}, + text_delta::{BuildInTextAttribute, TextOperations}, }; use rand::{prelude::*, Rng as WrappedRng}; use std::{sync::Once, time::Duration}; @@ -81,8 +81,8 @@ pub enum TestOp { pub struct TestBuilder { documents: Vec, - deltas: Vec>, - primes: Vec>, + deltas: Vec>, + primes: Vec>, } impl TestBuilder { @@ -169,29 +169,29 @@ impl TestBuilder { } TestOp::Transform(delta_a_i, delta_b_i) => { let (a_prime, b_prime) = self.documents[*delta_a_i] - .delta() - .transform(self.documents[*delta_b_i].delta()) + .get_operations() + .transform(self.documents[*delta_b_i].get_operations()) .unwrap(); tracing::trace!("a:{:?},b:{:?}", a_prime, b_prime); - let data_left = self.documents[*delta_a_i].delta().compose(&b_prime).unwrap(); - let data_right = self.documents[*delta_b_i].delta().compose(&a_prime).unwrap(); + let data_left = self.documents[*delta_a_i].get_operations().compose(&b_prime).unwrap(); + let data_right = self.documents[*delta_b_i].get_operations().compose(&a_prime).unwrap(); - self.documents[*delta_a_i].set_delta(data_left); - self.documents[*delta_b_i].set_delta(data_right); + self.documents[*delta_a_i].set_operations(data_left); + self.documents[*delta_b_i].set_operations(data_right); } TestOp::TransformPrime(a_doc_index, b_doc_index) => { let (prime_left, prime_right) = self.documents[*a_doc_index] - .delta() - .transform(self.documents[*b_doc_index].delta()) + .get_operations() + .transform(self.documents[*b_doc_index].get_operations()) .unwrap(); self.primes.insert(*a_doc_index, Some(prime_left)); self.primes.insert(*b_doc_index, Some(prime_right)); } TestOp::Invert(delta_a_i, delta_b_i) => { - let delta_a = &self.documents[*delta_a_i].delta(); - let delta_b = &self.documents[*delta_b_i].delta(); + let delta_a = &self.documents[*delta_a_i].get_operations(); + let delta_b = &self.documents[*delta_b_i].get_operations(); tracing::debug!("Invert: "); tracing::debug!("a: {}", delta_a.json_str()); tracing::debug!("b: {}", delta_b.json_str()); @@ -209,7 +209,7 @@ impl TestBuilder { assert_eq!(delta_a, &&new_delta_after_undo); - self.documents[*delta_a_i].set_delta(new_delta_after_undo); + self.documents[*delta_a_i].set_operations(new_delta_after_undo); } TestOp::Undo(delta_i) => { self.documents[*delta_i].undo().unwrap(); @@ -221,13 +221,13 @@ impl TestBuilder { std::thread::sleep(Duration::from_millis(*mills_sec as u64)); } TestOp::AssertStr(delta_i, expected) => { - assert_eq!(&self.documents[*delta_i].to_plain_string(), expected); + assert_eq!(&self.documents[*delta_i].to_content(), expected); } TestOp::AssertDocJson(delta_i, expected) => { - let delta_json = self.documents[*delta_i].delta_str(); - let expected_delta: TextDelta = serde_json::from_str(expected).unwrap(); - let target_delta: TextDelta = serde_json::from_str(&delta_json).unwrap(); + let delta_json = self.documents[*delta_i].get_operations_json(); + let expected_delta: TextOperations = serde_json::from_str(expected).unwrap(); + let target_delta: TextOperations = serde_json::from_str(&delta_json).unwrap(); if expected_delta != target_delta { log::error!("✅ expect: {}", expected,); @@ -238,8 +238,8 @@ impl TestBuilder { TestOp::AssertPrimeJson(doc_i, expected) => { let prime_json = self.primes[*doc_i].as_ref().unwrap().json_str(); - let expected_prime: TextDelta = serde_json::from_str(expected).unwrap(); - let target_prime: TextDelta = serde_json::from_str(&prime_json).unwrap(); + let expected_prime: TextOperations = serde_json::from_str(expected).unwrap(); + let target_prime: TextOperations = serde_json::from_str(&prime_json).unwrap(); if expected_prime != target_prime { log::error!("✅ expect prime: {}", expected,); @@ -249,7 +249,7 @@ impl TestBuilder { } TestOp::DocComposeDelta(doc_index, delta_i) => { let delta = self.deltas.get(*delta_i).unwrap().as_ref().unwrap(); - self.documents[*doc_index].compose_delta(delta.clone()).unwrap(); + self.documents[*doc_index].compose_operations(delta.clone()).unwrap(); } TestOp::DocComposePrime(doc_index, prime_i) => { let delta = self @@ -258,13 +258,13 @@ impl TestBuilder { .expect("Must call TransformPrime first") .as_ref() .unwrap(); - let new_delta = self.documents[*doc_index].delta().compose(delta).unwrap(); - self.documents[*doc_index].set_delta(new_delta); + let new_delta = self.documents[*doc_index].get_operations().compose(delta).unwrap(); + self.documents[*doc_index].set_operations(new_delta); } } } - pub fn run_scripts(mut self, scripts: Vec) { + pub fn run_scripts(mut self, scripts: Vec) { self.documents = vec![ClientDocument::new::(), ClientDocument::new::()]; self.primes = vec![None, None]; self.deltas = vec![None, None]; @@ -297,8 +297,8 @@ impl Rng { .collect() } - pub fn gen_delta(&mut self, s: &str) -> TextDelta { - let mut delta = TextDelta::default(); + pub fn gen_delta(&mut self, s: &str) -> TextOperations { + let mut delta = TextOperations::default(); let s = OTString::from(s); loop { let left = s.utf16_len() - delta.utf16_base_len; @@ -312,18 +312,18 @@ impl Rng { }; match self.0.gen_range(0.0..1.0) { f if f < 0.2 => { - delta.insert(&self.gen_string(i), Attributes::default()); + delta.insert(&self.gen_string(i), AttributeHashMap::default()); } f if f < 0.4 => { delta.delete(i); } _ => { - delta.retain(i, Attributes::default()); + delta.retain(i, AttributeHashMap::default()); } } } if self.0.gen_range(0.0..1.0) < 0.3 { - delta.insert(&("1".to_owned() + &self.gen_string(10)), Attributes::default()); + delta.insert(&("1".to_owned() + &self.gen_string(10)), AttributeHashMap::default()); } delta } diff --git a/frontend/rust-lib/flowy-text-block/tests/editor/op_test.rs b/frontend/rust-lib/flowy-text-block/tests/editor/op_test.rs index 3676bce207..df1320ca51 100644 --- a/frontend/rust-lib/flowy-text-block/tests/editor/op_test.rs +++ b/frontend/rust-lib/flowy-text-block/tests/editor/op_test.rs @@ -1,8 +1,8 @@ #![allow(clippy::all)] use crate::editor::{Rng, TestBuilder, TestOp::*}; use flowy_sync::client_document::{EmptyDoc, NewlineDoc}; -use lib_ot::text_delta::TextDeltaBuilder; -use lib_ot::{core::Interval, core::*, text_delta::TextDelta}; +use lib_ot::text_delta::TextOperationBuilder; +use lib_ot::{core::Interval, core::*, text_delta::TextOperations}; #[test] fn attributes_insert_text() { @@ -37,7 +37,7 @@ fn attributes_insert_text_at_middle() { #[test] fn delta_get_ops_in_interval_1() { let operations = OperationsBuilder::new().insert("123").insert("4").build(); - let delta = TextDeltaBuilder::from_operations(operations); + let delta = TextOperationBuilder::from_operations(operations); let mut iterator = OperationIterator::from_interval(&delta, Interval::new(0, 4)); assert_eq!(iterator.ops(), delta.ops); @@ -45,11 +45,11 @@ fn delta_get_ops_in_interval_1() { #[test] fn delta_get_ops_in_interval_2() { - let mut delta = TextDelta::default(); - let insert_a = Operation::insert("123"); - let insert_b = Operation::insert("4"); - let insert_c = Operation::insert("5"); - let retain_a = Operation::retain(3); + let mut delta = TextOperations::default(); + let insert_a = DeltaOperation::insert("123"); + let insert_b = DeltaOperation::insert("4"); + let insert_c = DeltaOperation::insert("5"); + let retain_a = DeltaOperation::retain(3); delta.add(insert_a.clone()); delta.add(retain_a.clone()); @@ -58,12 +58,12 @@ fn delta_get_ops_in_interval_2() { assert_eq!( OperationIterator::from_interval(&delta, Interval::new(0, 2)).ops(), - vec![Operation::insert("12")] + vec![DeltaOperation::insert("12")] ); assert_eq!( OperationIterator::from_interval(&delta, Interval::new(1, 3)).ops(), - vec![Operation::insert("23")] + vec![DeltaOperation::insert("23")] ); assert_eq!( @@ -73,7 +73,7 @@ fn delta_get_ops_in_interval_2() { assert_eq!( OperationIterator::from_interval(&delta, Interval::new(0, 4)).ops(), - vec![insert_a.clone(), Operation::retain(1)] + vec![insert_a.clone(), DeltaOperation::retain(1)] ); assert_eq!( @@ -89,21 +89,21 @@ fn delta_get_ops_in_interval_2() { #[test] fn delta_get_ops_in_interval_3() { - let mut delta = TextDelta::default(); - let insert_a = Operation::insert("123456"); + let mut delta = TextOperations::default(); + let insert_a = DeltaOperation::insert("123456"); delta.add(insert_a.clone()); assert_eq!( OperationIterator::from_interval(&delta, Interval::new(3, 5)).ops(), - vec![Operation::insert("45")] + vec![DeltaOperation::insert("45")] ); } #[test] fn delta_get_ops_in_interval_4() { - let mut delta = TextDelta::default(); - let insert_a = Operation::insert("12"); - let insert_b = Operation::insert("34"); - let insert_c = Operation::insert("56"); + let mut delta = TextOperations::default(); + let insert_a = DeltaOperation::insert("12"); + let insert_b = DeltaOperation::insert("34"); + let insert_c = DeltaOperation::insert("56"); delta.ops.push(insert_a.clone()); delta.ops.push(insert_b.clone()); @@ -124,20 +124,20 @@ fn delta_get_ops_in_interval_4() { assert_eq!( OperationIterator::from_interval(&delta, Interval::new(2, 5)).ops(), - vec![Operation::insert("34"), Operation::insert("5")] + vec![DeltaOperation::insert("34"), DeltaOperation::insert("5")] ); } #[test] fn delta_get_ops_in_interval_5() { - let mut delta = TextDelta::default(); - let insert_a = Operation::insert("123456"); - let insert_b = Operation::insert("789"); + let mut delta = TextOperations::default(); + let insert_a = DeltaOperation::insert("123456"); + let insert_b = DeltaOperation::insert("789"); delta.ops.push(insert_a.clone()); delta.ops.push(insert_b.clone()); assert_eq!( OperationIterator::from_interval(&delta, Interval::new(4, 8)).ops(), - vec![Operation::insert("56"), Operation::insert("78")] + vec![DeltaOperation::insert("56"), DeltaOperation::insert("78")] ); // assert_eq!( @@ -148,40 +148,40 @@ fn delta_get_ops_in_interval_5() { #[test] fn delta_get_ops_in_interval_6() { - let mut delta = TextDelta::default(); - let insert_a = Operation::insert("12345678"); + let mut delta = TextOperations::default(); + let insert_a = DeltaOperation::insert("12345678"); delta.add(insert_a.clone()); assert_eq!( OperationIterator::from_interval(&delta, Interval::new(4, 6)).ops(), - vec![Operation::insert("56")] + vec![DeltaOperation::insert("56")] ); } #[test] fn delta_get_ops_in_interval_7() { - let mut delta = TextDelta::default(); - let insert_a = Operation::insert("12345"); - let retain_a = Operation::retain(3); + let mut delta = TextOperations::default(); + let insert_a = DeltaOperation::insert("12345"); + let retain_a = DeltaOperation::retain(3); delta.add(insert_a.clone()); delta.add(retain_a.clone()); let mut iter_1 = OperationIterator::from_offset(&delta, 2); - assert_eq!(iter_1.next_op().unwrap(), Operation::insert("345")); - assert_eq!(iter_1.next_op().unwrap(), Operation::retain(3)); + assert_eq!(iter_1.next_op().unwrap(), DeltaOperation::insert("345")); + assert_eq!(iter_1.next_op().unwrap(), DeltaOperation::retain(3)); let mut iter_2 = OperationIterator::new(&delta); - assert_eq!(iter_2.next_op_with_len(2).unwrap(), Operation::insert("12")); - assert_eq!(iter_2.next_op().unwrap(), Operation::insert("345")); + assert_eq!(iter_2.next_op_with_len(2).unwrap(), DeltaOperation::insert("12")); + assert_eq!(iter_2.next_op().unwrap(), DeltaOperation::insert("345")); - assert_eq!(iter_2.next_op().unwrap(), Operation::retain(3)); + assert_eq!(iter_2.next_op().unwrap(), DeltaOperation::retain(3)); } #[test] fn delta_op_seek() { - let mut delta = TextDelta::default(); - let insert_a = Operation::insert("12345"); - let retain_a = Operation::retain(3); + let mut delta = TextOperations::default(); + let insert_a = DeltaOperation::insert("12345"); + let retain_a = DeltaOperation::retain(3); delta.add(insert_a.clone()); delta.add(retain_a.clone()); let mut iter = OperationIterator::new(&delta); @@ -191,92 +191,92 @@ fn delta_op_seek() { #[test] fn delta_utf16_code_unit_seek() { - let mut delta = TextDelta::default(); - delta.add(Operation::insert("12345")); + let mut delta = TextOperations::default(); + delta.add(DeltaOperation::insert("12345")); let mut iter = OperationIterator::new(&delta); iter.seek::(3); - assert_eq!(iter.next_op_with_len(2).unwrap(), Operation::insert("45")); + assert_eq!(iter.next_op_with_len(2).unwrap(), DeltaOperation::insert("45")); } #[test] fn delta_utf16_code_unit_seek_with_attributes() { - let mut delta = TextDelta::default(); + let mut delta = TextOperations::default(); let attributes = AttributeBuilder::new() .insert("bold", true) .insert("italic", true) .build(); - delta.add(Operation::insert_with_attributes("1234", attributes.clone())); - delta.add(Operation::insert("\n")); + delta.add(DeltaOperation::insert_with_attributes("1234", attributes.clone())); + delta.add(DeltaOperation::insert("\n")); let mut iter = OperationIterator::new(&delta); iter.seek::(0); assert_eq!( iter.next_op_with_len(4).unwrap(), - Operation::insert_with_attributes("1234", attributes), + DeltaOperation::insert_with_attributes("1234", attributes), ); } #[test] fn delta_next_op_len() { - let mut delta = TextDelta::default(); - delta.add(Operation::insert("12345")); + let mut delta = TextOperations::default(); + delta.add(DeltaOperation::insert("12345")); let mut iter = OperationIterator::new(&delta); - assert_eq!(iter.next_op_with_len(2).unwrap(), Operation::insert("12")); - assert_eq!(iter.next_op_with_len(2).unwrap(), Operation::insert("34")); - assert_eq!(iter.next_op_with_len(2).unwrap(), Operation::insert("5")); + assert_eq!(iter.next_op_with_len(2).unwrap(), DeltaOperation::insert("12")); + assert_eq!(iter.next_op_with_len(2).unwrap(), DeltaOperation::insert("34")); + assert_eq!(iter.next_op_with_len(2).unwrap(), DeltaOperation::insert("5")); assert_eq!(iter.next_op_with_len(1), None); } #[test] fn delta_next_op_len_with_chinese() { - let mut delta = TextDelta::default(); - delta.add(Operation::insert("你好")); + let mut delta = TextOperations::default(); + delta.add(DeltaOperation::insert("你好")); let mut iter = OperationIterator::new(&delta); assert_eq!(iter.next_op_len().unwrap(), 2); - assert_eq!(iter.next_op_with_len(2).unwrap(), Operation::insert("你好")); + assert_eq!(iter.next_op_with_len(2).unwrap(), DeltaOperation::insert("你好")); } #[test] fn delta_next_op_len_with_english() { - let mut delta = TextDelta::default(); - delta.add(Operation::insert("ab")); + let mut delta = TextOperations::default(); + delta.add(DeltaOperation::insert("ab")); let mut iter = OperationIterator::new(&delta); assert_eq!(iter.next_op_len().unwrap(), 2); - assert_eq!(iter.next_op_with_len(2).unwrap(), Operation::insert("ab")); + assert_eq!(iter.next_op_with_len(2).unwrap(), DeltaOperation::insert("ab")); } #[test] fn delta_next_op_len_after_seek() { - let mut delta = TextDelta::default(); - delta.add(Operation::insert("12345")); + let mut delta = TextOperations::default(); + delta.add(DeltaOperation::insert("12345")); let mut iter = OperationIterator::new(&delta); assert_eq!(iter.next_op_len().unwrap(), 5); iter.seek::(3); assert_eq!(iter.next_op_len().unwrap(), 2); - assert_eq!(iter.next_op_with_len(1).unwrap(), Operation::insert("4")); + assert_eq!(iter.next_op_with_len(1).unwrap(), DeltaOperation::insert("4")); assert_eq!(iter.next_op_len().unwrap(), 1); - assert_eq!(iter.next_op().unwrap(), Operation::insert("5")); + assert_eq!(iter.next_op().unwrap(), DeltaOperation::insert("5")); } #[test] fn delta_next_op_len_none() { - let mut delta = TextDelta::default(); - delta.add(Operation::insert("12345")); + let mut delta = TextOperations::default(); + delta.add(DeltaOperation::insert("12345")); let mut iter = OperationIterator::new(&delta); assert_eq!(iter.next_op_len().unwrap(), 5); - assert_eq!(iter.next_op_with_len(5).unwrap(), Operation::insert("12345")); + assert_eq!(iter.next_op_with_len(5).unwrap(), DeltaOperation::insert("12345")); assert_eq!(iter.next_op_len(), None); } #[test] fn delta_next_op_with_len_zero() { - let mut delta = TextDelta::default(); - delta.add(Operation::insert("12345")); + let mut delta = TextOperations::default(); + delta.add(DeltaOperation::insert("12345")); let mut iter = OperationIterator::new(&delta); assert_eq!(iter.next_op_with_len(0), None,); assert_eq!(iter.next_op_len().unwrap(), 5); @@ -284,29 +284,29 @@ fn delta_next_op_with_len_zero() { #[test] fn delta_next_op_with_len_cross_op_return_last() { - let mut delta = TextDelta::default(); - delta.add(Operation::insert("12345")); - delta.add(Operation::retain(1)); - delta.add(Operation::insert("678")); + let mut delta = TextOperations::default(); + delta.add(DeltaOperation::insert("12345")); + delta.add(DeltaOperation::retain(1)); + delta.add(DeltaOperation::insert("678")); let mut iter = OperationIterator::new(&delta); iter.seek::(4); assert_eq!(iter.next_op_len().unwrap(), 1); - assert_eq!(iter.next_op_with_len(2).unwrap(), Operation::retain(1)); + assert_eq!(iter.next_op_with_len(2).unwrap(), DeltaOperation::retain(1)); } #[test] fn lengths() { - let mut delta = TextDelta::default(); + let mut delta = TextOperations::default(); assert_eq!(delta.utf16_base_len, 0); assert_eq!(delta.utf16_target_len, 0); - delta.retain(5, Attributes::default()); + delta.retain(5, AttributeHashMap::default()); assert_eq!(delta.utf16_base_len, 5); assert_eq!(delta.utf16_target_len, 5); - delta.insert("abc", Attributes::default()); + delta.insert("abc", AttributeHashMap::default()); assert_eq!(delta.utf16_base_len, 5); assert_eq!(delta.utf16_target_len, 8); - delta.retain(2, Attributes::default()); + delta.retain(2, AttributeHashMap::default()); assert_eq!(delta.utf16_base_len, 7); assert_eq!(delta.utf16_target_len, 10); delta.delete(2); @@ -315,11 +315,11 @@ fn lengths() { } #[test] fn sequence() { - let mut delta = TextDelta::default(); - delta.retain(5, Attributes::default()); - delta.retain(0, Attributes::default()); - delta.insert("appflowy", Attributes::default()); - delta.insert("", Attributes::default()); + let mut delta = TextOperations::default(); + delta.retain(5, AttributeHashMap::default()); + delta.retain(0, AttributeHashMap::default()); + delta.insert("appflowy", AttributeHashMap::default()); + delta.insert("", AttributeHashMap::default()); delta.delete(3); delta.delete(0); assert_eq!(delta.ops.len(), 3); @@ -348,16 +348,16 @@ fn apply_test() { #[test] fn base_len_test() { - let mut delta_a = TextDelta::default(); - delta_a.insert("a", Attributes::default()); - delta_a.insert("b", Attributes::default()); - delta_a.insert("c", Attributes::default()); + let mut delta_a = TextOperations::default(); + delta_a.insert("a", AttributeHashMap::default()); + delta_a.insert("b", AttributeHashMap::default()); + delta_a.insert("c", AttributeHashMap::default()); let s = "hello world,".to_owned(); delta_a.delete(s.len()); let after_a = delta_a.apply(&s).unwrap(); - delta_a.insert("d", Attributes::default()); + delta_a.insert("d", AttributeHashMap::default()); assert_eq!("abc", &after_a); } @@ -387,62 +387,62 @@ fn invert_test() { #[test] fn empty_ops() { - let mut delta = TextDelta::default(); - delta.retain(0, Attributes::default()); - delta.insert("", Attributes::default()); + let mut delta = TextOperations::default(); + delta.retain(0, AttributeHashMap::default()); + delta.insert("", AttributeHashMap::default()); delta.delete(0); assert_eq!(delta.ops.len(), 0); } #[test] fn eq() { - let mut delta_a = TextDelta::default(); + let mut delta_a = TextOperations::default(); delta_a.delete(1); - delta_a.insert("lo", Attributes::default()); - delta_a.retain(2, Attributes::default()); - delta_a.retain(3, Attributes::default()); - let mut delta_b = TextDelta::default(); + delta_a.insert("lo", AttributeHashMap::default()); + delta_a.retain(2, AttributeHashMap::default()); + delta_a.retain(3, AttributeHashMap::default()); + let mut delta_b = TextOperations::default(); delta_b.delete(1); - delta_b.insert("l", Attributes::default()); - delta_b.insert("o", Attributes::default()); - delta_b.retain(5, Attributes::default()); + delta_b.insert("l", AttributeHashMap::default()); + delta_b.insert("o", AttributeHashMap::default()); + delta_b.retain(5, AttributeHashMap::default()); assert_eq!(delta_a, delta_b); delta_a.delete(1); - delta_b.retain(1, Attributes::default()); + delta_b.retain(1, AttributeHashMap::default()); assert_ne!(delta_a, delta_b); } #[test] fn ops_merging() { - let mut delta = TextDelta::default(); + let mut delta = TextOperations::default(); assert_eq!(delta.ops.len(), 0); - delta.retain(2, Attributes::default()); + delta.retain(2, AttributeHashMap::default()); assert_eq!(delta.ops.len(), 1); - assert_eq!(delta.ops.last(), Some(&Operation::retain(2))); - delta.retain(3, Attributes::default()); + assert_eq!(delta.ops.last(), Some(&DeltaOperation::retain(2))); + delta.retain(3, AttributeHashMap::default()); assert_eq!(delta.ops.len(), 1); - assert_eq!(delta.ops.last(), Some(&Operation::retain(5))); - delta.insert("abc", Attributes::default()); + assert_eq!(delta.ops.last(), Some(&DeltaOperation::retain(5))); + delta.insert("abc", AttributeHashMap::default()); assert_eq!(delta.ops.len(), 2); - assert_eq!(delta.ops.last(), Some(&Operation::insert("abc"))); - delta.insert("xyz", Attributes::default()); + assert_eq!(delta.ops.last(), Some(&DeltaOperation::insert("abc"))); + delta.insert("xyz", AttributeHashMap::default()); assert_eq!(delta.ops.len(), 2); - assert_eq!(delta.ops.last(), Some(&Operation::insert("abcxyz"))); + assert_eq!(delta.ops.last(), Some(&DeltaOperation::insert("abcxyz"))); delta.delete(1); assert_eq!(delta.ops.len(), 3); - assert_eq!(delta.ops.last(), Some(&Operation::delete(1))); + assert_eq!(delta.ops.last(), Some(&DeltaOperation::delete(1))); delta.delete(1); assert_eq!(delta.ops.len(), 3); - assert_eq!(delta.ops.last(), Some(&Operation::delete(2))); + assert_eq!(delta.ops.last(), Some(&DeltaOperation::delete(2))); } #[test] fn is_noop() { - let mut delta = TextDelta::default(); + let mut delta = TextOperations::default(); assert!(delta.is_noop()); - delta.retain(5, Attributes::default()); + delta.retain(5, AttributeHashMap::default()); assert!(delta.is_noop()); - delta.retain(3, Attributes::default()); + delta.retain(3, AttributeHashMap::default()); assert!(delta.is_noop()); - delta.insert("lorem", Attributes::default()); + delta.insert("lorem", AttributeHashMap::default()); assert!(!delta.is_noop()); } #[test] @@ -484,15 +484,15 @@ fn transform_random_delta() { #[test] fn transform_with_two_delta() { - let mut a = TextDelta::default(); + let mut a = TextOperations::default(); let mut a_s = String::new(); a.insert("123", AttributeBuilder::new().insert("bold", true).build()); a_s = a.apply(&a_s).unwrap(); assert_eq!(&a_s, "123"); - let mut b = TextDelta::default(); + let mut b = TextOperations::default(); let mut b_s = String::new(); - b.insert("456", Attributes::default()); + b.insert("456", AttributeHashMap::default()); b_s = b.apply(&b_s).unwrap(); assert_eq!(&b_s, "456"); @@ -580,12 +580,12 @@ fn transform_two_conflict_non_seq_delta() { #[test] fn delta_invert_no_attribute_delta() { - let mut delta = TextDelta::default(); - delta.add(Operation::insert("123")); + let mut delta = TextOperations::default(); + delta.add(DeltaOperation::insert("123")); - let mut change = TextDelta::default(); - change.add(Operation::retain(3)); - change.add(Operation::insert("456")); + let mut change = TextOperations::default(); + change.add(DeltaOperation::retain(3)); + change.add(DeltaOperation::insert("456")); let undo = change.invert(&delta); let new_delta = delta.compose(&change).unwrap(); diff --git a/frontend/rust-lib/flowy-text-block/tests/editor/serde_test.rs b/frontend/rust-lib/flowy-text-block/tests/editor/serde_test.rs index 3609f90fff..1553530668 100644 --- a/frontend/rust-lib/flowy-text-block/tests/editor/serde_test.rs +++ b/frontend/rust-lib/flowy-text-block/tests/editor/serde_test.rs @@ -2,7 +2,7 @@ use flowy_sync::client_document::{ClientDocument, EmptyDoc}; use lib_ot::text_delta::TextOperation; use lib_ot::{ core::*, - text_delta::{BuildInTextAttribute, TextDelta}, + text_delta::{BuildInTextAttribute, TextOperations}, }; #[test] @@ -11,7 +11,7 @@ fn operation_insert_serialize_test() { .insert("bold", true) .insert("italic", true) .build(); - let operation = Operation::insert_with_attributes("123", attributes); + let operation = DeltaOperation::insert_with_attributes("123", attributes); let json = serde_json::to_string(&operation).unwrap(); eprintln!("{}", json); @@ -21,7 +21,7 @@ fn operation_insert_serialize_test() { #[test] fn operation_retain_serialize_test() { - let operation = Operation::Retain(12.into()); + let operation = DeltaOperation::Retain(12.into()); let json = serde_json::to_string(&operation).unwrap(); eprintln!("{}", json); let insert_op: TextOperation = serde_json::from_str(&json).unwrap(); @@ -42,7 +42,7 @@ fn attributes_serialize_test() { .insert_entry(BuildInTextAttribute::Bold(true)) .insert_entry(BuildInTextAttribute::Italic(true)) .build(); - let retain = Operation::insert_with_attributes("123", attributes); + let retain = DeltaOperation::insert_with_attributes("123", attributes); let json = serde_json::to_string(&retain).unwrap(); eprintln!("{}", json); @@ -50,22 +50,22 @@ fn attributes_serialize_test() { #[test] fn delta_serialize_multi_attribute_test() { - let mut delta = Operations::default(); + let mut delta = DeltaOperations::default(); let attributes = AttributeBuilder::new() .insert_entry(BuildInTextAttribute::Bold(true)) .insert_entry(BuildInTextAttribute::Italic(true)) .build(); - let retain = Operation::insert_with_attributes("123", attributes); + let retain = DeltaOperation::insert_with_attributes("123", attributes); delta.add(retain); - delta.add(Operation::Retain(5.into())); - delta.add(Operation::Delete(3)); + delta.add(DeltaOperation::Retain(5.into())); + delta.add(DeltaOperation::Delete(3)); let json = serde_json::to_string(&delta).unwrap(); eprintln!("{}", json); - let delta_from_json = Operations::from_json(&json).unwrap(); + let delta_from_json = DeltaOperations::from_json(&json).unwrap(); assert_eq!(delta_from_json, delta); } @@ -77,7 +77,7 @@ fn delta_deserialize_test() { {"retain":2,"attributes":{"italic":true,"bold":true}}, {"retain":2,"attributes":{"italic":true,"bold":true}} ]"#; - let delta = TextDelta::from_json(json).unwrap(); + let delta = TextOperations::from_json(json).unwrap(); eprintln!("{}", delta); } @@ -86,7 +86,7 @@ fn delta_deserialize_null_test() { let json = r#"[ {"retain":7,"attributes":{"bold":null}} ]"#; - let delta1 = TextDelta::from_json(json).unwrap(); + let delta1 = TextOperations::from_json(json).unwrap(); let mut attribute = BuildInTextAttribute::Bold(true); attribute.remove_value(); @@ -104,10 +104,10 @@ fn document_insert_serde_test() { let mut document = ClientDocument::new::(); document.insert(0, "\n").unwrap(); document.insert(0, "123").unwrap(); - let json = document.delta_str(); + let json = document.get_operations_json(); assert_eq!(r#"[{"insert":"123\n"}]"#, json); assert_eq!( r#"[{"insert":"123\n"}]"#, - ClientDocument::from_json(&json).unwrap().delta_str() + ClientDocument::from_json(&json).unwrap().get_operations_json() ); } diff --git a/shared-lib/flowy-sync/src/client_document/data.rs b/shared-lib/flowy-sync/src/client_document/data.rs deleted file mode 100644 index 449b8bd136..0000000000 --- a/shared-lib/flowy-sync/src/client_document/data.rs +++ /dev/null @@ -1,12 +0,0 @@ -use serde::{Deserialize, Serialize}; - -#[derive(Serialize, Deserialize, Debug)] -pub struct ImageData { - image: String, -} - -impl ToString for ImageData { - fn to_string(&self) -> String { - self.image.clone() - } -} diff --git a/shared-lib/flowy-sync/src/client_document/default/mod.rs b/shared-lib/flowy-sync/src/client_document/default/mod.rs index 0ebfd29b3e..a6303081b8 100644 --- a/shared-lib/flowy-sync/src/client_document/default/mod.rs +++ b/shared-lib/flowy-sync/src/client_document/default/mod.rs @@ -1,19 +1,19 @@ -use lib_ot::{core::OperationBuilder, text_delta::TextDelta}; +use lib_ot::{core::OperationBuilder, text_delta::TextOperations}; #[inline] -pub fn initial_quill_delta() -> TextDelta { +pub fn initial_document_operations() -> TextOperations { OperationBuilder::new().insert("\n").build() } #[inline] -pub fn initial_quill_delta_string() -> String { - initial_quill_delta().json_str() +pub fn initial_document_str() -> String { + initial_document_operations().json_str() } #[inline] -pub fn initial_read_me() -> TextDelta { +pub fn initial_read_me() -> TextOperations { let json = include_str!("READ_ME.json"); - TextDelta::from_json(json).unwrap() + TextOperations::from_json(json).unwrap() } #[cfg(test)] diff --git a/shared-lib/flowy-sync/src/client_document/document_pad.rs b/shared-lib/flowy-sync/src/client_document/document_pad.rs index e15c9beb61..cdf5fdfad9 100644 --- a/shared-lib/flowy-sync/src/client_document/document_pad.rs +++ b/shared-lib/flowy-sync/src/client_document/document_pad.rs @@ -1,35 +1,35 @@ +use crate::client_document::default::initial_document_str; use crate::{ client_document::{ - default::initial_quill_delta, history::{History, UndoResult}, view::{ViewExtensions, RECORD_THRESHOLD}, }, errors::CollaborateError, }; use bytes::Bytes; -use lib_ot::{core::*, text_delta::TextDelta}; +use lib_ot::{core::*, text_delta::TextOperations}; use tokio::sync::mpsc; -pub trait InitialDocumentText { - fn initial_delta() -> TextDelta; +pub trait InitialDocumentContent { + fn json_str() -> String; } pub struct EmptyDoc(); -impl InitialDocumentText for EmptyDoc { - fn initial_delta() -> TextDelta { - TextDelta::new() +impl InitialDocumentContent for EmptyDoc { + fn json_str() -> String { + TextOperations::default().json_str() } } pub struct NewlineDoc(); -impl InitialDocumentText for NewlineDoc { - fn initial_delta() -> TextDelta { - initial_quill_delta() +impl InitialDocumentContent for NewlineDoc { + fn json_str() -> String { + initial_document_str() } } pub struct ClientDocument { - delta: TextDelta, + operations: TextOperations, history: History, view: ViewExtensions, last_edit_time: usize, @@ -37,13 +37,14 @@ pub struct ClientDocument { } impl ClientDocument { - pub fn new() -> Self { - Self::from_delta(C::initial_delta()) + pub fn new() -> Self { + let content = C::json_str(); + Self::from_json(&content).unwrap() } - pub fn from_delta(delta: TextDelta) -> Self { + pub fn from_operations(operations: TextOperations) -> Self { ClientDocument { - delta, + operations, history: History::new(), view: ViewExtensions::new(), last_edit_time: 0, @@ -52,24 +53,24 @@ impl ClientDocument { } pub fn from_json(json: &str) -> Result { - let delta = TextDelta::from_json(json)?; - Ok(Self::from_delta(delta)) + let operations = TextOperations::from_json(json)?; + Ok(Self::from_operations(operations)) } - pub fn delta_str(&self) -> String { - self.delta.json_str() + pub fn get_operations_json(&self) -> String { + self.operations.json_str() } pub fn to_bytes(&self) -> Bytes { - self.delta.json_bytes() + self.operations.json_bytes() } - pub fn to_plain_string(&self) -> String { - self.delta.apply("").unwrap() + pub fn to_content(&self) -> String { + self.operations.content().unwrap() } - pub fn delta(&self) -> &TextDelta { - &self.delta + pub fn get_operations(&self) -> &TextOperations { + &self.operations } pub fn md5(&self) -> String { @@ -81,9 +82,9 @@ impl ClientDocument { self.notify = Some(notify); } - pub fn set_delta(&mut self, data: TextDelta) { - tracing::trace!("document: {}", data.json_str()); - self.delta = data; + pub fn set_operations(&mut self, operations: TextOperations) { + tracing::trace!("document: {}", operations.json_str()); + self.operations = operations; match &self.notify { None => {} @@ -93,74 +94,78 @@ impl ClientDocument { } } - pub fn compose_delta(&mut self, delta: TextDelta) -> Result<(), CollaborateError> { - tracing::trace!("{} compose {}", &self.delta.json_str(), delta.json_str()); - let composed_delta = self.delta.compose(&delta)?; - let mut undo_delta = delta.invert(&self.delta); + pub fn compose_operations(&mut self, operations: TextOperations) -> Result<(), CollaborateError> { + tracing::trace!("{} compose {}", &self.operations.json_str(), operations.json_str()); + let composed_operations = self.operations.compose(&operations)?; + let mut undo_operations = operations.invert(&self.operations); let now = chrono::Utc::now().timestamp_millis() as usize; if now - self.last_edit_time < RECORD_THRESHOLD { - if let Some(last_delta) = self.history.undo() { + if let Some(last_operation) = self.history.undo() { tracing::trace!("compose previous change"); - tracing::trace!("current = {}", undo_delta); - tracing::trace!("previous = {}", last_delta); - undo_delta = undo_delta.compose(&last_delta)?; + tracing::trace!("current = {}", undo_operations); + tracing::trace!("previous = {}", last_operation); + undo_operations = undo_operations.compose(&last_operation)?; } } else { self.last_edit_time = now; } - if !undo_delta.is_empty() { - tracing::trace!("add history delta: {}", undo_delta); - self.history.record(undo_delta); + if !undo_operations.is_empty() { + tracing::trace!("add history operations: {}", undo_operations); + self.history.record(undo_operations); } - self.set_delta(composed_delta); + self.set_operations(composed_operations); Ok(()) } - pub fn insert(&mut self, index: usize, data: T) -> Result { + pub fn insert(&mut self, index: usize, data: T) -> Result { let text = data.to_string(); let interval = Interval::new(index, index); - let _ = validate_interval(&self.delta, &interval)?; - let delta = self.view.insert(&self.delta, &text, interval)?; - self.compose_delta(delta.clone())?; - Ok(delta) + let _ = validate_interval(&self.operations, &interval)?; + let operations = self.view.insert(&self.operations, &text, interval)?; + self.compose_operations(operations.clone())?; + Ok(operations) } - pub fn delete(&mut self, interval: Interval) -> Result { - let _ = validate_interval(&self.delta, &interval)?; + pub fn delete(&mut self, interval: Interval) -> Result { + let _ = validate_interval(&self.operations, &interval)?; debug_assert!(!interval.is_empty()); - let delete = self.view.delete(&self.delta, interval)?; - if !delete.is_empty() { - let _ = self.compose_delta(delete.clone())?; + let operations = self.view.delete(&self.operations, interval)?; + if !operations.is_empty() { + let _ = self.compose_operations(operations.clone())?; } - Ok(delete) + Ok(operations) } - pub fn format(&mut self, interval: Interval, attribute: AttributeEntry) -> Result { - let _ = validate_interval(&self.delta, &interval)?; + pub fn format( + &mut self, + interval: Interval, + attribute: AttributeEntry, + ) -> Result { + let _ = validate_interval(&self.operations, &interval)?; tracing::trace!("format {} with {:?}", interval, attribute); - let format_delta = self.view.format(&self.delta, attribute, interval).unwrap(); - self.compose_delta(format_delta.clone())?; - Ok(format_delta) + let operations = self.view.format(&self.operations, attribute, interval).unwrap(); + self.compose_operations(operations.clone())?; + Ok(operations) } - pub fn replace(&mut self, interval: Interval, data: T) -> Result { - let _ = validate_interval(&self.delta, &interval)?; - let mut delta = TextDelta::default(); + pub fn replace(&mut self, interval: Interval, data: T) -> Result { + let _ = validate_interval(&self.operations, &interval)?; + let mut operations = TextOperations::default(); let text = data.to_string(); if !text.is_empty() { - delta = self.view.insert(&self.delta, &text, interval)?; - self.compose_delta(delta.clone())?; + operations = self.view.insert(&self.operations, &text, interval)?; + self.compose_operations(operations.clone())?; } if !interval.is_empty() { let delete = self.delete(interval)?; - delta = delta.compose(&delete)?; + operations = operations.compose(&delete)?; } - Ok(delta) + Ok(operations) } pub fn can_undo(&self) -> bool { @@ -174,11 +179,13 @@ impl ClientDocument { pub fn undo(&mut self) -> Result { match self.history.undo() { None => Err(CollaborateError::undo().context("Undo stack is empty")), - Some(undo_delta) => { - let (new_delta, inverted_delta) = self.invert(&undo_delta)?; - self.set_delta(new_delta); - self.history.add_redo(inverted_delta); - Ok(UndoResult { delta: undo_delta }) + Some(undo_operations) => { + let (new_operations, inverted_operations) = self.invert(&undo_operations)?; + self.set_operations(new_operations); + self.history.add_redo(inverted_operations); + Ok(UndoResult { + operations: undo_operations, + }) } } } @@ -186,35 +193,41 @@ impl ClientDocument { pub fn redo(&mut self) -> Result { match self.history.redo() { None => Err(CollaborateError::redo()), - Some(redo_delta) => { - let (new_delta, inverted_delta) = self.invert(&redo_delta)?; - self.set_delta(new_delta); - self.history.add_undo(inverted_delta); - Ok(UndoResult { delta: redo_delta }) + Some(redo_operations) => { + let (new_operations, inverted_operations) = self.invert(&redo_operations)?; + self.set_operations(new_operations); + self.history.add_undo(inverted_operations); + Ok(UndoResult { + operations: redo_operations, + }) } } } pub fn is_empty(&self) -> bool { // The document is empty if its text is equal to the initial text. - self.delta == NewlineDoc::initial_delta() + self.operations.json_str() == NewlineDoc::json_str() } } impl ClientDocument { - fn invert(&self, delta: &TextDelta) -> Result<(TextDelta, TextDelta), CollaborateError> { + fn invert(&self, operations: &TextOperations) -> Result<(TextOperations, TextOperations), CollaborateError> { // c = a.compose(b) // d = b.invert(a) // a = c.compose(d) - let new_delta = self.delta.compose(delta)?; - let inverted_delta = delta.invert(&self.delta); - Ok((new_delta, inverted_delta)) + let new_operations = self.operations.compose(operations)?; + let inverted_operations = operations.invert(&self.operations); + Ok((new_operations, inverted_operations)) } } -fn validate_interval(delta: &TextDelta, interval: &Interval) -> Result<(), CollaborateError> { - if delta.utf16_target_len < interval.end { - log::error!("{:?} out of bounds. should 0..{}", interval, delta.utf16_target_len); +fn validate_interval(operations: &TextOperations, interval: &Interval) -> Result<(), CollaborateError> { + if operations.utf16_target_len < interval.end { + log::error!( + "{:?} out of bounds. should 0..{}", + interval, + operations.utf16_target_len + ); return Err(CollaborateError::out_of_bound()); } Ok(()) diff --git a/shared-lib/flowy-sync/src/client_document/extensions/delete/default_delete.rs b/shared-lib/flowy-sync/src/client_document/extensions/delete/default_delete.rs index c02a7f1fe9..5fcf100299 100644 --- a/shared-lib/flowy-sync/src/client_document/extensions/delete/default_delete.rs +++ b/shared-lib/flowy-sync/src/client_document/extensions/delete/default_delete.rs @@ -1,7 +1,7 @@ use crate::client_document::DeleteExt; use lib_ot::{ core::{Interval, OperationBuilder}, - text_delta::TextDelta, + text_delta::TextOperations, }; pub struct DefaultDelete {} @@ -10,7 +10,7 @@ impl DeleteExt for DefaultDelete { "DefaultDelete" } - fn apply(&self, _delta: &TextDelta, interval: Interval) -> Option { + fn apply(&self, _delta: &TextOperations, interval: Interval) -> Option { Some( OperationBuilder::new() .retain(interval.start) diff --git a/shared-lib/flowy-sync/src/client_document/extensions/delete/preserve_line_format_merge.rs b/shared-lib/flowy-sync/src/client_document/extensions/delete/preserve_line_format_merge.rs index 4148ee4531..0f30102616 100644 --- a/shared-lib/flowy-sync/src/client_document/extensions/delete/preserve_line_format_merge.rs +++ b/shared-lib/flowy-sync/src/client_document/extensions/delete/preserve_line_format_merge.rs @@ -1,7 +1,7 @@ use crate::{client_document::DeleteExt, util::is_newline}; use lib_ot::{ core::{Interval, OperationAttributes, OperationBuilder, OperationIterator, Utf16CodeUnitMetric, NEW_LINE}, - text_delta::{empty_attributes, TextDelta}, + text_delta::{empty_attributes, TextOperations}, }; pub struct PreserveLineFormatOnMerge {} @@ -10,7 +10,7 @@ impl DeleteExt for PreserveLineFormatOnMerge { "PreserveLineFormatOnMerge" } - fn apply(&self, delta: &TextDelta, interval: Interval) -> Option { + fn apply(&self, delta: &TextOperations, interval: Interval) -> Option { if interval.is_empty() { return None; } @@ -45,7 +45,7 @@ impl DeleteExt for PreserveLineFormatOnMerge { attributes.remove_all_value(); if newline_op.has_attribute() { - attributes.extend_other(newline_op.get_attributes()); + attributes.extend(newline_op.get_attributes()); } new_delta.retain(line_break, empty_attributes()); diff --git a/shared-lib/flowy-sync/src/client_document/extensions/format/resolve_block_format.rs b/shared-lib/flowy-sync/src/client_document/extensions/format/resolve_block_format.rs index 26d0562687..c2c2006e3e 100644 --- a/shared-lib/flowy-sync/src/client_document/extensions/format/resolve_block_format.rs +++ b/shared-lib/flowy-sync/src/client_document/extensions/format/resolve_block_format.rs @@ -2,7 +2,7 @@ use lib_ot::core::AttributeEntry; use lib_ot::text_delta::is_block; use lib_ot::{ core::{Interval, OperationBuilder, OperationIterator}, - text_delta::{empty_attributes, AttributeScope, TextDelta}, + text_delta::{empty_attributes, AttributeScope, TextOperations}, }; use crate::{ @@ -16,7 +16,7 @@ impl FormatExt for ResolveBlockFormat { "ResolveBlockFormat" } - fn apply(&self, delta: &TextDelta, interval: Interval, attribute: &AttributeEntry) -> Option { + fn apply(&self, delta: &TextOperations, interval: Interval, attribute: &AttributeEntry) -> Option { if !is_block(&attribute.key) { return None; } diff --git a/shared-lib/flowy-sync/src/client_document/extensions/format/resolve_inline_format.rs b/shared-lib/flowy-sync/src/client_document/extensions/format/resolve_inline_format.rs index c4e7086715..7ee82dcadc 100644 --- a/shared-lib/flowy-sync/src/client_document/extensions/format/resolve_inline_format.rs +++ b/shared-lib/flowy-sync/src/client_document/extensions/format/resolve_inline_format.rs @@ -2,7 +2,7 @@ use lib_ot::core::AttributeEntry; use lib_ot::text_delta::is_inline; use lib_ot::{ core::{Interval, OperationBuilder, OperationIterator}, - text_delta::{AttributeScope, TextDelta}, + text_delta::{AttributeScope, TextOperations}, }; use crate::{ @@ -16,7 +16,7 @@ impl FormatExt for ResolveInlineFormat { "ResolveInlineFormat" } - fn apply(&self, delta: &TextDelta, interval: Interval, attribute: &AttributeEntry) -> Option { + fn apply(&self, delta: &TextOperations, interval: Interval, attribute: &AttributeEntry) -> Option { if !is_inline(&attribute.key) { return None; } diff --git a/shared-lib/flowy-sync/src/client_document/extensions/helper.rs b/shared-lib/flowy-sync/src/client_document/extensions/helper.rs index 547eab71e1..6e267f0cd0 100644 --- a/shared-lib/flowy-sync/src/client_document/extensions/helper.rs +++ b/shared-lib/flowy-sync/src/client_document/extensions/helper.rs @@ -1,9 +1,9 @@ use crate::util::find_newline; use lib_ot::core::AttributeEntry; -use lib_ot::text_delta::{empty_attributes, AttributeScope, TextDelta, TextOperation}; +use lib_ot::text_delta::{empty_attributes, AttributeScope, TextOperation, TextOperations}; -pub(crate) fn line_break(op: &TextOperation, attribute: &AttributeEntry, scope: AttributeScope) -> TextDelta { - let mut new_delta = TextDelta::new(); +pub(crate) fn line_break(op: &TextOperation, attribute: &AttributeEntry, scope: AttributeScope) -> TextOperations { + let mut new_delta = TextOperations::new(); let mut start = 0; let end = op.len(); let mut s = op.get_data(); diff --git a/shared-lib/flowy-sync/src/client_document/extensions/insert/auto_exit_block.rs b/shared-lib/flowy-sync/src/client_document/extensions/insert/auto_exit_block.rs index 1a7ce78690..52ed6165cd 100644 --- a/shared-lib/flowy-sync/src/client_document/extensions/insert/auto_exit_block.rs +++ b/shared-lib/flowy-sync/src/client_document/extensions/insert/auto_exit_block.rs @@ -1,6 +1,6 @@ use crate::{client_document::InsertExt, util::is_newline}; use lib_ot::core::{is_empty_line_at_index, OperationBuilder, OperationIterator}; -use lib_ot::text_delta::{attributes_except_header, BuildInTextAttributeKey, TextDelta}; +use lib_ot::text_delta::{attributes_except_header, BuildInTextAttributeKey, TextOperations}; pub struct AutoExitBlock {} @@ -9,7 +9,7 @@ impl InsertExt for AutoExitBlock { "AutoExitBlock" } - fn apply(&self, delta: &TextDelta, replace_len: usize, text: &str, index: usize) -> Option { + fn apply(&self, delta: &TextOperations, replace_len: usize, text: &str, index: usize) -> Option { // Auto exit block will be triggered by enter two new lines if !is_newline(text) { return None; diff --git a/shared-lib/flowy-sync/src/client_document/extensions/insert/auto_format.rs b/shared-lib/flowy-sync/src/client_document/extensions/insert/auto_format.rs index b2deae600d..2fe7b70b0e 100644 --- a/shared-lib/flowy-sync/src/client_document/extensions/insert/auto_format.rs +++ b/shared-lib/flowy-sync/src/client_document/extensions/insert/auto_format.rs @@ -1,8 +1,8 @@ use crate::{client_document::InsertExt, util::is_whitespace}; -use lib_ot::core::Attributes; +use lib_ot::core::AttributeHashMap; use lib_ot::{ core::{count_utf16_code_units, OperationBuilder, OperationIterator}, - text_delta::{empty_attributes, BuildInTextAttribute, TextDelta}, + text_delta::{empty_attributes, BuildInTextAttribute, TextOperations}, }; use std::cmp::min; use url::Url; @@ -13,7 +13,7 @@ impl InsertExt for AutoFormatExt { "AutoFormatExt" } - fn apply(&self, delta: &TextDelta, replace_len: usize, text: &str, index: usize) -> Option { + fn apply(&self, delta: &TextOperations, replace_len: usize, text: &str, index: usize) -> Option { // enter whitespace to trigger auto format if !is_whitespace(text) { return None; @@ -61,7 +61,7 @@ pub enum AutoFormatter { } impl AutoFormatter { - pub fn to_attributes(&self) -> Attributes { + pub fn to_attributes(&self) -> AttributeHashMap { match self { AutoFormatter::Url(url) => BuildInTextAttribute::Link(url.as_str()).into(), } diff --git a/shared-lib/flowy-sync/src/client_document/extensions/insert/default_insert.rs b/shared-lib/flowy-sync/src/client_document/extensions/insert/default_insert.rs index b8be2ad5d3..948cf7f994 100644 --- a/shared-lib/flowy-sync/src/client_document/extensions/insert/default_insert.rs +++ b/shared-lib/flowy-sync/src/client_document/extensions/insert/default_insert.rs @@ -1,8 +1,8 @@ use crate::client_document::InsertExt; -use lib_ot::core::Attributes; +use lib_ot::core::AttributeHashMap; use lib_ot::{ core::{OperationAttributes, OperationBuilder, OperationIterator, NEW_LINE}, - text_delta::{BuildInTextAttributeKey, TextDelta}, + text_delta::{BuildInTextAttributeKey, TextOperations}, }; pub struct DefaultInsertAttribute {} @@ -11,9 +11,9 @@ impl InsertExt for DefaultInsertAttribute { "DefaultInsertAttribute" } - fn apply(&self, delta: &TextDelta, replace_len: usize, text: &str, index: usize) -> Option { + fn apply(&self, delta: &TextOperations, replace_len: usize, text: &str, index: usize) -> Option { let iter = OperationIterator::new(delta); - let mut attributes = Attributes::new(); + let mut attributes = AttributeHashMap::new(); // Enable each line split by "\n" remains the block attributes. for example: // insert "\n" to "123456" at index 3 @@ -28,7 +28,7 @@ impl InsertExt for DefaultInsertAttribute { .get_attributes() .contains_key(BuildInTextAttributeKey::Header.as_ref()) { - attributes.extend_other(op.get_attributes()); + attributes.extend(op.get_attributes()); } } } diff --git a/shared-lib/flowy-sync/src/client_document/extensions/insert/mod.rs b/shared-lib/flowy-sync/src/client_document/extensions/insert/mod.rs index 5206cb4a09..19661006e6 100644 --- a/shared-lib/flowy-sync/src/client_document/extensions/insert/mod.rs +++ b/shared-lib/flowy-sync/src/client_document/extensions/insert/mod.rs @@ -2,7 +2,7 @@ use crate::client_document::InsertExt; pub use auto_exit_block::*; pub use auto_format::*; pub use default_insert::*; -use lib_ot::text_delta::TextDelta; +use lib_ot::text_delta::TextOperations; pub use preserve_block_format::*; pub use preserve_inline_format::*; pub use reset_format_on_new_line::*; @@ -20,7 +20,13 @@ impl InsertExt for InsertEmbedsExt { "InsertEmbedsExt" } - fn apply(&self, _delta: &TextDelta, _replace_len: usize, _text: &str, _index: usize) -> Option { + fn apply( + &self, + _delta: &TextOperations, + _replace_len: usize, + _text: &str, + _index: usize, + ) -> Option { None } } @@ -31,7 +37,13 @@ impl InsertExt for ForceNewlineForInsertsAroundEmbedExt { "ForceNewlineForInsertsAroundEmbedExt" } - fn apply(&self, _delta: &TextDelta, _replace_len: usize, _text: &str, _index: usize) -> Option { + fn apply( + &self, + _delta: &TextOperations, + _replace_len: usize, + _text: &str, + _index: usize, + ) -> Option { None } } diff --git a/shared-lib/flowy-sync/src/client_document/extensions/insert/preserve_block_format.rs b/shared-lib/flowy-sync/src/client_document/extensions/insert/preserve_block_format.rs index 1b8ba41399..3ce1d1f9f0 100644 --- a/shared-lib/flowy-sync/src/client_document/extensions/insert/preserve_block_format.rs +++ b/shared-lib/flowy-sync/src/client_document/extensions/insert/preserve_block_format.rs @@ -1,8 +1,8 @@ use crate::{client_document::InsertExt, util::is_newline}; -use lib_ot::core::Attributes; +use lib_ot::core::AttributeHashMap; use lib_ot::{ core::{OperationBuilder, OperationIterator, NEW_LINE}, - text_delta::{attributes_except_header, empty_attributes, BuildInTextAttributeKey, TextDelta}, + text_delta::{attributes_except_header, empty_attributes, BuildInTextAttributeKey, TextOperations}, }; pub struct PreserveBlockFormatOnInsert {} @@ -11,7 +11,7 @@ impl InsertExt for PreserveBlockFormatOnInsert { "PreserveBlockFormatOnInsert" } - fn apply(&self, delta: &TextDelta, replace_len: usize, text: &str, index: usize) -> Option { + fn apply(&self, delta: &TextOperations, replace_len: usize, text: &str, index: usize) -> Option { if !is_newline(text) { return None; } @@ -26,7 +26,7 @@ impl InsertExt for PreserveBlockFormatOnInsert { return None; } - let mut reset_attribute = Attributes::new(); + let mut reset_attribute = AttributeHashMap::new(); if newline_attributes.contains_key(BuildInTextAttributeKey::Header.as_ref()) { reset_attribute.insert(BuildInTextAttributeKey::Header, 1); } diff --git a/shared-lib/flowy-sync/src/client_document/extensions/insert/preserve_inline_format.rs b/shared-lib/flowy-sync/src/client_document/extensions/insert/preserve_inline_format.rs index 94890b198b..f8bd30dc9b 100644 --- a/shared-lib/flowy-sync/src/client_document/extensions/insert/preserve_inline_format.rs +++ b/shared-lib/flowy-sync/src/client_document/extensions/insert/preserve_inline_format.rs @@ -4,7 +4,7 @@ use crate::{ }; use lib_ot::{ core::{OpNewline, OperationBuilder, OperationIterator, NEW_LINE}, - text_delta::{empty_attributes, BuildInTextAttributeKey, TextDelta}, + text_delta::{empty_attributes, BuildInTextAttributeKey, TextOperations}, }; pub struct PreserveInlineFormat {} @@ -13,7 +13,7 @@ impl InsertExt for PreserveInlineFormat { "PreserveInlineFormat" } - fn apply(&self, delta: &TextDelta, replace_len: usize, text: &str, index: usize) -> Option { + fn apply(&self, delta: &TextOperations, replace_len: usize, text: &str, index: usize) -> Option { if contain_newline(text) { return None; } @@ -59,7 +59,7 @@ impl InsertExt for PreserveLineFormatOnSplit { "PreserveLineFormatOnSplit" } - fn apply(&self, delta: &TextDelta, replace_len: usize, text: &str, index: usize) -> Option { + fn apply(&self, delta: &TextOperations, replace_len: usize, text: &str, index: usize) -> Option { if !is_newline(text) { return None; } @@ -76,7 +76,7 @@ impl InsertExt for PreserveLineFormatOnSplit { return None; } - let mut new_delta = TextDelta::new(); + let mut new_delta = TextOperations::new(); new_delta.retain(index + replace_len, empty_attributes()); if newline_status.is_contain() { diff --git a/shared-lib/flowy-sync/src/client_document/extensions/insert/reset_format_on_new_line.rs b/shared-lib/flowy-sync/src/client_document/extensions/insert/reset_format_on_new_line.rs index 0043ed89d0..3a15e9dba0 100644 --- a/shared-lib/flowy-sync/src/client_document/extensions/insert/reset_format_on_new_line.rs +++ b/shared-lib/flowy-sync/src/client_document/extensions/insert/reset_format_on_new_line.rs @@ -1,8 +1,8 @@ use crate::{client_document::InsertExt, util::is_newline}; -use lib_ot::core::Attributes; +use lib_ot::core::AttributeHashMap; use lib_ot::{ core::{OperationBuilder, OperationIterator, Utf16CodeUnitMetric, NEW_LINE}, - text_delta::{BuildInTextAttributeKey, TextDelta}, + text_delta::{BuildInTextAttributeKey, TextOperations}, }; pub struct ResetLineFormatOnNewLine {} @@ -11,7 +11,7 @@ impl InsertExt for ResetLineFormatOnNewLine { "ResetLineFormatOnNewLine" } - fn apply(&self, delta: &TextDelta, replace_len: usize, text: &str, index: usize) -> Option { + fn apply(&self, delta: &TextOperations, replace_len: usize, text: &str, index: usize) -> Option { if !is_newline(text) { return None; } @@ -23,7 +23,7 @@ impl InsertExt for ResetLineFormatOnNewLine { return None; } - let mut reset_attribute = Attributes::new(); + let mut reset_attribute = AttributeHashMap::new(); if next_op .get_attributes() .contains_key(BuildInTextAttributeKey::Header.as_ref()) diff --git a/shared-lib/flowy-sync/src/client_document/extensions/mod.rs b/shared-lib/flowy-sync/src/client_document/extensions/mod.rs index 1933663422..a2cd2dc9d7 100644 --- a/shared-lib/flowy-sync/src/client_document/extensions/mod.rs +++ b/shared-lib/flowy-sync/src/client_document/extensions/mod.rs @@ -2,7 +2,7 @@ pub use delete::*; pub use format::*; pub use insert::*; use lib_ot::core::AttributeEntry; -use lib_ot::{core::Interval, text_delta::TextDelta}; +use lib_ot::{core::Interval, text_delta::TextOperations}; mod delete; mod format; @@ -15,15 +15,15 @@ pub type DeleteExtension = Box; pub trait InsertExt { fn ext_name(&self) -> &str; - fn apply(&self, delta: &TextDelta, replace_len: usize, text: &str, index: usize) -> Option; + fn apply(&self, delta: &TextOperations, replace_len: usize, text: &str, index: usize) -> Option; } pub trait FormatExt { fn ext_name(&self) -> &str; - fn apply(&self, delta: &TextDelta, interval: Interval, attribute: &AttributeEntry) -> Option; + fn apply(&self, delta: &TextOperations, interval: Interval, attribute: &AttributeEntry) -> Option; } pub trait DeleteExt { fn ext_name(&self) -> &str; - fn apply(&self, delta: &TextDelta, interval: Interval) -> Option; + fn apply(&self, delta: &TextOperations, interval: Interval) -> Option; } diff --git a/shared-lib/flowy-sync/src/client_document/history.rs b/shared-lib/flowy-sync/src/client_document/history.rs index 75ff91d243..4d08a8238d 100644 --- a/shared-lib/flowy-sync/src/client_document/history.rs +++ b/shared-lib/flowy-sync/src/client_document/history.rs @@ -1,18 +1,18 @@ -use lib_ot::text_delta::TextDelta; +use lib_ot::text_delta::TextOperations; const MAX_UNDOES: usize = 20; #[derive(Debug, Clone)] pub struct UndoResult { - pub delta: TextDelta, + pub operations: TextOperations, } #[derive(Debug, Clone)] pub struct History { #[allow(dead_code)] cur_undo: usize, - undoes: Vec, - redoes: Vec, + undoes: Vec, + redoes: Vec, capacity: usize, } @@ -40,15 +40,15 @@ impl History { !self.redoes.is_empty() } - pub fn add_undo(&mut self, delta: TextDelta) { + pub fn add_undo(&mut self, delta: TextOperations) { self.undoes.push(delta); } - pub fn add_redo(&mut self, delta: TextDelta) { + pub fn add_redo(&mut self, delta: TextOperations) { self.redoes.push(delta); } - pub fn record(&mut self, delta: TextDelta) { + pub fn record(&mut self, delta: TextOperations) { if delta.ops.is_empty() { return; } @@ -61,7 +61,7 @@ impl History { } } - pub fn undo(&mut self) -> Option { + pub fn undo(&mut self) -> Option { if !self.can_undo() { return None; } @@ -69,7 +69,7 @@ impl History { Some(delta) } - pub fn redo(&mut self) -> Option { + pub fn redo(&mut self) -> Option { if !self.can_redo() { return None; } diff --git a/shared-lib/flowy-sync/src/client_document/mod.rs b/shared-lib/flowy-sync/src/client_document/mod.rs index c463469c22..7e52b8f9e8 100644 --- a/shared-lib/flowy-sync/src/client_document/mod.rs +++ b/shared-lib/flowy-sync/src/client_document/mod.rs @@ -4,7 +4,6 @@ pub use document_pad::*; pub(crate) use extensions::*; pub use view::*; -mod data; pub mod default; mod document_pad; mod extensions; diff --git a/shared-lib/flowy-sync/src/client_document/view.rs b/shared-lib/flowy-sync/src/client_document/view.rs index 6646d0f4e2..7c06e36bb8 100644 --- a/shared-lib/flowy-sync/src/client_document/view.rs +++ b/shared-lib/flowy-sync/src/client_document/view.rs @@ -3,7 +3,7 @@ use lib_ot::core::AttributeEntry; use lib_ot::{ core::{trim, Interval}, errors::{ErrorBuilder, OTError, OTErrorCode}, - text_delta::TextDelta, + text_delta::TextOperations, }; pub const RECORD_THRESHOLD: usize = 400; // in milliseconds @@ -23,24 +23,29 @@ impl ViewExtensions { } } - pub(crate) fn insert(&self, delta: &TextDelta, text: &str, interval: Interval) -> Result { - let mut new_delta = None; + pub(crate) fn insert( + &self, + operations: &TextOperations, + text: &str, + interval: Interval, + ) -> Result { + let mut new_operations = None; for ext in &self.insert_exts { - if let Some(mut delta) = ext.apply(delta, interval.size(), text, interval.start) { - trim(&mut delta); - tracing::trace!("[{}] applied, delta: {}", ext.ext_name(), delta); - new_delta = Some(delta); + if let Some(mut operations) = ext.apply(operations, interval.size(), text, interval.start) { + trim(&mut operations); + tracing::trace!("[{}] applied, delta: {}", ext.ext_name(), operations); + new_operations = Some(operations); break; } } - match new_delta { + match new_operations { None => Err(ErrorBuilder::new(OTErrorCode::ApplyInsertFail).build()), - Some(new_delta) => Ok(new_delta), + Some(new_operations) => Ok(new_operations), } } - pub(crate) fn delete(&self, delta: &TextDelta, interval: Interval) -> Result { + pub(crate) fn delete(&self, delta: &TextOperations, interval: Interval) -> Result { let mut new_delta = None; for ext in &self.delete_exts { if let Some(mut delta) = ext.apply(delta, interval) { @@ -59,23 +64,23 @@ impl ViewExtensions { pub(crate) fn format( &self, - delta: &TextDelta, + operations: &TextOperations, attribute: AttributeEntry, interval: Interval, - ) -> Result { - let mut new_delta = None; + ) -> Result { + let mut new_operations = None; for ext in &self.format_exts { - if let Some(mut delta) = ext.apply(delta, interval, &attribute) { - trim(&mut delta); - tracing::trace!("[{}] applied, delta: {}", ext.ext_name(), delta); - new_delta = Some(delta); + if let Some(mut operations) = ext.apply(operations, interval, &attribute) { + trim(&mut operations); + tracing::trace!("[{}] applied, delta: {}", ext.ext_name(), operations); + new_operations = Some(operations); break; } } - match new_delta { + match new_operations { None => Err(ErrorBuilder::new(OTErrorCode::ApplyFormatFail).build()), - Some(new_delta) => Ok(new_delta), + Some(new_operations) => Ok(new_operations), } } } diff --git a/shared-lib/flowy-sync/src/client_folder/builder.rs b/shared-lib/flowy-sync/src/client_folder/builder.rs index 6581591c25..972051a462 100644 --- a/shared-lib/flowy-sync/src/client_folder/builder.rs +++ b/shared-lib/flowy-sync/src/client_folder/builder.rs @@ -1,13 +1,12 @@ -use crate::entities::folder::FolderDelta; -use crate::util::make_text_delta_from_revisions; +use crate::util::make_operations_from_revisions; use crate::{ - client_folder::{default_folder_delta, FolderPad}, + client_folder::{default_folder_operations, FolderPad}, entities::revision::Revision, errors::CollaborateResult, }; +use crate::server_folder::FolderOperations; use flowy_folder_data_model::revision::{TrashRevision, WorkspaceRevision}; - use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize)] @@ -37,11 +36,11 @@ impl FolderPadBuilder { } pub(crate) fn build_with_revisions(self, revisions: Vec) -> CollaborateResult { - let mut folder_delta: FolderDelta = make_text_delta_from_revisions(revisions)?; - if folder_delta.is_empty() { - folder_delta = default_folder_delta(); + let mut operations: FolderOperations = make_operations_from_revisions(revisions)?; + if operations.is_empty() { + operations = default_folder_operations(); } - FolderPad::from_delta(folder_delta) + FolderPad::from_operations(operations) } #[allow(dead_code)] diff --git a/shared-lib/flowy-sync/src/client_folder/folder_pad.rs b/shared-lib/flowy-sync/src/client_folder/folder_pad.rs index 964df23fd7..87cb5c603d 100644 --- a/shared-lib/flowy-sync/src/client_folder/folder_pad.rs +++ b/shared-lib/flowy-sync/src/client_folder/folder_pad.rs @@ -1,24 +1,23 @@ use crate::errors::internal_error; +use crate::server_folder::FolderOperations; use crate::util::cal_diff; use crate::{ client_folder::builder::FolderPadBuilder, - entities::{ - folder::FolderDelta, - revision::{md5, Revision}, - }, + entities::revision::{md5, Revision}, errors::{CollaborateError, CollaborateResult}, }; use flowy_folder_data_model::revision::{AppRevision, FolderRevision, TrashRevision, ViewRevision, WorkspaceRevision}; use lib_infra::util::move_vec_element; use lib_ot::core::*; - use serde::Deserialize; use std::sync::Arc; +pub type FolderOperationsBuilder = DeltaBuilder; + #[derive(Debug, Clone, Eq, PartialEq)] pub struct FolderPad { folder_rev: FolderRevision, - delta: FolderDelta, + operations: FolderOperations, } impl FolderPad { @@ -33,43 +32,43 @@ impl FolderPad { pub fn from_folder_rev(folder_rev: FolderRevision) -> CollaborateResult { let json = serde_json::to_string(&folder_rev) .map_err(|e| CollaborateError::internal().context(format!("Serialize to folder json str failed: {}", e)))?; - let delta = DeltaBuilder::new().insert(&json).build(); + let operations = FolderOperationsBuilder::new().insert(&json).build(); - Ok(Self { folder_rev, delta }) + Ok(Self { folder_rev, operations }) } pub fn from_revisions(revisions: Vec) -> CollaborateResult { FolderPadBuilder::new().build_with_revisions(revisions) } - pub fn from_delta(delta: FolderDelta) -> CollaborateResult { + pub fn from_operations(operations: FolderOperations) -> CollaborateResult { // TODO: Reconvert from history if delta.to_str() failed. - let content = delta.content()?; + let content = operations.content()?; let mut deserializer = serde_json::Deserializer::from_reader(content.as_bytes()); let folder_rev = FolderRevision::deserialize(&mut deserializer).map_err(|e| { tracing::error!("Deserialize folder from {} failed", content); - return CollaborateError::internal().context(format!("Deserialize delta to folder failed: {}", e)); + return CollaborateError::internal().context(format!("Deserialize operations to folder failed: {}", e)); })?; - Ok(Self { folder_rev, delta }) + Ok(Self { folder_rev, operations }) } - pub fn delta(&self) -> &FolderDelta { - &self.delta + pub fn get_operations(&self) -> &FolderOperations { + &self.operations } - pub fn reset_folder(&mut self, delta: FolderDelta) -> CollaborateResult { - let folder = FolderPad::from_delta(delta)?; + pub fn reset_folder(&mut self, operations: FolderOperations) -> CollaborateResult { + let folder = FolderPad::from_operations(operations)?; self.folder_rev = folder.folder_rev; - self.delta = folder.delta; + self.operations = folder.operations; Ok(self.md5()) } - pub fn compose_remote_delta(&mut self, delta: FolderDelta) -> CollaborateResult { - let composed_delta = self.delta.compose(&delta)?; - self.reset_folder(composed_delta) + pub fn compose_remote_operations(&mut self, operations: FolderOperations) -> CollaborateResult { + let composed_operations = self.operations.compose(&operations)?; + self.reset_folder(composed_operations) } pub fn is_empty(&self) -> bool { @@ -318,7 +317,7 @@ impl FolderPad { } pub fn md5(&self) -> String { - md5(&self.delta.json_bytes()) + md5(&self.operations.json_bytes()) } pub fn to_json(&self) -> CollaborateResult { @@ -345,9 +344,12 @@ impl FolderPad { let new = self.to_json()?; match cal_diff::(old, new) { None => Ok(None), - Some(delta) => { - self.delta = self.delta.compose(&delta)?; - Ok(Some(FolderChangeset { delta, md5: self.md5() })) + Some(operations) => { + self.operations = self.operations.compose(&operations)?; + Ok(Some(FolderChangeset { + operations, + md5: self.md5(), + })) } } } @@ -380,9 +382,12 @@ impl FolderPad { let new = self.to_json()?; match cal_diff::(old, new) { None => Ok(None), - Some(delta) => { - self.delta = self.delta.compose(&delta)?; - Ok(Some(FolderChangeset { delta, md5: self.md5() })) + Some(operations) => { + self.operations = self.operations.compose(&operations)?; + Ok(Some(FolderChangeset { + operations, + md5: self.md5(), + })) } } } @@ -428,58 +433,62 @@ impl FolderPad { } } -pub fn default_folder_delta() -> FolderDelta { - DeltaBuilder::new().insert(r#"{"workspaces":[],"trash":[]}"#).build() +pub fn default_folder_operations() -> FolderOperations { + FolderOperationsBuilder::new() + .insert(r#"{"workspaces":[],"trash":[]}"#) + .build() } -pub fn initial_folder_delta(folder_pad: &FolderPad) -> CollaborateResult { +pub fn initial_folder_operations(folder_pad: &FolderPad) -> CollaborateResult { let json = folder_pad.to_json()?; - let delta = DeltaBuilder::new().insert(&json).build(); - Ok(delta) + let operations = FolderOperationsBuilder::new().insert(&json).build(); + Ok(operations) } impl std::default::Default for FolderPad { fn default() -> Self { FolderPad { folder_rev: FolderRevision::default(), - delta: default_folder_delta(), + operations: default_folder_operations(), } } } pub struct FolderChangeset { - pub delta: FolderDelta, - /// md5: the md5 of the FolderPad's delta after applying the change. + pub operations: FolderOperations, + /// md5: the md5 of the FolderPad's operations after applying the change. pub md5: String, } #[cfg(test)] mod tests { #![allow(clippy::all)] - use crate::{client_folder::folder_pad::FolderPad, entities::folder::FolderDelta}; + use crate::client_folder::folder_pad::FolderPad; use chrono::Utc; use serde::Deserialize; + use crate::client_folder::FolderOperationsBuilder; + use crate::server_folder::FolderOperations; use flowy_folder_data_model::revision::{ AppRevision, FolderRevision, TrashRevision, ViewRevision, WorkspaceRevision, }; - use lib_ot::core::{Delta, DeltaBuilder, OperationTransform}; + use lib_ot::core::{DeltaBuilder, OperationTransform}; #[test] fn folder_add_workspace() { - let (mut folder, initial_delta, _) = test_folder(); + let (mut folder, initial_operations, _) = test_folder(); let _time = Utc::now(); let mut workspace_1 = WorkspaceRevision::default(); workspace_1.name = "My first workspace".to_owned(); - let delta_1 = folder.create_workspace(workspace_1).unwrap().unwrap().delta; + let operations_1 = folder.create_workspace(workspace_1).unwrap().unwrap().operations; let mut workspace_2 = WorkspaceRevision::default(); workspace_2.name = "My second workspace".to_owned(); - let delta_2 = folder.create_workspace(workspace_2).unwrap().unwrap().delta; + let operations_2 = folder.create_workspace(workspace_2).unwrap().unwrap().operations; - let folder_from_delta = make_folder_from_delta(initial_delta, vec![delta_1, delta_2]); - assert_eq!(folder, folder_from_delta); + let folder_from_operations = make_folder_from_operations(initial_operations, vec![operations_1, operations_2]); + assert_eq!(folder, folder_from_operations); } #[test] @@ -498,35 +507,35 @@ mod tests { #[test] fn folder_update_workspace() { - let (mut folder, initial_delta, workspace) = test_folder(); + let (mut folder, initial_operation, workspace) = test_folder(); assert_folder_equal( &folder, - &make_folder_from_delta(initial_delta.clone(), vec![]), + &make_folder_from_operations(initial_operation.clone(), vec![]), r#"{"workspaces":[{"id":"1","name":"😁 my first workspace","desc":"","apps":[],"modified_time":0,"create_time":0}],"trash":[]}"#, ); - let delta = folder + let operations = folder .update_workspace(&workspace.id, Some("☺️ rename workspace️".to_string()), None) .unwrap() .unwrap() - .delta; + .operations; - let folder_from_delta = make_folder_from_delta(initial_delta, vec![delta]); + let folder_from_operations = make_folder_from_operations(initial_operation, vec![operations]); assert_folder_equal( &folder, - &folder_from_delta, + &folder_from_operations, r#"{"workspaces":[{"id":"1","name":"☺️ rename workspace️","desc":"","apps":[],"modified_time":0,"create_time":0}],"trash":[]}"#, ); } #[test] fn folder_add_app() { - let (folder, initial_delta, _app) = test_app_folder(); - let folder_from_delta = make_folder_from_delta(initial_delta, vec![]); - assert_eq!(folder, folder_from_delta); + let (folder, initial_operations, _app) = test_app_folder(); + let folder_from_operations = make_folder_from_operations(initial_operations, vec![]); + assert_eq!(folder, folder_from_operations); assert_folder_equal( &folder, - &folder_from_delta, + &folder_from_operations, r#"{ "workspaces": [ { @@ -556,14 +565,14 @@ mod tests { #[test] fn folder_update_app() { - let (mut folder, initial_delta, app) = test_app_folder(); - let delta = folder + let (mut folder, initial_operations, app) = test_app_folder(); + let operations = folder .update_app(&app.id, Some("🤪 rename app".to_owned()), None) .unwrap() .unwrap() - .delta; + .operations; - let new_folder = make_folder_from_delta(initial_delta, vec![delta]); + let new_folder = make_folder_from_operations(initial_operations, vec![operations]); assert_folder_equal( &folder, &new_folder, @@ -596,9 +605,9 @@ mod tests { #[test] fn folder_delete_app() { - let (mut folder, initial_delta, app) = test_app_folder(); - let delta = folder.delete_app(&app.id).unwrap().unwrap().delta; - let new_folder = make_folder_from_delta(initial_delta, vec![delta]); + let (mut folder, initial_operations, app) = test_app_folder(); + let operations = folder.delete_app(&app.id).unwrap().unwrap().operations; + let new_folder = make_folder_from_operations(initial_operations, vec![operations]); assert_folder_equal( &folder, &new_folder, @@ -620,10 +629,10 @@ mod tests { #[test] fn folder_add_view() { - let (folder, initial_delta, _view) = test_view_folder(); + let (folder, initial_operations, _view) = test_view_folder(); assert_folder_equal( &folder, - &make_folder_from_delta(initial_delta, vec![]), + &make_folder_from_operations(initial_operations, vec![]), r#" { "workspaces": [ @@ -666,14 +675,14 @@ mod tests { #[test] fn folder_update_view() { - let (mut folder, initial_delta, view) = test_view_folder(); - let delta = folder + let (mut folder, initial_operations, view) = test_view_folder(); + let operations = folder .update_view(&view.id, Some("😦 rename view".to_owned()), None, 123) .unwrap() .unwrap() - .delta; + .operations; - let new_folder = make_folder_from_delta(initial_delta, vec![delta]); + let new_folder = make_folder_from_operations(initial_operations, vec![operations]); assert_folder_equal( &folder, &new_folder, @@ -718,10 +727,10 @@ mod tests { #[test] fn folder_delete_view() { - let (mut folder, initial_delta, view) = test_view_folder(); - let delta = folder.delete_view(&view.id).unwrap().unwrap().delta; + let (mut folder, initial_operations, view) = test_view_folder(); + let operations = folder.delete_view(&view.id).unwrap().unwrap().operations; - let new_folder = make_folder_from_delta(initial_delta, vec![delta]); + let new_folder = make_folder_from_operations(initial_operations, vec![operations]); assert_folder_equal( &folder, &new_folder, @@ -754,10 +763,10 @@ mod tests { #[test] fn folder_add_trash() { - let (folder, initial_delta, _trash) = test_trash(); + let (folder, initial_operations, _trash) = test_trash(); assert_folder_equal( &folder, - &make_folder_from_delta(initial_delta, vec![]), + &make_folder_from_operations(initial_operations, vec![]), r#"{ "workspaces": [], "trash": [ @@ -776,11 +785,11 @@ mod tests { #[test] fn folder_delete_trash() { - let (mut folder, initial_delta, trash) = test_trash(); - let delta = folder.delete_trash(Some(vec![trash.id])).unwrap().unwrap().delta; + let (mut folder, initial_operations, trash) = test_trash(); + let operations = folder.delete_trash(Some(vec![trash.id])).unwrap().unwrap().operations; assert_folder_equal( &folder, - &make_folder_from_delta(initial_delta, vec![delta]), + &make_folder_from_operations(initial_operations, vec![operations]), r#"{ "workspaces": [], "trash": [] @@ -789,10 +798,10 @@ mod tests { ); } - fn test_folder() -> (FolderPad, FolderDelta, WorkspaceRevision) { + fn test_folder() -> (FolderPad, FolderOperations, WorkspaceRevision) { let folder_rev = FolderRevision::default(); let folder_json = serde_json::to_string(&folder_rev).unwrap(); - let mut delta = DeltaBuilder::new().insert(&folder_json).build(); + let mut operations = FolderOperationsBuilder::new().insert(&folder_json).build(); let mut workspace_rev = WorkspaceRevision::default(); workspace_rev.name = "😁 my first workspace".to_owned(); @@ -800,66 +809,75 @@ mod tests { let mut folder = FolderPad::from_folder_rev(folder_rev).unwrap(); - delta = delta - .compose(&folder.create_workspace(workspace_rev.clone()).unwrap().unwrap().delta) + operations = operations + .compose( + &folder + .create_workspace(workspace_rev.clone()) + .unwrap() + .unwrap() + .operations, + ) .unwrap(); - (folder, delta, workspace_rev) + (folder, operations, workspace_rev) } - fn test_app_folder() -> (FolderPad, FolderDelta, AppRevision) { - let (mut folder_rev, mut initial_delta, workspace) = test_folder(); + fn test_app_folder() -> (FolderPad, FolderOperations, AppRevision) { + let (mut folder_rev, mut initial_operations, workspace) = test_folder(); let mut app_rev = AppRevision::default(); app_rev.workspace_id = workspace.id; app_rev.name = "😁 my first app".to_owned(); - initial_delta = initial_delta - .compose(&folder_rev.create_app(app_rev.clone()).unwrap().unwrap().delta) + initial_operations = initial_operations + .compose(&folder_rev.create_app(app_rev.clone()).unwrap().unwrap().operations) .unwrap(); - (folder_rev, initial_delta, app_rev) + (folder_rev, initial_operations, app_rev) } - fn test_view_folder() -> (FolderPad, FolderDelta, ViewRevision) { - let (mut folder, mut initial_delta, app) = test_app_folder(); + fn test_view_folder() -> (FolderPad, FolderOperations, ViewRevision) { + let (mut folder, mut initial_operations, app) = test_app_folder(); let mut view_rev = ViewRevision::default(); view_rev.app_id = app.id.clone(); view_rev.name = "🎃 my first view".to_owned(); - initial_delta = initial_delta - .compose(&folder.create_view(view_rev.clone()).unwrap().unwrap().delta) + initial_operations = initial_operations + .compose(&folder.create_view(view_rev.clone()).unwrap().unwrap().operations) .unwrap(); - (folder, initial_delta, view_rev) + (folder, initial_operations, view_rev) } - fn test_trash() -> (FolderPad, FolderDelta, TrashRevision) { + fn test_trash() -> (FolderPad, FolderOperations, TrashRevision) { let folder_rev = FolderRevision::default(); let folder_json = serde_json::to_string(&folder_rev).unwrap(); - let mut delta = DeltaBuilder::new().insert(&folder_json).build(); + let mut operations = FolderOperationsBuilder::new().insert(&folder_json).build(); let mut trash_rev = TrashRevision::default(); trash_rev.name = "🚽 my first trash".to_owned(); trash_rev.id = "1".to_owned(); let mut folder = FolderPad::from_folder_rev(folder_rev).unwrap(); - delta = delta + operations = operations .compose( &folder .create_trash(vec![trash_rev.clone().into()]) .unwrap() .unwrap() - .delta, + .operations, ) .unwrap(); - (folder, delta, trash_rev) + (folder, operations, trash_rev) } - fn make_folder_from_delta(mut initial_delta: FolderDelta, deltas: Vec) -> FolderPad { - for delta in deltas { - initial_delta = initial_delta.compose(&delta).unwrap(); + fn make_folder_from_operations( + mut initial_operation: FolderOperations, + operations: Vec, + ) -> FolderPad { + for operation in operations { + initial_operation = initial_operation.compose(&operation).unwrap(); } - FolderPad::from_delta(initial_delta).unwrap() + FolderPad::from_operations(initial_operation).unwrap() } fn assert_folder_equal(old: &FolderPad, new: &FolderPad, expected: &str) { diff --git a/shared-lib/flowy-sync/src/client_grid/block_revision_pad.rs b/shared-lib/flowy-sync/src/client_grid/block_revision_pad.rs index 1c655b62ec..36f65837c0 100644 --- a/shared-lib/flowy-sync/src/client_grid/block_revision_pad.rs +++ b/shared-lib/flowy-sync/src/client_grid/block_revision_pad.rs @@ -1,18 +1,21 @@ use crate::entities::revision::{md5, RepeatedRevision, Revision}; use crate::errors::{CollaborateError, CollaborateResult}; -use crate::util::{cal_diff, make_text_delta_from_revisions}; +use crate::util::{cal_diff, make_operations_from_revisions}; use flowy_grid_data_model::revision::{ gen_block_id, gen_row_id, CellRevision, GridBlockRevision, RowChangeset, RowRevision, }; -use lib_ot::core::{Delta, DeltaBuilder, EmptyAttributes, OperationTransform}; +use lib_ot::core::{DeltaBuilder, DeltaOperations, EmptyAttributes, OperationTransform}; use std::borrow::Cow; use std::collections::HashMap; use std::sync::Arc; +pub type GridBlockOperations = DeltaOperations; +pub type GridBlockOperationsBuilder = DeltaBuilder; + #[derive(Debug, Clone)] pub struct GridBlockRevisionPad { block: GridBlockRevision, - delta: Delta, + operations: GridBlockOperations, } impl std::ops::Deref for GridBlockRevisionPad { @@ -42,19 +45,22 @@ impl GridBlockRevisionPad { } } - pub fn from_delta(delta: Delta) -> CollaborateResult { - let s = delta.content()?; + pub fn from_operations(operations: GridBlockOperations) -> CollaborateResult { + let s = operations.content()?; let revision: GridBlockRevision = serde_json::from_str(&s).map_err(|e| { - let msg = format!("Deserialize delta to GridBlockRevision failed: {}", e); + let msg = format!("Deserialize operations to GridBlockRevision failed: {}", e); tracing::error!("{}", s); CollaborateError::internal().context(msg) })?; - Ok(Self { block: revision, delta }) + Ok(Self { + block: revision, + operations, + }) } pub fn from_revisions(_grid_id: &str, revisions: Vec) -> CollaborateResult { - let block_delta: Delta = make_text_delta_from_revisions(revisions)?; - Self::from_delta(block_delta) + let operations: GridBlockOperations = make_operations_from_revisions(revisions)?; + Self::from_operations(operations) } #[tracing::instrument(level = "trace", skip(self, row), err)] @@ -202,12 +208,12 @@ impl GridBlockRevisionPad { let new = self.revision_json()?; match cal_diff::(old, new) { None => Ok(None), - Some(delta) => { - tracing::trace!("[GridBlockRevision] Composing delta {}", delta.json_str()); - self.delta = self.delta.compose(&delta)?; + Some(operations) => { + tracing::trace!("[GridBlockRevision] Composing operations {}", operations.json_str()); + self.operations = self.operations.compose(&operations)?; Ok(Some(GridBlockRevisionChangeset { - delta, - md5: md5(&self.delta.json_bytes()), + operations, + md5: md5(&self.operations.json_bytes()), })) } } @@ -234,25 +240,25 @@ impl GridBlockRevisionPad { .map_err(|e| CollaborateError::internal().context(format!("serial block to json failed: {}", e))) } - pub fn json_str(&self) -> String { - self.delta.json_str() + pub fn operations_json_str(&self) -> String { + self.operations.json_str() } } pub struct GridBlockRevisionChangeset { - pub delta: Delta, + pub operations: GridBlockOperations, /// md5: the md5 of the grid after applying the change. pub md5: String, } -pub fn make_grid_block_delta(block_rev: &GridBlockRevision) -> Delta { +pub fn make_grid_block_operations(block_rev: &GridBlockRevision) -> GridBlockOperations { let json = serde_json::to_string(&block_rev).unwrap(); - DeltaBuilder::new().insert(&json).build() + GridBlockOperationsBuilder::new().insert(&json).build() } pub fn make_grid_block_revisions(user_id: &str, grid_block_meta_data: &GridBlockRevision) -> RepeatedRevision { - let delta = make_grid_block_delta(grid_block_meta_data); - let bytes = delta.json_bytes(); + let operations = make_grid_block_operations(grid_block_meta_data); + let bytes = operations.json_bytes(); let revision = Revision::initial_revision(user_id, &grid_block_meta_data.block_id, bytes); revision.into() } @@ -264,19 +270,19 @@ impl std::default::Default for GridBlockRevisionPad { rows: vec![], }; - let delta = make_grid_block_delta(&block_revision); + let operations = make_grid_block_operations(&block_revision); GridBlockRevisionPad { block: block_revision, - delta, + operations, } } } #[cfg(test)] mod tests { - use crate::client_grid::GridBlockRevisionPad; + use crate::client_grid::{GridBlockOperations, GridBlockRevisionPad}; use flowy_grid_data_model::revision::{RowChangeset, RowRevision}; - use lib_ot::core::Delta; + use std::borrow::Cow; #[test] @@ -293,7 +299,7 @@ mod tests { let change = pad.add_row_rev(row.clone(), None).unwrap().unwrap(); assert_eq!(pad.rows.first().unwrap().as_ref(), &row); assert_eq!( - change.delta.json_str(), + change.operations.json_str(), r#"[{"retain":24},{"insert":"{\"id\":\"1\",\"block_id\":\"1\",\"cells\":[],\"height\":0,\"visibility\":false}"},{"retain":2}]"# ); } @@ -307,19 +313,19 @@ mod tests { let change = pad.add_row_rev(row_1.clone(), None).unwrap().unwrap(); assert_eq!( - change.delta.json_str(), + change.operations.json_str(), r#"[{"retain":24},{"insert":"{\"id\":\"1\",\"block_id\":\"1\",\"cells\":[],\"height\":0,\"visibility\":false}"},{"retain":2}]"# ); let change = pad.add_row_rev(row_2.clone(), None).unwrap().unwrap(); assert_eq!( - change.delta.json_str(), + change.operations.json_str(), r#"[{"retain":90},{"insert":",{\"id\":\"2\",\"block_id\":\"1\",\"cells\":[],\"height\":0,\"visibility\":false}"},{"retain":2}]"# ); let change = pad.add_row_rev(row_3.clone(), Some("2".to_string())).unwrap().unwrap(); assert_eq!( - change.delta.json_str(), + change.operations.json_str(), r#"[{"retain":157},{"insert":",{\"id\":\"3\",\"block_id\":\"1\",\"cells\":[],\"height\":0,\"visibility\":false}"},{"retain":2}]"# ); @@ -373,7 +379,7 @@ mod tests { #[test] fn block_meta_delete_row() { let mut pad = test_pad(); - let pre_delta_str = pad.json_str(); + let pre_json_str = pad.operations_json_str(); let row = RowRevision { id: "1".to_string(), block_id: pad.block_id.clone(), @@ -384,9 +390,12 @@ mod tests { let _ = pad.add_row_rev(row.clone(), None).unwrap().unwrap(); let change = pad.delete_rows(vec![Cow::Borrowed(&row.id)]).unwrap().unwrap(); - assert_eq!(change.delta.json_str(), r#"[{"retain":24},{"delete":66},{"retain":2}]"#); + assert_eq!( + change.operations.json_str(), + r#"[{"retain":24},{"delete":66},{"retain":2}]"# + ); - assert_eq!(pad.json_str(), pre_delta_str); + assert_eq!(pad.operations_json_str(), pre_json_str); } #[test] @@ -411,7 +420,7 @@ mod tests { let change = pad.update_row(changeset).unwrap().unwrap(); assert_eq!( - change.delta.json_str(), + change.operations.json_str(), r#"[{"retain":69},{"insert":"10"},{"retain":15},{"insert":"tru"},{"delete":4},{"retain":4}]"# ); @@ -422,7 +431,7 @@ mod tests { } fn test_pad() -> GridBlockRevisionPad { - let delta = Delta::from_json(r#"[{"insert":"{\"block_id\":\"1\",\"rows\":[]}"}]"#).unwrap(); - GridBlockRevisionPad::from_delta(delta).unwrap() + let operations = GridBlockOperations::from_json(r#"[{"insert":"{\"block_id\":\"1\",\"rows\":[]}"}]"#).unwrap(); + GridBlockRevisionPad::from_operations(operations).unwrap() } } diff --git a/shared-lib/flowy-sync/src/client_grid/grid_revision_pad.rs b/shared-lib/flowy-sync/src/client_grid/grid_revision_pad.rs index 64197716bb..df80521fae 100644 --- a/shared-lib/flowy-sync/src/client_grid/grid_revision_pad.rs +++ b/shared-lib/flowy-sync/src/client_grid/grid_revision_pad.rs @@ -1,22 +1,22 @@ use crate::entities::revision::{md5, RepeatedRevision, Revision}; use crate::errors::{internal_error, CollaborateError, CollaborateResult}; -use crate::util::{cal_diff, make_text_delta_from_revisions}; -use bytes::Bytes; +use crate::util::{cal_diff, make_operations_from_revisions}; + use flowy_grid_data_model::revision::{ gen_block_id, gen_grid_id, FieldRevision, FieldTypeRevision, GridBlockMetaRevision, GridBlockMetaRevisionChangeset, GridRevision, }; use lib_infra::util::move_vec_element; -use lib_ot::core::{Delta, DeltaBuilder, EmptyAttributes, OperationTransform}; +use lib_ot::core::{DeltaBuilder, DeltaOperations, EmptyAttributes, OperationTransform}; use std::collections::HashMap; use std::sync::Arc; -pub type GridRevisionDelta = Delta; -pub type GridRevisionDeltaBuilder = DeltaBuilder; +pub type GridOperations = DeltaOperations; +pub type GridOperationsBuilder = DeltaBuilder; pub struct GridRevisionPad { grid_rev: Arc, - delta: GridRevisionDelta, + operations: GridOperations, } pub trait JsonDeserializer { @@ -49,23 +49,23 @@ impl GridRevisionPad { (fields, blocks) } - pub fn from_delta(delta: GridRevisionDelta) -> CollaborateResult { - let content = delta.content()?; + pub fn from_operations(operations: GridOperations) -> CollaborateResult { + let content = operations.content()?; let grid: GridRevision = serde_json::from_str(&content).map_err(|e| { - let msg = format!("Deserialize delta to grid failed: {}", e); + let msg = format!("Deserialize operations to grid failed: {}", e); tracing::error!("{}", msg); CollaborateError::internal().context(msg) })?; Ok(Self { grid_rev: Arc::new(grid), - delta, + operations, }) } pub fn from_revisions(revisions: Vec) -> CollaborateResult { - let grid_delta: GridRevisionDelta = make_text_delta_from_revisions(revisions)?; - Self::from_delta(grid_delta) + let operations: GridOperations = make_operations_from_revisions(revisions)?; + Self::from_operations(operations) } #[tracing::instrument(level = "debug", skip_all, err)] @@ -293,18 +293,14 @@ impl GridRevisionPad { } pub fn md5(&self) -> String { - md5(&self.delta.json_bytes()) + md5(&self.operations.json_bytes()) } - pub fn delta_str(&self) -> String { - self.delta.json_str() + pub fn operations_json_str(&self) -> String { + self.operations.json_str() } - pub fn delta_bytes(&self) -> Bytes { - self.delta.json_bytes() - } - - pub fn fields(&self) -> &[Arc] { + pub fn get_fields(&self) -> &[Arc] { &self.grid_rev.fields } @@ -320,9 +316,12 @@ impl GridRevisionPad { let new = self.json_str()?; match cal_diff::(old, new) { None => Ok(None), - Some(delta) => { - self.delta = self.delta.compose(&delta)?; - Ok(Some(GridRevisionChangeset { delta, md5: self.md5() })) + Some(operations) => { + self.operations = self.operations.compose(&operations)?; + Ok(Some(GridRevisionChangeset { + operations, + md5: self.md5(), + })) } } } @@ -377,19 +376,19 @@ pub fn make_grid_rev_json_str(grid_revision: &GridRevision) -> CollaborateResult } pub struct GridRevisionChangeset { - pub delta: GridRevisionDelta, + pub operations: GridOperations, /// md5: the md5 of the grid after applying the change. pub md5: String, } -pub fn make_grid_delta(grid_rev: &GridRevision) -> GridRevisionDelta { +pub fn make_grid_operations(grid_rev: &GridRevision) -> GridOperations { let json = serde_json::to_string(&grid_rev).unwrap(); - DeltaBuilder::new().insert(&json).build() + GridOperationsBuilder::new().insert(&json).build() } pub fn make_grid_revisions(user_id: &str, grid_rev: &GridRevision) -> RepeatedRevision { - let delta = make_grid_delta(grid_rev); - let bytes = delta.json_bytes(); + let operations = make_grid_operations(grid_rev); + let bytes = operations.json_bytes(); let revision = Revision::initial_revision(user_id, &grid_rev.grid_id, bytes); revision.into() } @@ -397,10 +396,10 @@ pub fn make_grid_revisions(user_id: &str, grid_rev: &GridRevision) -> RepeatedRe impl std::default::Default for GridRevisionPad { fn default() -> Self { let grid = GridRevision::new(&gen_grid_id()); - let delta = make_grid_delta(&grid); + let operations = make_grid_operations(&grid); GridRevisionPad { grid_rev: Arc::new(grid), - delta, + operations, } } } diff --git a/shared-lib/flowy-sync/src/client_grid/view_revision_pad.rs b/shared-lib/flowy-sync/src/client_grid/view_revision_pad.rs index 11e9d5a07e..46e91734b4 100644 --- a/shared-lib/flowy-sync/src/client_grid/view_revision_pad.rs +++ b/shared-lib/flowy-sync/src/client_grid/view_revision_pad.rs @@ -1,17 +1,20 @@ use crate::entities::revision::{md5, Revision}; use crate::errors::{internal_error, CollaborateError, CollaborateResult}; -use crate::util::{cal_diff, make_text_delta_from_revisions}; +use crate::util::{cal_diff, make_operations_from_revisions}; use flowy_grid_data_model::revision::{ FieldRevision, FieldTypeRevision, FilterConfigurationRevision, FilterConfigurationsByFieldId, GridViewRevision, GroupConfigurationRevision, GroupConfigurationsByFieldId, LayoutRevision, }; -use lib_ot::core::{Delta, DeltaBuilder, EmptyAttributes, OperationTransform}; +use lib_ot::core::{DeltaBuilder, DeltaOperations, EmptyAttributes, OperationTransform}; use std::sync::Arc; +pub type GridViewOperations = DeltaOperations; +pub type GridViewOperationsBuilder = DeltaBuilder; + #[derive(Debug, Clone)] pub struct GridViewRevisionPad { view: Arc, - delta: Delta, + operations: GridViewOperations, } impl std::ops::Deref for GridViewRevisionPad { @@ -28,33 +31,33 @@ impl GridViewRevisionPad { pub fn new(grid_id: String, view_id: String, layout: LayoutRevision) -> Self { let view = Arc::new(GridViewRevision::new(grid_id, view_id, layout)); let json = serde_json::to_string(&view).unwrap(); - let delta = DeltaBuilder::new().insert(&json).build(); - Self { view, delta } + let operations = GridViewOperationsBuilder::new().insert(&json).build(); + Self { view, operations } } - pub fn from_delta(view_id: &str, delta: Delta) -> CollaborateResult { - if delta.is_empty() { + pub fn from_operations(view_id: &str, operations: GridViewOperations) -> CollaborateResult { + if operations.is_empty() { return Ok(GridViewRevisionPad::new( view_id.to_owned(), view_id.to_owned(), LayoutRevision::Table, )); } - let s = delta.content()?; + let s = operations.content()?; let view: GridViewRevision = serde_json::from_str(&s).map_err(|e| { - let msg = format!("Deserialize delta to GridViewRevision failed: {}", e); + let msg = format!("Deserialize operations to GridViewRevision failed: {}", e); tracing::error!("parsing json: {}", s); CollaborateError::internal().context(msg) })?; Ok(Self { view: Arc::new(view), - delta, + operations, }) } pub fn from_revisions(view_id: &str, revisions: Vec) -> CollaborateResult { - let delta: Delta = make_text_delta_from_revisions(revisions)?; - Self::from_delta(view_id, delta) + let operations: GridViewOperations = make_operations_from_revisions(revisions)?; + Self::from_operations(view_id, operations) } pub fn get_groups_by_field_revs(&self, field_revs: &[Arc]) -> Option { @@ -183,10 +186,10 @@ impl GridViewRevisionPad { let new = self.json_str()?; match cal_diff::(old, new) { None => Ok(None), - Some(delta) => { - self.delta = self.delta.compose(&delta)?; - let md5 = md5(&self.delta.json_bytes()); - Ok(Some(GridViewRevisionChangeset { delta, md5 })) + Some(operations) => { + self.operations = self.operations.compose(&operations)?; + let md5 = md5(&self.operations.json_bytes()); + Ok(Some(GridViewRevisionChangeset { operations, md5 })) } } } @@ -196,7 +199,7 @@ impl GridViewRevisionPad { #[derive(Debug)] pub struct GridViewRevisionChangeset { - pub delta: Delta, + pub operations: GridViewOperations, pub md5: String, } @@ -206,7 +209,7 @@ pub fn make_grid_view_rev_json_str(grid_revision: &GridViewRevision) -> Collabor Ok(json) } -pub fn make_grid_view_delta(grid_view: &GridViewRevision) -> Delta { +pub fn make_grid_view_operations(grid_view: &GridViewRevision) -> GridViewOperations { let json = serde_json::to_string(grid_view).unwrap(); - DeltaBuilder::new().insert(&json).build() + GridViewOperationsBuilder::new().insert(&json).build() } diff --git a/shared-lib/flowy-sync/src/entities/folder.rs b/shared-lib/flowy-sync/src/entities/folder.rs index bf4cd59e93..1f7ecd0b60 100644 --- a/shared-lib/flowy-sync/src/entities/folder.rs +++ b/shared-lib/flowy-sync/src/entities/folder.rs @@ -1,7 +1,4 @@ use flowy_derive::ProtoBuf; -use lib_ot::core::Delta; - -pub type FolderDelta = Delta; #[derive(ProtoBuf, Default, Debug, Clone, Eq, PartialEq)] pub struct FolderInfo { diff --git a/shared-lib/flowy-sync/src/entities/revision.rs b/shared-lib/flowy-sync/src/entities/revision.rs index 2b7d78ecc8..4f7cc7a148 100644 --- a/shared-lib/flowy-sync/src/entities/revision.rs +++ b/shared-lib/flowy-sync/src/entities/revision.rs @@ -1,8 +1,9 @@ use bytes::Bytes; use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; -use lib_ot::text_delta::TextDelta; use std::{convert::TryFrom, fmt::Formatter, ops::RangeInclusive}; +pub type RevisionObject = lib_ot::text_delta::TextOperations; + #[derive(PartialEq, Eq, Clone, Default, ProtoBuf)] pub struct Revision { #[pb(index = 1)] @@ -12,7 +13,7 @@ pub struct Revision { pub rev_id: i64, #[pb(index = 3)] - pub delta_data: Vec, + pub bytes: Vec, #[pb(index = 4)] pub md5: String, @@ -47,22 +48,15 @@ impl Revision { self.rev_id == 0 } - pub fn initial_revision(user_id: &str, object_id: &str, delta_data: Bytes) -> Self { - let md5 = md5(&delta_data); - Self::new(object_id, 0, 0, delta_data, user_id, md5) + pub fn initial_revision(user_id: &str, object_id: &str, bytes: Bytes) -> Self { + let md5 = md5(&bytes); + Self::new(object_id, 0, 0, bytes, user_id, md5) } - pub fn new( - object_id: &str, - base_rev_id: i64, - rev_id: i64, - delta_data: Bytes, - user_id: &str, - md5: String, - ) -> Revision { + pub fn new(object_id: &str, base_rev_id: i64, rev_id: i64, bytes: Bytes, user_id: &str, md5: String) -> Revision { let user_id = user_id.to_owned(); let object_id = object_id.to_owned(); - let delta_data = delta_data.to_vec(); + let bytes = bytes.to_vec(); let base_rev_id = base_rev_id; let rev_id = rev_id; @@ -73,7 +67,7 @@ impl Revision { Self { base_rev_id, rev_id, - delta_data, + bytes, md5, object_id, ty: RevType::DeprecatedLocal, @@ -87,12 +81,12 @@ impl std::fmt::Debug for Revision { let _ = f.write_fmt(format_args!("object_id {}, ", self.object_id))?; let _ = f.write_fmt(format_args!("base_rev_id {}, ", self.base_rev_id))?; let _ = f.write_fmt(format_args!("rev_id {}, ", self.rev_id))?; - match TextDelta::from_bytes(&self.delta_data) { - Ok(delta) => { - let _ = f.write_fmt(format_args!("delta {:?}", delta.json_str()))?; + match RevisionObject::from_bytes(&self.bytes) { + Ok(object) => { + let _ = f.write_fmt(format_args!("object {:?}", object.json_str()))?; } Err(e) => { - let _ = f.write_fmt(format_args!("delta {:?}", e))?; + let _ = f.write_fmt(format_args!("object {:?}", e))?; } } Ok(()) diff --git a/shared-lib/flowy-sync/src/entities/text_block.rs b/shared-lib/flowy-sync/src/entities/text_block.rs index cca7222bd0..edea62a0e0 100644 --- a/shared-lib/flowy-sync/src/entities/text_block.rs +++ b/shared-lib/flowy-sync/src/entities/text_block.rs @@ -3,7 +3,7 @@ use crate::{ errors::CollaborateError, }; use flowy_derive::ProtoBuf; -use lib_ot::{errors::OTError, text_delta::TextDelta}; +use lib_ot::{errors::OTError, text_delta::TextOperations}; #[derive(ProtoBuf, Default, Debug, Clone)] pub struct CreateTextBlockParams { @@ -30,8 +30,8 @@ pub struct DocumentPB { } impl DocumentPB { - pub fn delta(&self) -> Result { - let delta = TextDelta::from_bytes(&self.text)?; + pub fn delta(&self) -> Result { + let delta = TextOperations::from_bytes(&self.text)?; Ok(delta) } } @@ -45,7 +45,7 @@ impl std::convert::TryFrom for DocumentPB { .context("Revision's rev_id should be 0 when creating the document")); } - let delta = TextDelta::from_bytes(&revision.delta_data)?; + let delta = TextOperations::from_bytes(&revision.bytes)?; let doc_json = delta.json_str(); Ok(DocumentPB { diff --git a/shared-lib/flowy-sync/src/lib.rs b/shared-lib/flowy-sync/src/lib.rs index 745d588f7e..b21023c903 100644 --- a/shared-lib/flowy-sync/src/lib.rs +++ b/shared-lib/flowy-sync/src/lib.rs @@ -9,4 +9,4 @@ pub mod server_folder; pub mod synchronizer; pub mod util; -pub use lib_ot::text_delta::TextDelta; +pub use lib_ot::text_delta::TextOperations; diff --git a/shared-lib/flowy-sync/src/server_document/document_manager.rs b/shared-lib/flowy-sync/src/server_document/document_manager.rs index 95a25bb6da..786021b0b4 100644 --- a/shared-lib/flowy-sync/src/server_document/document_manager.rs +++ b/shared-lib/flowy-sync/src/server_document/document_manager.rs @@ -11,8 +11,8 @@ use async_stream::stream; use dashmap::DashMap; use futures::stream::StreamExt; use lib_infra::future::BoxResultFuture; -use lib_ot::core::Attributes; -use lib_ot::text_delta::TextDelta; +use lib_ot::core::AttributeHashMap; +use lib_ot::text_delta::TextOperations; use std::{collections::HashMap, fmt::Debug, sync::Arc}; use tokio::{ sync::{mpsc, oneshot, RwLock}, @@ -199,7 +199,7 @@ impl std::ops::Drop for ServerDocumentManager { } } -type DocumentRevisionSynchronizer = RevisionSynchronizer; +type DocumentRevisionSynchronizer = RevisionSynchronizer; struct OpenDocumentHandler { doc_id: String, @@ -213,8 +213,8 @@ impl OpenDocumentHandler { let (sender, receiver) = mpsc::channel(1000); let users = DashMap::new(); - let delta = TextDelta::from_bytes(&doc.text)?; - let sync_object = ServerDocument::from_delta(&doc_id, delta); + let operations = TextOperations::from_bytes(&doc.text)?; + let sync_object = ServerDocument::from_operations(&doc_id, operations); let synchronizer = Arc::new(DocumentRevisionSynchronizer::new(doc.rev_id, sync_object, persistence)); let queue = DocumentCommandRunner::new(&doc.block_id, receiver, synchronizer); diff --git a/shared-lib/flowy-sync/src/server_document/document_pad.rs b/shared-lib/flowy-sync/src/server_document/document_pad.rs index 7a46a8b432..3a6c54628f 100644 --- a/shared-lib/flowy-sync/src/server_document/document_pad.rs +++ b/shared-lib/flowy-sync/src/server_document/document_pad.rs @@ -1,45 +1,49 @@ -use crate::{client_document::InitialDocumentText, errors::CollaborateError, synchronizer::RevisionSyncObject}; -use lib_ot::{core::*, text_delta::TextDelta}; +use crate::synchronizer::RevisionOperations; +use crate::{client_document::InitialDocumentContent, errors::CollaborateError, synchronizer::RevisionSyncObject}; +use lib_ot::{core::*, text_delta::TextOperations}; pub struct ServerDocument { - doc_id: String, - delta: TextDelta, + document_id: String, + operations: TextOperations, } impl ServerDocument { #[allow(dead_code)] - pub fn new(doc_id: &str) -> Self { - Self::from_delta(doc_id, C::initial_delta()) + pub fn new(doc_id: &str) -> Self { + let operations = TextOperations::from_json(&C::json_str()).unwrap(); + Self::from_operations(doc_id, operations) } - pub fn from_delta(doc_id: &str, delta: TextDelta) -> Self { - let doc_id = doc_id.to_owned(); - ServerDocument { doc_id, delta } + pub fn from_operations(document_id: &str, operations: TextOperations) -> Self { + let document_id = document_id.to_owned(); + ServerDocument { + document_id, + operations, + } } } -impl RevisionSyncObject for ServerDocument { - fn id(&self) -> &str { - &self.doc_id +impl RevisionSyncObject for ServerDocument { + fn object_id(&self) -> &str { + &self.document_id } - fn compose(&mut self, other: &TextDelta) -> Result<(), CollaborateError> { - // tracing::trace!("{} compose {}", &self.delta.to_json(), other.to_json()); - let new_delta = self.delta.compose(other)?; - self.delta = new_delta; + fn object_json(&self) -> String { + self.operations.json_str() + } + + fn compose(&mut self, other: &TextOperations) -> Result<(), CollaborateError> { + let operations = self.operations.compose(other)?; + self.operations = operations; Ok(()) } - fn transform(&self, other: &TextDelta) -> Result<(TextDelta, TextDelta), CollaborateError> { - let value = self.delta.transform(other)?; + fn transform(&self, other: &TextOperations) -> Result<(TextOperations, TextOperations), CollaborateError> { + let value = self.operations.transform(other)?; Ok(value) } - fn to_json(&self) -> String { - self.delta.json_str() - } - - fn set_delta(&mut self, new_delta: Operations) { - self.delta = new_delta; + fn set_operations(&mut self, operations: RevisionOperations) { + self.operations = operations; } } diff --git a/shared-lib/flowy-sync/src/server_folder/folder_manager.rs b/shared-lib/flowy-sync/src/server_folder/folder_manager.rs index 14e28b9421..43d624028c 100644 --- a/shared-lib/flowy-sync/src/server_folder/folder_manager.rs +++ b/shared-lib/flowy-sync/src/server_folder/folder_manager.rs @@ -1,19 +1,16 @@ use crate::entities::revision::{RepeatedRevision, Revision}; +use crate::server_folder::folder_pad::{FolderOperations, FolderRevisionSynchronizer}; use crate::{ - entities::{ - folder::{FolderDelta, FolderInfo}, - ws_data::ServerRevisionWSDataBuilder, - }, + entities::{folder::FolderInfo, ws_data::ServerRevisionWSDataBuilder}, errors::{internal_error, CollaborateError, CollaborateResult}, protobuf::ClientRevisionWSData, server_folder::folder_pad::ServerFolder, - synchronizer::{RevisionSyncPersistence, RevisionSyncResponse, RevisionSynchronizer, RevisionUser}, + synchronizer::{RevisionSyncPersistence, RevisionSyncResponse, RevisionUser}, util::rev_id_from_str, }; use async_stream::stream; use futures::stream::StreamExt; use lib_infra::future::BoxResultFuture; -use lib_ot::core::EmptyAttributes; use std::{collections::HashMap, fmt::Debug, sync::Arc}; use tokio::{ sync::{mpsc, oneshot, RwLock}, @@ -188,8 +185,6 @@ impl ServerFolderManager { } } -type FolderRevisionSynchronizer = RevisionSynchronizer; - struct OpenFolderHandler { folder_id: String, sender: mpsc::Sender, @@ -199,8 +194,8 @@ impl OpenFolderHandler { fn new(folder_info: FolderInfo, persistence: Arc) -> CollaborateResult { let (sender, receiver) = mpsc::channel(1000); let folder_id = folder_info.folder_id.clone(); - let delta = FolderDelta::from_bytes(&folder_info.text)?; - let sync_object = ServerFolder::from_delta(&folder_id, delta); + let operations = FolderOperations::from_bytes(&folder_info.text)?; + let sync_object = ServerFolder::from_operations(&folder_id, operations); let synchronizer = Arc::new(FolderRevisionSynchronizer::new( folder_info.rev_id, sync_object, diff --git a/shared-lib/flowy-sync/src/server_folder/folder_pad.rs b/shared-lib/flowy-sync/src/server_folder/folder_pad.rs index 9efa7dd6ed..f192cc7f3d 100644 --- a/shared-lib/flowy-sync/src/server_folder/folder_pad.rs +++ b/shared-lib/flowy-sync/src/server_folder/folder_pad.rs @@ -1,41 +1,45 @@ -use crate::{entities::folder::FolderDelta, errors::CollaborateError, synchronizer::RevisionSyncObject}; -use lib_ot::core::{Delta, EmptyAttributes, OperationTransform}; +use crate::synchronizer::{RevisionOperations, RevisionSynchronizer}; +use crate::{errors::CollaborateError, synchronizer::RevisionSyncObject}; +use lib_ot::core::{DeltaOperations, EmptyAttributes, OperationTransform}; + +pub type FolderRevisionSynchronizer = RevisionSynchronizer; +pub type FolderOperations = DeltaOperations; pub struct ServerFolder { folder_id: String, - delta: FolderDelta, + operations: FolderOperations, } impl ServerFolder { - pub fn from_delta(folder_id: &str, delta: FolderDelta) -> Self { + pub fn from_operations(folder_id: &str, operations: FolderOperations) -> Self { Self { folder_id: folder_id.to_owned(), - delta, + operations, } } } impl RevisionSyncObject for ServerFolder { - fn id(&self) -> &str { + fn object_id(&self) -> &str { &self.folder_id } - fn compose(&mut self, other: &Delta) -> Result<(), CollaborateError> { - let new_delta = self.delta.compose(other)?; - self.delta = new_delta; + fn object_json(&self) -> String { + self.operations.json_str() + } + + fn compose(&mut self, other: &FolderOperations) -> Result<(), CollaborateError> { + let operations = self.operations.compose(other)?; + self.operations = operations; Ok(()) } - fn transform(&self, other: &Delta) -> Result<(Delta, Delta), CollaborateError> { - let value = self.delta.transform(other)?; + fn transform(&self, other: &FolderOperations) -> Result<(FolderOperations, FolderOperations), CollaborateError> { + let value = self.operations.transform(other)?; Ok(value) } - fn to_json(&self) -> String { - self.delta.json_str() - } - - fn set_delta(&mut self, new_delta: Delta) { - self.delta = new_delta; + fn set_operations(&mut self, operations: RevisionOperations) { + self.operations = operations; } } diff --git a/shared-lib/flowy-sync/src/server_folder/mod.rs b/shared-lib/flowy-sync/src/server_folder/mod.rs index 309254d1e5..7858b783c6 100644 --- a/shared-lib/flowy-sync/src/server_folder/mod.rs +++ b/shared-lib/flowy-sync/src/server_folder/mod.rs @@ -2,3 +2,4 @@ mod folder_manager; mod folder_pad; pub use folder_manager::*; +pub use folder_pad::*; diff --git a/shared-lib/flowy-sync/src/synchronizer.rs b/shared-lib/flowy-sync/src/synchronizer.rs index 3c3be82f82..49bfaf5a77 100644 --- a/shared-lib/flowy-sync/src/synchronizer.rs +++ b/shared-lib/flowy-sync/src/synchronizer.rs @@ -9,7 +9,7 @@ use crate::{ util::*, }; use lib_infra::future::BoxResultFuture; -use lib_ot::core::{OperationAttributes, Operations}; +use lib_ot::core::{DeltaOperations, OperationAttributes}; use parking_lot::RwLock; use serde::de::DeserializeOwned; use std::{ @@ -22,6 +22,14 @@ use std::{ time::Duration, }; +pub type RevisionOperations = DeltaOperations; + +pub trait RevisionOperations2: Send + Sync { + fn from_bytes>(bytes: B) -> Result + where + Self: Sized; +} + pub trait RevisionUser: Send + Sync + Debug { fn user_id(&self) -> String; fn receive(&self, resp: RevisionSyncResponse); @@ -43,12 +51,19 @@ pub trait RevisionSyncPersistence: Send + Sync + 'static { ) -> BoxResultFuture<(), CollaborateError>; } -pub trait RevisionSyncObject: Send + Sync + 'static { - fn id(&self) -> &str; - fn compose(&mut self, other: &Operations) -> Result<(), CollaborateError>; - fn transform(&self, other: &Operations) -> Result<(Operations, Operations), CollaborateError>; - fn to_json(&self) -> String; - fn set_delta(&mut self, new_delta: Operations); +pub trait RevisionSyncObject: Send + Sync + 'static { + fn object_id(&self) -> &str; + + fn object_json(&self) -> String; + + fn compose(&mut self, other: &RevisionOperations) -> Result<(), CollaborateError>; + + fn transform( + &self, + other: &RevisionOperations, + ) -> Result<(RevisionOperations, RevisionOperations), CollaborateError>; + + fn set_operations(&mut self, operations: RevisionOperations); } pub enum RevisionSyncResponse { @@ -57,25 +72,25 @@ pub enum RevisionSyncResponse { Ack(ServerRevisionWSData), } -pub struct RevisionSynchronizer { +pub struct RevisionSynchronizer { object_id: String, rev_id: AtomicI64, - object: Arc>>, + object: Arc>>, persistence: Arc, } -impl RevisionSynchronizer +impl RevisionSynchronizer where - T: OperationAttributes + DeserializeOwned + serde::Serialize + 'static, + Attribute: OperationAttributes + DeserializeOwned + serde::Serialize + 'static, { - pub fn new(rev_id: i64, sync_object: S, persistence: P) -> RevisionSynchronizer + pub fn new(rev_id: i64, sync_object: S, persistence: P) -> RevisionSynchronizer where - S: RevisionSyncObject, + S: RevisionSyncObject, P: RevisionSyncPersistence, { let object = Arc::new(RwLock::new(sync_object)); let persistence = Arc::new(persistence); - let object_id = object.read().id().to_owned(); + let object_id = object.read().object_id().to_owned(); RevisionSynchronizer { object_id, rev_id: AtomicI64::new(rev_id), @@ -117,7 +132,7 @@ where } let _ = self.persistence.save_revisions(repeated_revision).await?; } else { - // The server delta is outdated, pull the missing revision from the client. + // The server ops is outdated, pull the missing revision from the client. let range = RevisionRange { start: server_rev_id, end: first_revision.rev_id, @@ -131,9 +146,9 @@ where tracing::trace!("Applied {} revision rev_id is the same as cur_rev_id", self.object_id); } Ordering::Greater => { - // The client delta is outdated. Transform the client revision delta and then - // send the prime delta to the client. Client should compose the this prime - // delta. + // The client ops is outdated. Transform the client revision ops and then + // send the prime ops to the client. Client should compose the this prime + // ops. let from_rev_id = first_revision.rev_id; let to_rev_id = server_base_rev_id; let _ = self.push_revisions_to_user(user, from_rev_id, to_rev_id).await; @@ -153,9 +168,9 @@ where } Ordering::Equal => tracing::trace!("{} is up to date.", object_id), Ordering::Greater => { - // The client delta is outdated. Transform the client revision delta and then - // send the prime delta to the client. Client should compose the this prime - // delta. + // The client ops is outdated. Transform the client revision ops and then + // send the prime ops to the client. Client should compose the this prime + // ops. let from_rev_id = client_rev_id; let to_rev_id = server_rev_id; tracing::trace!("Push revisions to user"); @@ -171,40 +186,43 @@ where tracing::Span::current().record("object_id", &object_id.as_str()); let revisions: Vec = repeated_revision.clone().into_inner(); let (_, rev_id) = pair_rev_id_from_revision_pbs(&revisions); - let delta = make_delta_from_revision_pb(revisions)?; + let operations = make_operations_from_revisions(revisions)?; let _ = self.persistence.reset_object(&object_id, repeated_revision).await?; - self.object.write().set_delta(delta); + self.object.write().set_operations(operations); let _ = self.rev_id.fetch_update(SeqCst, SeqCst, |_e| Some(rev_id)); Ok(()) } pub fn object_json(&self) -> String { - self.object.read().to_json() + self.object.read().object_json() } fn compose_revision(&self, revision: &Revision) -> Result<(), CollaborateError> { - let delta = Operations::::from_bytes(&revision.delta_data)?; - let _ = self.compose_delta(delta)?; + let operations = RevisionOperations::::from_bytes(&revision.bytes)?; + let _ = self.compose_operations(operations)?; let _ = self.rev_id.fetch_update(SeqCst, SeqCst, |_e| Some(revision.rev_id)); Ok(()) } #[tracing::instrument(level = "debug", skip(self, revision))] - fn transform_revision(&self, revision: &RevisionPB) -> Result<(Operations, Operations), CollaborateError> { - let cli_delta = Operations::::from_bytes(&revision.delta_data)?; - let result = self.object.read().transform(&cli_delta)?; + fn transform_revision( + &self, + revision: &RevisionPB, + ) -> Result<(RevisionOperations, RevisionOperations), CollaborateError> { + let client_operations = RevisionOperations::::from_bytes(&revision.bytes)?; + let result = self.object.read().transform(&client_operations)?; Ok(result) } - fn compose_delta(&self, delta: Operations) -> Result<(), CollaborateError> { - if delta.is_empty() { - log::warn!("Composed delta is empty"); + fn compose_operations(&self, operations: RevisionOperations) -> Result<(), CollaborateError> { + if operations.is_empty() { + log::warn!("Composed operations is empty"); } match self.object.try_write_for(Duration::from_millis(300)) { None => log::error!("Failed to acquire write lock of object"), Some(mut write_guard) => { - let _ = write_guard.compose(&delta)?; + let _ = write_guard.compose(&operations)?; } } Ok(()) diff --git a/shared-lib/flowy-sync/src/util.rs b/shared-lib/flowy-sync/src/util.rs index c3a9a914a5..43c06823fa 100644 --- a/shared-lib/flowy-sync/src/util.rs +++ b/shared-lib/flowy-sync/src/util.rs @@ -1,16 +1,17 @@ +use crate::server_folder::FolderOperations; use crate::{ entities::{ - folder::{FolderDelta, FolderInfo}, + folder::FolderInfo, revision::{RepeatedRevision, Revision}, text_block::DocumentPB, }, errors::{CollaborateError, CollaborateResult}, }; use dissimilar::Chunk; -use lib_ot::core::{Delta, EmptyAttributes, OTString, OperationAttributes, OperationBuilder}; +use lib_ot::core::{OTString, OperationAttributes, OperationBuilder}; use lib_ot::{ - core::{OperationTransform, Operations, NEW_LINE, WHITESPACE}, - text_delta::TextDelta, + core::{DeltaOperations, OperationTransform, NEW_LINE, WHITESPACE}, + text_delta::TextOperations, }; use serde::de::DeserializeOwned; use std::sync::atomic::{AtomicI64, Ordering::SeqCst}; @@ -62,42 +63,24 @@ impl RevIdCounter { } #[tracing::instrument(level = "trace", skip(revisions), err)] -pub fn make_delta_from_revisions(revisions: Vec) -> CollaborateResult> +pub fn make_operations_from_revisions(revisions: Vec) -> CollaborateResult> where T: OperationAttributes + DeserializeOwned, { - let mut delta = Operations::::new(); + let mut new_operations = DeltaOperations::::new(); for revision in revisions { - if revision.delta_data.is_empty() { + if revision.bytes.is_empty() { tracing::warn!("revision delta_data is empty"); + continue; } - let revision_delta = Operations::::from_bytes(revision.delta_data).map_err(|e| { + let operations = DeltaOperations::::from_bytes(revision.bytes).map_err(|e| { let err_msg = format!("Deserialize remote revision failed: {:?}", e); CollaborateError::internal().context(err_msg) })?; - delta = delta.compose(&revision_delta)?; + new_operations = new_operations.compose(&operations)?; } - Ok(delta) -} - -pub fn make_text_delta_from_revisions(revisions: Vec) -> CollaborateResult { - make_delta_from_revisions::(revisions) -} - -pub fn make_delta_from_revision_pb(revisions: Vec) -> CollaborateResult> -where - T: OperationAttributes + DeserializeOwned, -{ - let mut new_delta = Operations::::new(); - for revision in revisions { - let delta = Operations::::from_bytes(revision.delta_data).map_err(|e| { - let err_msg = format!("Deserialize remote revision failed: {:?}", e); - CollaborateError::internal().context(err_msg) - })?; - new_delta = new_delta.compose(&delta)?; - } - Ok(new_delta) + Ok(new_operations) } pub fn pair_rev_id_from_revision_pbs(revisions: &[Revision]) -> (i64, i64) { @@ -140,16 +123,16 @@ pub fn make_folder_from_revisions_pb( return Ok(None); } - let mut folder_delta = FolderDelta::new(); + let mut folder_delta = FolderOperations::new(); let mut base_rev_id = 0; let mut rev_id = 0; for revision in revisions { base_rev_id = revision.base_rev_id; rev_id = revision.rev_id; - if revision.delta_data.is_empty() { + if revision.bytes.is_empty() { tracing::warn!("revision delta_data is empty"); } - let delta = FolderDelta::from_bytes(revision.delta_data)?; + let delta = FolderOperations::from_bytes(revision.bytes)?; folder_delta = folder_delta.compose(&delta)?; } @@ -172,18 +155,18 @@ pub fn make_document_from_revision_pbs( return Ok(None); } - let mut delta = TextDelta::new(); + let mut delta = TextOperations::new(); let mut base_rev_id = 0; let mut rev_id = 0; for revision in revisions { base_rev_id = revision.base_rev_id; rev_id = revision.rev_id; - if revision.delta_data.is_empty() { + if revision.bytes.is_empty() { tracing::warn!("revision delta_data is empty"); } - let new_delta = TextDelta::from_bytes(revision.delta_data)?; + let new_delta = TextOperations::from_bytes(revision.bytes)?; delta = delta.compose(&new_delta)?; } @@ -206,7 +189,7 @@ pub fn rev_id_from_str(s: &str) -> Result { Ok(rev_id) } -pub fn cal_diff(old: String, new: String) -> Option> { +pub fn cal_diff(old: String, new: String) -> Option> { let chunks = dissimilar::diff(&old, &new); let mut delta_builder = OperationBuilder::::new(); for chunk in &chunks { diff --git a/shared-lib/lib-ot/src/core/attributes/attribute.rs b/shared-lib/lib-ot/src/core/attributes/attribute.rs index 119be9fcb7..cdbf7c44e1 100644 --- a/shared-lib/lib-ot/src/core/attributes/attribute.rs +++ b/shared-lib/lib-ot/src/core/attributes/attribute.rs @@ -5,8 +5,6 @@ use std::collections::HashMap; use std::fmt; use std::fmt::Display; -pub type AttributeMap = HashMap; - #[derive(Debug, Clone)] pub struct AttributeEntry { pub key: AttributeKey, @@ -20,37 +18,37 @@ impl AttributeEntry { } } -impl std::convert::From for Attributes { +impl std::convert::From for AttributeHashMap { fn from(entry: AttributeEntry) -> Self { - let mut attributes = Attributes::new(); + let mut attributes = AttributeHashMap::new(); attributes.insert_entry(entry); attributes } } #[derive(Default, Clone, Serialize, Deserialize, Eq, PartialEq, Debug)] -pub struct Attributes(AttributeMap); +pub struct AttributeHashMap(HashMap); -impl std::ops::Deref for Attributes { - type Target = AttributeMap; +impl std::ops::Deref for AttributeHashMap { + type Target = HashMap; fn deref(&self) -> &Self::Target { &self.0 } } -impl std::ops::DerefMut for Attributes { +impl std::ops::DerefMut for AttributeHashMap { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } } -impl Attributes { - pub fn new() -> Attributes { - Attributes(HashMap::new()) +impl AttributeHashMap { + pub fn new() -> AttributeHashMap { + AttributeHashMap(HashMap::new()) } - pub fn from_value(attribute_map: AttributeMap) -> Self { + pub fn from_value(attribute_map: HashMap) -> Self { Self(attribute_map) } @@ -91,7 +89,7 @@ impl Attributes { /// Create a new key/value map by constructing new attributes from the other /// if it's not None and replace the key/value with self key/value. - pub fn merge(&mut self, other: Option) { + pub fn merge(&mut self, other: Option) { if other.is_none() { return; } @@ -108,7 +106,7 @@ impl Attributes { } } -impl Display for Attributes { +impl Display for AttributeHashMap { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { for (key, value) in self.0.iter() { let _ = f.write_str(&format!("{:?}:{:?}", key, value))?; @@ -117,21 +115,21 @@ impl Display for Attributes { } } -impl OperationAttributes for Attributes { +impl OperationAttributes for AttributeHashMap { fn is_empty(&self) -> bool { self.is_empty() } - fn remove_empty(&mut self) { + fn remove(&mut self) { self.retain(|_, v| v.value.is_some()); } - fn extend_other(&mut self, other: Self) { + fn extend(&mut self, other: Self) { self.0.extend(other.0); } } -impl OperationTransform for Attributes { +impl OperationTransform for AttributeHashMap { fn compose(&self, other: &Self) -> Result where Self: Sized, @@ -145,25 +143,27 @@ impl OperationTransform for Attributes { where Self: Sized, { - let a = self.iter().fold(Attributes::new(), |mut new_attributes, (k, v)| { + let a = self.iter().fold(AttributeHashMap::new(), |mut new_attributes, (k, v)| { if !other.contains_key(k) { new_attributes.insert(k.clone(), v.clone()); } new_attributes }); - let b = other.iter().fold(Attributes::new(), |mut new_attributes, (k, v)| { - if !self.contains_key(k) { - new_attributes.insert(k.clone(), v.clone()); - } - new_attributes - }); + let b = other + .iter() + .fold(AttributeHashMap::new(), |mut new_attributes, (k, v)| { + if !self.contains_key(k) { + new_attributes.insert(k.clone(), v.clone()); + } + new_attributes + }); Ok((a, b)) } fn invert(&self, other: &Self) -> Self { - let base_inverted = other.iter().fold(Attributes::new(), |mut attributes, (k, v)| { + let base_inverted = other.iter().fold(AttributeHashMap::new(), |mut attributes, (k, v)| { if other.get(k) != self.get(k) && self.contains_key(k) { attributes.insert(k.clone(), v.clone()); } @@ -275,7 +275,7 @@ impl std::convert::From for AttributeValue { #[derive(Default)] pub struct AttributeBuilder { - attributes: Attributes, + attributes: AttributeHashMap, } impl AttributeBuilder { @@ -298,7 +298,7 @@ impl AttributeBuilder { self } - pub fn build(self) -> Attributes { + pub fn build(self) -> AttributeHashMap { self.attributes } } diff --git a/shared-lib/lib-ot/src/core/delta/builder.rs b/shared-lib/lib-ot/src/core/delta/builder.rs index e00cab532e..624be9b287 100644 --- a/shared-lib/lib-ot/src/core/delta/builder.rs +++ b/shared-lib/lib-ot/src/core/delta/builder.rs @@ -1,6 +1,6 @@ use crate::core::delta::operation::OperationAttributes; -use crate::core::delta::{trim, Operations}; -use crate::core::Operation; +use crate::core::delta::{trim, DeltaOperations}; +use crate::core::DeltaOperation; /// A builder for creating new [Operations] objects. /// @@ -17,7 +17,7 @@ use crate::core::Operation; /// assert_eq!(delta.content().unwrap(), "AppFlowy"); /// ``` pub struct OperationBuilder { - delta: Operations, + delta: DeltaOperations, } impl std::default::Default for OperationBuilder @@ -26,7 +26,7 @@ where { fn default() -> Self { Self { - delta: Operations::new(), + delta: DeltaOperations::new(), } } } @@ -39,7 +39,7 @@ where OperationBuilder::default() } - pub fn from_operations(operations: Vec>) -> Operations { + pub fn from_operations(operations: Vec>) -> DeltaOperations { let mut delta = OperationBuilder::default().build(); operations.into_iter().for_each(|operation| { delta.add(operation); @@ -52,10 +52,10 @@ where /// # Examples /// /// ``` - /// use lib_ot::text_delta::{BuildInTextAttribute, TextDelta, TextDeltaBuilder}; + /// use lib_ot::text_delta::{BuildInTextAttribute, TextOperations, TextOperationBuilder}; /// /// let mut attribute = BuildInTextAttribute::Bold(true); - /// let delta = TextDeltaBuilder::new().retain_with_attributes(7, attribute.into()).build(); + /// let delta = TextOperationBuilder::new().retain_with_attributes(7, attribute.into()).build(); /// /// assert_eq!(delta.json_str(), r#"[{"retain":7,"attributes":{"bold":true}}]"#); /// ``` @@ -111,14 +111,14 @@ where /// /// ``` /// use lib_ot::core::{OperationTransform, DeltaBuilder}; - /// use lib_ot::text_delta::{BuildInTextAttribute, TextDeltaBuilder}; + /// use lib_ot::text_delta::{BuildInTextAttribute, TextOperationBuilder}; /// let delta = DeltaBuilder::new() /// .retain(3) /// .trim() /// .build(); /// assert_eq!(delta.ops.len(), 0); /// - /// let delta = TextDeltaBuilder::new() + /// let delta = TextOperationBuilder::new() /// .retain_with_attributes(3, BuildInTextAttribute::Bold(true).into()) /// .trim() /// .build(); @@ -130,7 +130,7 @@ where } /// Builds the `Delta` - pub fn build(self) -> Operations { + pub fn build(self) -> DeltaOperations { self.delta } } diff --git a/shared-lib/lib-ot/src/core/delta/cursor.rs b/shared-lib/lib-ot/src/core/delta/cursor.rs index e7e41d80f2..de2ae4304e 100644 --- a/shared-lib/lib-ot/src/core/delta/cursor.rs +++ b/shared-lib/lib-ot/src/core/delta/cursor.rs @@ -1,6 +1,6 @@ #![allow(clippy::while_let_on_iterator)] -use crate::core::delta::operation::{Operation, OperationAttributes}; -use crate::core::delta::Operations; +use crate::core::delta::operation::{DeltaOperation, OperationAttributes}; +use crate::core::delta::DeltaOperations; use crate::core::interval::Interval; use crate::errors::{ErrorBuilder, OTError, OTErrorCode}; use std::{cmp::min, iter::Enumerate, slice::Iter}; @@ -8,13 +8,13 @@ use std::{cmp::min, iter::Enumerate, slice::Iter}; /// A [OperationsCursor] is used to iterate the delta and return the corresponding delta. #[derive(Debug)] pub struct OperationsCursor<'a, T: OperationAttributes> { - pub(crate) delta: &'a Operations, + pub(crate) delta: &'a DeltaOperations, pub(crate) origin_iv: Interval, pub(crate) consume_iv: Interval, pub(crate) consume_count: usize, pub(crate) op_offset: usize, - iter: Enumerate>>, - next_op: Option>, + iter: Enumerate>>, + next_op: Option>, } impl<'a, T> OperationsCursor<'a, T> @@ -29,19 +29,19 @@ where /// # Examples /// /// ``` - /// use lib_ot::core::{OperationsCursor, OperationIterator, Interval, Operation}; - /// use lib_ot::text_delta::TextDelta; - /// let mut delta = TextDelta::default(); - /// delta.add(Operation::insert("123")); - /// delta.add(Operation::insert("4")); + /// use lib_ot::core::{OperationsCursor, OperationIterator, Interval, DeltaOperation}; + /// use lib_ot::text_delta::TextOperations; + /// let mut delta = TextOperations::default(); + /// delta.add(DeltaOperation::insert("123")); + /// delta.add(DeltaOperation::insert("4")); /// /// let mut cursor = OperationsCursor::new(&delta, Interval::new(0, 3)); /// assert_eq!(cursor.next_iv(), Interval::new(0,3)); - /// assert_eq!(cursor.next_with_len(Some(2)).unwrap(), Operation::insert("12")); - /// assert_eq!(cursor.get_next_op().unwrap(), Operation::insert("3")); + /// assert_eq!(cursor.next_with_len(Some(2)).unwrap(), DeltaOperation::insert("12")); + /// assert_eq!(cursor.get_next_op().unwrap(), DeltaOperation::insert("3")); /// assert_eq!(cursor.get_next_op(), None); /// ``` - pub fn new(delta: &'a Operations, interval: Interval) -> OperationsCursor<'a, T> { + pub fn new(delta: &'a DeltaOperations, interval: Interval) -> OperationsCursor<'a, T> { // debug_assert!(interval.start <= delta.target_len); let mut cursor = Self { delta, @@ -62,12 +62,12 @@ where } /// Returns the next operation - pub fn get_next_op(&mut self) -> Option> { + pub fn get_next_op(&mut self) -> Option> { self.next_with_len(None) } /// Returns the reference of the next operation - pub fn next_op(&self) -> Option<&Operation> { + pub fn next_op(&self) -> Option<&DeltaOperation> { let mut next_op = self.next_op.as_ref(); if next_op.is_none() { let mut offset = 0; @@ -87,7 +87,7 @@ where /// * `expected_len`: Return the next operation with the specified length. /// /// - pub fn next_with_len(&mut self, expected_len: Option) -> Option> { + pub fn next_with_len(&mut self, expected_len: Option) -> Option> { let mut find_op = None; let holder = self.next_op.clone(); let mut next_op = holder.as_ref(); @@ -182,7 +182,7 @@ where } } -fn find_next<'a, T>(cursor: &mut OperationsCursor<'a, T>) -> Option<&'a Operation> +fn find_next<'a, T>(cursor: &mut OperationsCursor<'a, T>) -> Option<&'a DeltaOperation> where T: OperationAttributes, { diff --git a/shared-lib/lib-ot/src/core/delta/iterator.rs b/shared-lib/lib-ot/src/core/delta/iterator.rs index 9063a67bfd..bd4d3ee55a 100644 --- a/shared-lib/lib-ot/src/core/delta/iterator.rs +++ b/shared-lib/lib-ot/src/core/delta/iterator.rs @@ -1,8 +1,8 @@ use super::cursor::*; -use crate::core::delta::operation::{Operation, OperationAttributes}; -use crate::core::delta::{Operations, NEW_LINE}; +use crate::core::delta::operation::{DeltaOperation, OperationAttributes}; +use crate::core::delta::{DeltaOperations, NEW_LINE}; use crate::core::interval::Interval; -use crate::core::Attributes; +use crate::core::AttributeHashMap; use std::ops::{Deref, DerefMut}; @@ -14,19 +14,19 @@ pub(crate) const MAX_IV_LEN: usize = i32::MAX as usize; /// You could check [this](https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/architecture/backend/delta) out for more information. /// /// ``` -/// use lib_ot::core::{OperationIterator, Interval, Operation}; -/// use lib_ot::text_delta::TextDelta; -/// let mut delta = TextDelta::default(); -/// delta.add(Operation::insert("123")); -/// delta.add(Operation::insert("4")); +/// use lib_ot::core::{OperationIterator, Interval, DeltaOperation}; +/// use lib_ot::text_delta::TextOperations; +/// let mut delta = TextOperations::default(); +/// delta.add(DeltaOperation::insert("123")); +/// delta.add(DeltaOperation::insert("4")); /// assert_eq!( /// OperationIterator::from_interval(&delta, Interval::new(0, 2)).ops(), -/// vec![Operation::insert("12")] +/// vec![DeltaOperation::insert("12")] /// ); /// /// assert_eq!( /// OperationIterator::from_interval(&delta, Interval::new(1, 3)).ops(), -/// vec![Operation::insert("23")] +/// vec![DeltaOperation::insert("23")] /// ); /// ``` pub struct OperationIterator<'a, T: OperationAttributes> { @@ -37,24 +37,24 @@ impl<'a, T> OperationIterator<'a, T> where T: OperationAttributes, { - pub fn new(delta: &'a Operations) -> Self { + pub fn new(delta: &'a DeltaOperations) -> Self { let interval = Interval::new(0, MAX_IV_LEN); Self::from_interval(delta, interval) } - pub fn from_offset(delta: &'a Operations, offset: usize) -> Self { + pub fn from_offset(delta: &'a DeltaOperations, offset: usize) -> Self { let interval = Interval::new(0, MAX_IV_LEN); let mut iter = Self::from_interval(delta, interval); iter.seek::(offset); iter } - pub fn from_interval(delta: &'a Operations, interval: Interval) -> Self { + pub fn from_interval(delta: &'a DeltaOperations, interval: Interval) -> Self { let cursor = OperationsCursor::new(delta, interval); Self { cursor } } - pub fn ops(&mut self) -> Vec> { + pub fn ops(&mut self) -> Vec> { self.collect::>() } @@ -67,16 +67,16 @@ where } } - pub fn next_op(&mut self) -> Option> { + pub fn next_op(&mut self) -> Option> { self.cursor.get_next_op() } - pub fn next_op_with_len(&mut self, len: usize) -> Option> { + pub fn next_op_with_len(&mut self, len: usize) -> Option> { self.cursor.next_with_len(Some(len)) } // find next op contains NEW_LINE - pub fn next_op_with_newline(&mut self) -> Option<(Operation, usize)> { + pub fn next_op_with_newline(&mut self) -> Option<(DeltaOperation, usize)> { let mut offset = 0; while self.has_next() { if let Some(op) = self.next_op() { @@ -127,13 +127,13 @@ impl<'a, T> Iterator for OperationIterator<'a, T> where T: OperationAttributes, { - type Item = Operation; + type Item = DeltaOperation; fn next(&mut self) -> Option { self.next_op() } } -pub fn is_empty_line_at_index(delta: &Operations, index: usize) -> bool { +pub fn is_empty_line_at_index(delta: &DeltaOperations, index: usize) -> bool { let mut iter = OperationIterator::new(delta); let (prev, next) = (iter.next_op_with_len(index), iter.next_op()); if prev.is_none() { @@ -157,12 +157,12 @@ impl<'a, T> AttributesIter<'a, T> where T: OperationAttributes, { - pub fn new(delta: &'a Operations) -> Self { + pub fn new(delta: &'a DeltaOperations) -> Self { let interval = Interval::new(0, usize::MAX); Self::from_interval(delta, interval) } - pub fn from_interval(delta: &'a Operations, interval: Interval) -> Self { + pub fn from_interval(delta: &'a DeltaOperations, interval: Interval) -> Self { let delta_iter = OperationIterator::from_interval(delta, interval); Self { delta_iter } } @@ -207,16 +207,16 @@ where let mut attributes = T::default(); match next_op.unwrap() { - Operation::::Delete(_n) => {} - Operation::::Retain(retain) => { + DeltaOperation::::Delete(_n) => {} + DeltaOperation::::Retain(retain) => { tracing::trace!("extend retain attributes with {} ", &retain.attributes); - attributes.extend_other(retain.attributes.clone()); + attributes.extend(retain.attributes.clone()); length = retain.n; } - Operation::::Insert(insert) => { + DeltaOperation::::Insert(insert) => { tracing::trace!("extend insert attributes with {} ", &insert.attributes); - attributes.extend_other(insert.attributes.clone()); + attributes.extend(insert.attributes.clone()); length = insert.utf16_size(); } } @@ -235,7 +235,7 @@ pub enum OpNewline { } impl OpNewline { - pub fn parse(op: &Operation) -> OpNewline { + pub fn parse(op: &DeltaOperation) -> OpNewline { let s = op.get_data(); if s == NEW_LINE { diff --git a/shared-lib/lib-ot/src/core/delta/operation/builder.rs b/shared-lib/lib-ot/src/core/delta/operation/builder.rs index 864bc39775..bdea0e80ae 100644 --- a/shared-lib/lib-ot/src/core/delta/operation/builder.rs +++ b/shared-lib/lib-ot/src/core/delta/operation/builder.rs @@ -1,11 +1,11 @@ -use crate::core::delta::operation::{EmptyAttributes, Operation, OperationAttributes}; +use crate::core::delta::operation::{DeltaOperation, EmptyAttributes, OperationAttributes}; // pub type RichTextOpBuilder = OperationsBuilder; pub type PlainTextOpBuilder = OperationsBuilder; #[derive(Default)] pub struct OperationsBuilder { - operations: Vec>, + operations: Vec>, } impl OperationsBuilder @@ -17,35 +17,35 @@ where } pub fn retain_with_attributes(mut self, n: usize, attributes: T) -> OperationsBuilder { - let retain = Operation::retain_with_attributes(n, attributes); + let retain = DeltaOperation::retain_with_attributes(n, attributes); self.operations.push(retain); self } pub fn retain(mut self, n: usize) -> OperationsBuilder { - let retain = Operation::retain(n); + let retain = DeltaOperation::retain(n); self.operations.push(retain); self } pub fn delete(mut self, n: usize) -> OperationsBuilder { - self.operations.push(Operation::Delete(n)); + self.operations.push(DeltaOperation::Delete(n)); self } pub fn insert_with_attributes(mut self, s: &str, attributes: T) -> OperationsBuilder { - let insert = Operation::insert_with_attributes(s, attributes); + let insert = DeltaOperation::insert_with_attributes(s, attributes); self.operations.push(insert); self } pub fn insert(mut self, s: &str) -> OperationsBuilder { - let insert = Operation::insert(s); + let insert = DeltaOperation::insert(s); self.operations.push(insert); self } - pub fn build(self) -> Vec> { + pub fn build(self) -> Vec> { self.operations } } diff --git a/shared-lib/lib-ot/src/core/delta/operation/operation.rs b/shared-lib/lib-ot/src/core/delta/operation/operation.rs index 23c15b13c6..19efd022b5 100644 --- a/shared-lib/lib-ot/src/core/delta/operation/operation.rs +++ b/shared-lib/lib-ot/src/core/delta/operation/operation.rs @@ -75,17 +75,13 @@ pub trait OperationAttributes: Default + Display + Eq + PartialEq + Clone + Debu true } - /// Remove the empty attribute which value is None. - fn remove_empty(&mut self) { - // Do nothing - } + /// Remove the attribute which value is None. + fn remove(&mut self) {} - fn extend_other(&mut self, _other: Self) { - // Do nothing - } + fn extend(&mut self, _other: Self) {} } -/// [Operation] consists of three types. +/// [DeltaOperation] consists of three types. /// * Delete /// * Retain /// * Insert @@ -96,13 +92,13 @@ pub trait OperationAttributes: Default + Display + Eq + PartialEq + Clone + Debu /// to json string. You could check out the operation_serde.rs for more information. /// #[derive(Debug, Clone, Eq, PartialEq)] -pub enum Operation { +pub enum DeltaOperation { Delete(usize), Retain(Retain), Insert(Insert), } -impl Operation +impl DeltaOperation where T: OperationAttributes, { @@ -142,25 +138,25 @@ where /// Return the String if the operation is [Insert] operation, otherwise return the empty string. pub fn get_data(&self) -> &str { match self { - Operation::Delete(_) => "", - Operation::Retain(_) => "", - Operation::Insert(insert) => &insert.s, + DeltaOperation::Delete(_) => "", + DeltaOperation::Retain(_) => "", + DeltaOperation::Insert(insert) => &insert.s, } } pub fn get_attributes(&self) -> T { match self { - Operation::Delete(_) => T::default(), - Operation::Retain(retain) => retain.attributes.clone(), - Operation::Insert(insert) => insert.attributes.clone(), + DeltaOperation::Delete(_) => T::default(), + DeltaOperation::Retain(retain) => retain.attributes.clone(), + DeltaOperation::Insert(insert) => insert.attributes.clone(), } } pub fn set_attributes(&mut self, attributes: T) { match self { - Operation::Delete(_) => log::error!("Delete should not contains attributes"), - Operation::Retain(retain) => retain.attributes = attributes, - Operation::Insert(insert) => insert.attributes = attributes, + DeltaOperation::Delete(_) => log::error!("Delete should not contains attributes"), + DeltaOperation::Retain(retain) => retain.attributes = attributes, + DeltaOperation::Insert(insert) => insert.attributes = attributes, } } @@ -170,9 +166,9 @@ where pub fn len(&self) -> usize { match self { - Operation::Delete(n) => *n, - Operation::Retain(r) => r.n, - Operation::Insert(i) => i.utf16_size(), + DeltaOperation::Delete(n) => *n, + DeltaOperation::Retain(r) => r.n, + DeltaOperation::Insert(i) => i.utf16_size(), } } @@ -181,26 +177,26 @@ where } #[allow(dead_code)] - pub fn split(&self, index: usize) -> (Option>, Option>) { + pub fn split(&self, index: usize) -> (Option>, Option>) { debug_assert!(index < self.len()); let left; let right; match self { - Operation::Delete(n) => { - left = Some(Operation::::delete(index)); - right = Some(Operation::::delete(*n - index)); + DeltaOperation::Delete(n) => { + left = Some(DeltaOperation::::delete(index)); + right = Some(DeltaOperation::::delete(*n - index)); } - Operation::Retain(retain) => { - left = Some(Operation::::delete(index)); - right = Some(Operation::::delete(retain.n - index)); + DeltaOperation::Retain(retain) => { + left = Some(DeltaOperation::::delete(index)); + right = Some(DeltaOperation::::delete(retain.n - index)); } - Operation::Insert(insert) => { + DeltaOperation::Insert(insert) => { let attributes = self.get_attributes(); - left = Some(Operation::::insert_with_attributes( + left = Some(DeltaOperation::::insert_with_attributes( &insert.s[0..index], attributes.clone(), )); - right = Some(Operation::::insert_with_attributes( + right = Some(DeltaOperation::::insert_with_attributes( &insert.s[index..insert.utf16_size()], attributes, )); @@ -218,27 +214,27 @@ where /// # Examples /// /// ``` - /// use lib_ot::core::{Interval, Operation, EmptyAttributes}; - /// let operation = Operation::::insert("1234"); + /// use lib_ot::core::{Interval, DeltaOperation, EmptyAttributes}; + /// let operation = DeltaOperation::::insert("1234"); /// /// let op1 = operation.shrink(Interval::new(0,3)).unwrap(); - /// assert_eq!(op1 , Operation::insert("123")); + /// assert_eq!(op1 , DeltaOperation::insert("123")); /// /// let op2= operation.shrink(Interval::new(3,4)).unwrap(); - /// assert_eq!(op2, Operation::insert("4")); + /// assert_eq!(op2, DeltaOperation::insert("4")); /// ``` - pub fn shrink(&self, interval: Interval) -> Option> { + pub fn shrink(&self, interval: Interval) -> Option> { let op = match self { - Operation::Delete(n) => Operation::delete(min(*n, interval.size())), - Operation::Retain(retain) => { - Operation::retain_with_attributes(min(retain.n, interval.size()), retain.attributes.clone()) + DeltaOperation::Delete(n) => DeltaOperation::delete(min(*n, interval.size())), + DeltaOperation::Retain(retain) => { + DeltaOperation::retain_with_attributes(min(retain.n, interval.size()), retain.attributes.clone()) } - Operation::Insert(insert) => { + DeltaOperation::Insert(insert) => { if interval.start > insert.utf16_size() { - Operation::insert("") + DeltaOperation::insert("") } else { let s = insert.s.sub_str(interval).unwrap_or_else(|| "".to_owned()); - Operation::insert_with_attributes(&s, insert.attributes.clone()) + DeltaOperation::insert_with_attributes(&s, insert.attributes.clone()) } } }; @@ -250,21 +246,21 @@ where } pub fn is_delete(&self) -> bool { - if let Operation::Delete(_) = self { + if let DeltaOperation::Delete(_) = self { return true; } false } pub fn is_insert(&self) -> bool { - if let Operation::Insert(_) = self { + if let DeltaOperation::Insert(_) = self { return true; } false } pub fn is_retain(&self) -> bool { - if let Operation::Retain(_) = self { + if let DeltaOperation::Retain(_) = self { return true; } false @@ -272,27 +268,27 @@ where pub fn is_plain(&self) -> bool { match self { - Operation::Delete(_) => true, - Operation::Retain(retain) => retain.is_plain(), - Operation::Insert(insert) => insert.is_plain(), + DeltaOperation::Delete(_) => true, + DeltaOperation::Retain(retain) => retain.is_plain(), + DeltaOperation::Insert(insert) => insert.is_plain(), } } } -impl fmt::Display for Operation +impl fmt::Display for DeltaOperation where T: OperationAttributes, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str("{")?; match self { - Operation::Delete(n) => { + DeltaOperation::Delete(n) => { f.write_fmt(format_args!("delete: {}", n))?; } - Operation::Retain(r) => { + DeltaOperation::Retain(r) => { f.write_fmt(format_args!("{}", r))?; } - Operation::Insert(i) => { + DeltaOperation::Insert(i) => { f.write_fmt(format_args!("{}", i))?; } } @@ -324,7 +320,7 @@ impl Retain where T: OperationAttributes, { - pub fn merge_or_new(&mut self, n: usize, attributes: T) -> Option> { + pub fn merge_or_new(&mut self, n: usize, attributes: T) -> Option> { // tracing::trace!( // "merge_retain_or_new_op: len: {:?}, l: {} - r: {}", // n, @@ -335,7 +331,7 @@ where self.n += n; None } else { - Some(Operation::retain_with_attributes(n, attributes)) + Some(DeltaOperation::retain_with_attributes(n, attributes)) } } @@ -411,12 +407,12 @@ where self.s.utf16_len() } - pub fn merge_or_new_op(&mut self, s: &str, attributes: T) -> Option> { + pub fn merge_or_new_op(&mut self, s: &str, attributes: T) -> Option> { if self.attributes == attributes { self.s += s; None } else { - Some(Operation::::insert_with_attributes(s, attributes)) + Some(DeltaOperation::::insert_with_attributes(s, attributes)) } } diff --git a/shared-lib/lib-ot/src/core/delta/operation/operation_serde.rs b/shared-lib/lib-ot/src/core/delta/operation/operation_serde.rs index 73d44578ba..ec00b03800 100644 --- a/shared-lib/lib-ot/src/core/delta/operation/operation_serde.rs +++ b/shared-lib/lib-ot/src/core/delta/operation/operation_serde.rs @@ -1,4 +1,4 @@ -use crate::core::delta::operation::{Insert, Operation, OperationAttributes, Retain}; +use crate::core::delta::operation::{DeltaOperation, Insert, OperationAttributes, Retain}; use crate::core::ot_str::OTString; use serde::{ de, @@ -8,7 +8,7 @@ use serde::{ }; use std::{fmt, marker::PhantomData}; -impl Serialize for Operation +impl Serialize for DeltaOperation where T: OperationAttributes + Serialize, { @@ -17,22 +17,22 @@ where S: Serializer, { match self { - Operation::Retain(retain) => retain.serialize(serializer), - Operation::Delete(i) => { + DeltaOperation::Retain(retain) => retain.serialize(serializer), + DeltaOperation::Delete(i) => { let mut map = serializer.serialize_map(Some(1))?; map.serialize_entry("delete", i)?; map.end() } - Operation::Insert(insert) => insert.serialize(serializer), + DeltaOperation::Insert(insert) => insert.serialize(serializer), } } } -impl<'de, T> Deserialize<'de> for Operation +impl<'de, T> Deserialize<'de> for DeltaOperation where T: OperationAttributes + Deserialize<'de>, { - fn deserialize(deserializer: D) -> Result, D::Error> + fn deserialize(deserializer: D) -> Result, D::Error> where D: Deserializer<'de>, { @@ -42,7 +42,7 @@ where where T: OperationAttributes + Deserialize<'de>, { - type Value = Operation; + type Value = DeltaOperation; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("an integer between -2^64 and 2^63 or a string") @@ -61,21 +61,21 @@ where if operation.is_some() { return Err(de::Error::duplicate_field("operation")); } - operation = Some(Operation::::Delete(map.next_value()?)); + operation = Some(DeltaOperation::::Delete(map.next_value()?)); } "retain" => { if operation.is_some() { return Err(de::Error::duplicate_field("operation")); } let i: usize = map.next_value()?; - operation = Some(Operation::::Retain(i.into())); + operation = Some(DeltaOperation::::Retain(i.into())); } "insert" => { if operation.is_some() { return Err(de::Error::duplicate_field("operation")); } let i: String = map.next_value()?; - operation = Some(Operation::::Insert(i.into())); + operation = Some(DeltaOperation::::Insert(i.into())); } "attributes" => { if attributes.is_some() { diff --git a/shared-lib/lib-ot/src/core/delta/ops.rs b/shared-lib/lib-ot/src/core/delta/ops.rs index 29e8e0f5ed..df697f845e 100644 --- a/shared-lib/lib-ot/src/core/delta/ops.rs +++ b/shared-lib/lib-ot/src/core/delta/ops.rs @@ -1,6 +1,6 @@ use crate::errors::{ErrorBuilder, OTError, OTErrorCode}; -use crate::core::delta::operation::{EmptyAttributes, Operation, OperationAttributes, OperationTransform}; +use crate::core::delta::operation::{DeltaOperation, EmptyAttributes, OperationAttributes, OperationTransform}; use crate::core::delta::{OperationIterator, MAX_IV_LEN}; use crate::core::interval::Interval; use crate::core::ot_str::OTString; @@ -15,7 +15,7 @@ use std::{ str::FromStr, }; -pub type Delta = Operations; +pub type Delta = DeltaOperations; pub type DeltaBuilder = OperationBuilder; /// A [Delta] contains list of operations that consists of 'Retain', 'Delete' and 'Insert' operation. @@ -28,8 +28,8 @@ pub type DeltaBuilder = OperationBuilder; /// a JSON string. /// #[derive(Clone, Debug, PartialEq, Eq)] -pub struct Operations { - pub ops: Vec>, +pub struct DeltaOperations { + pub ops: Vec>, /// 'Delete' and 'Retain' operation will update the [utf16_base_len] /// Transforming the other delta, it requires the utf16_base_len must be equal. @@ -40,7 +40,7 @@ pub struct Operations { pub utf16_target_len: usize, } -impl Default for Operations +impl Default for DeltaOperations where T: OperationAttributes, { @@ -53,7 +53,7 @@ where } } -impl fmt::Display for Operations +impl fmt::Display for DeltaOperations where T: OperationAttributes, { @@ -68,12 +68,12 @@ where } } -impl FromIterator> for Operations +impl FromIterator> for DeltaOperations where T: OperationAttributes, { - fn from_iter>>(ops: I) -> Self { - let mut operations = Operations::default(); + fn from_iter>>(ops: I) -> Self { + let mut operations = DeltaOperations::default(); for op in ops { operations.add(op); } @@ -81,7 +81,7 @@ where } } -impl Operations +impl DeltaOperations where T: OperationAttributes, { @@ -99,11 +99,11 @@ where } /// Adding an operation. It will be added in sequence. - pub fn add(&mut self, op: Operation) { + pub fn add(&mut self, op: DeltaOperation) { 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), + DeltaOperation::Delete(i) => self.delete(i), + DeltaOperation::Insert(i) => self.insert(&i.s, i.attributes), + DeltaOperation::Retain(r) => self.retain(r.n, r.attributes), } } @@ -113,10 +113,10 @@ where return; } self.utf16_base_len += n as usize; - if let Some(Operation::Delete(n_last)) = self.ops.last_mut() { + if let Some(DeltaOperation::Delete(n_last)) = self.ops.last_mut() { *n_last += n; } else { - self.ops.push(Operation::delete(n)); + self.ops.push(DeltaOperation::delete(n)); } } @@ -129,20 +129,20 @@ where self.utf16_target_len += s.utf16_len(); let new_last = match self.ops.as_mut_slice() { - [.., Operation::::Insert(insert)] => { + [.., DeltaOperation::::Insert(insert)] => { // insert.merge_or_new_op(&s, attributes) } - [.., Operation::::Insert(pre_insert), Operation::Delete(_)] => { + [.., DeltaOperation::::Insert(pre_insert), DeltaOperation::Delete(_)] => { // pre_insert.merge_or_new_op(&s, attributes) } - [.., op_last @ Operation::::Delete(_)] => { + [.., op_last @ DeltaOperation::::Delete(_)] => { let new_last = op_last.clone(); - *op_last = Operation::::insert_with_attributes(&s, attributes); + *op_last = DeltaOperation::::insert_with_attributes(&s, attributes); Some(new_last) } - _ => Some(Operation::::insert_with_attributes(&s, attributes)), + _ => Some(DeltaOperation::::insert_with_attributes(&s, attributes)), }; match new_last { @@ -159,12 +159,13 @@ where self.utf16_base_len += n as usize; self.utf16_target_len += n as usize; - if let Some(Operation::::Retain(retain)) = self.ops.last_mut() { + if let Some(DeltaOperation::::Retain(retain)) = self.ops.last_mut() { if let Some(new_op) = retain.merge_or_new(n, attributes) { self.ops.push(new_op); } } else { - self.ops.push(Operation::::retain_with_attributes(n, attributes)); + self.ops + .push(DeltaOperation::::retain_with_attributes(n, attributes)); } } @@ -207,17 +208,17 @@ where let code_point_iter = &mut applied_str.utf16_iter(); for op in &self.ops { match &op { - Operation::Retain(retain) => { + DeltaOperation::Retain(retain) => { for c in code_point_iter.take(retain.n as usize) { new_s.push_str(str::from_utf8(c.0).unwrap_or("")); } } - Operation::Delete(delete) => { + DeltaOperation::Delete(delete) => { for _ in 0..*delete { code_point_iter.next(); } } - Operation::Insert(insert) => { + DeltaOperation::Insert(insert) => { new_s += &insert.s; } } @@ -249,22 +250,22 @@ where /// ``` /// pub fn invert_str(&self, inverted_s: &str) -> Self { - let mut inverted = Operations::default(); + let mut inverted = DeltaOperations::default(); let inverted_s: OTString = inverted_s.into(); let code_point_iter = &mut inverted_s.utf16_iter(); for op in &self.ops { match &op { - Operation::Retain(retain) => { + DeltaOperation::Retain(retain) => { inverted.retain(retain.n, T::default()); for _ in 0..retain.n { code_point_iter.next(); } } - Operation::Insert(insert) => { + DeltaOperation::Insert(insert) => { inverted.delete(insert.utf16_size()); } - Operation::Delete(delete) => { + DeltaOperation::Delete(delete) => { let bytes = code_point_iter .take(*delete as usize) .into_iter() @@ -280,7 +281,7 @@ where /// Return true if the delta doesn't contain any [Insert] or [Delete] operations. pub fn is_noop(&self) -> bool { - matches!(self.ops.as_slice(), [] | [Operation::Retain(_)]) + matches!(self.ops.as_slice(), [] | [DeltaOperation::Retain(_)]) } pub fn is_empty(&self) -> bool { @@ -292,7 +293,7 @@ where } } -impl OperationTransform for Operations +impl OperationTransform for DeltaOperations where T: OperationAttributes, { @@ -300,7 +301,7 @@ where where Self: Sized, { - let mut new_delta = Operations::default(); + let mut new_delta = DeltaOperations::default(); let mut iter = OperationIterator::new(self); let mut other_iter = OperationIterator::new(other); @@ -322,25 +323,25 @@ where let op = iter .next_op_with_len(length) - .unwrap_or_else(|| Operation::retain(length)); + .unwrap_or_else(|| DeltaOperation::retain(length)); let other_op = other_iter .next_op_with_len(length) - .unwrap_or_else(|| Operation::retain(length)); + .unwrap_or_else(|| DeltaOperation::retain(length)); // debug_assert_eq!(op.len(), other_op.len(), "Composing delta failed,"); match (&op, &other_op) { - (Operation::Retain(retain), Operation::Retain(other_retain)) => { + (DeltaOperation::Retain(retain), DeltaOperation::Retain(other_retain)) => { let composed_attrs = retain.attributes.compose(&other_retain.attributes)?; - new_delta.add(Operation::retain_with_attributes(retain.n, composed_attrs)) + new_delta.add(DeltaOperation::retain_with_attributes(retain.n, composed_attrs)) } - (Operation::Insert(insert), Operation::Retain(other_retain)) => { + (DeltaOperation::Insert(insert), DeltaOperation::Retain(other_retain)) => { let mut composed_attrs = insert.attributes.compose(&other_retain.attributes)?; - composed_attrs.remove_empty(); - new_delta.add(Operation::insert_with_attributes(op.get_data(), composed_attrs)) + composed_attrs.remove(); + new_delta.add(DeltaOperation::insert_with_attributes(op.get_data(), composed_attrs)) } - (Operation::Retain(_), Operation::Delete(_)) => { + (DeltaOperation::Retain(_), DeltaOperation::Delete(_)) => { new_delta.add(other_op); } (a, b) => { @@ -366,8 +367,8 @@ where .build()); } - let mut a_prime = Operations::default(); - let mut b_prime = Operations::default(); + let mut a_prime = DeltaOperations::default(); + let mut b_prime = DeltaOperations::default(); let mut ops1 = self.ops.iter().cloned(); let mut ops2 = other.ops.iter().cloned(); @@ -377,13 +378,13 @@ where loop { match (&next_op1, &next_op2) { (None, None) => break, - (Some(Operation::Insert(insert)), _) => { + (Some(DeltaOperation::Insert(insert)), _) => { // let composed_attrs = transform_attributes(&next_op1, &next_op2, true); a_prime.insert(&insert.s, insert.attributes.clone()); b_prime.retain(insert.utf16_size(), insert.attributes.clone()); next_op1 = ops1.next(); } - (_, Some(Operation::Insert(o_insert))) => { + (_, Some(DeltaOperation::Insert(o_insert))) => { let composed_attrs = transform_op_attribute(&next_op1, &next_op2)?; a_prime.retain(o_insert.utf16_size(), composed_attrs.clone()); b_prime.insert(&o_insert.s, composed_attrs); @@ -395,13 +396,13 @@ where (_, None) => { return Err(ErrorBuilder::new(OTErrorCode::IncompatibleLength).build()); } - (Some(Operation::Retain(retain)), Some(Operation::Retain(o_retain))) => { + (Some(DeltaOperation::Retain(retain)), Some(DeltaOperation::Retain(o_retain))) => { let composed_attrs = transform_op_attribute(&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(Operation::retain(o_retain.n - retain.n)); + next_op2 = Some(DeltaOperation::retain(o_retain.n - retain.n)); next_op1 = ops1.next(); } Ordering::Equal => { @@ -413,14 +414,14 @@ where Ordering::Greater => { a_prime.retain(o_retain.n, composed_attrs.clone()); b_prime.retain(o_retain.n, composed_attrs.clone()); - next_op1 = Some(Operation::retain(retain.n - o_retain.n)); + next_op1 = Some(DeltaOperation::retain(retain.n - o_retain.n)); next_op2 = ops2.next(); } }; } - (Some(Operation::Delete(i)), Some(Operation::Delete(j))) => match i.cmp(j) { + (Some(DeltaOperation::Delete(i)), Some(DeltaOperation::Delete(j))) => match i.cmp(j) { Ordering::Less => { - next_op2 = Some(Operation::delete(*j - *i)); + next_op2 = Some(DeltaOperation::delete(*j - *i)); next_op1 = ops1.next(); } Ordering::Equal => { @@ -428,15 +429,15 @@ where next_op2 = ops2.next(); } Ordering::Greater => { - next_op1 = Some(Operation::delete(*i - *j)); + next_op1 = Some(DeltaOperation::delete(*i - *j)); next_op2 = ops2.next(); } }, - (Some(Operation::Delete(i)), Some(Operation::Retain(o_retain))) => { + (Some(DeltaOperation::Delete(i)), Some(DeltaOperation::Retain(o_retain))) => { match i.cmp(o_retain) { Ordering::Less => { a_prime.delete(*i); - next_op2 = Some(Operation::retain(o_retain.n - *i)); + next_op2 = Some(DeltaOperation::retain(o_retain.n - *i)); next_op1 = ops1.next(); } Ordering::Equal => { @@ -446,16 +447,16 @@ where } Ordering::Greater => { a_prime.delete(o_retain.n); - next_op1 = Some(Operation::delete(*i - o_retain.n)); + next_op1 = Some(DeltaOperation::delete(*i - o_retain.n)); next_op2 = ops2.next(); } }; } - (Some(Operation::Retain(retain)), Some(Operation::Delete(j))) => { + (Some(DeltaOperation::Retain(retain)), Some(DeltaOperation::Delete(j))) => { match retain.cmp(j) { Ordering::Less => { b_prime.delete(retain.n); - next_op2 = Some(Operation::delete(*j - retain.n)); + next_op2 = Some(DeltaOperation::delete(*j - retain.n)); next_op1 = ops1.next(); } Ordering::Equal => { @@ -465,7 +466,7 @@ where } Ordering::Greater => { b_prime.delete(*j); - next_op1 = Some(Operation::retain(retain.n - *j)); + next_op1 = Some(DeltaOperation::retain(retain.n - *j)); next_op2 = ops2.next(); } }; @@ -476,16 +477,16 @@ where } fn invert(&self, other: &Self) -> Self { - let mut inverted = Operations::default(); + let mut inverted = DeltaOperations::default(); let mut index = 0; for op in &self.ops { let len: usize = op.len() as usize; match op { - Operation::Delete(n) => { + DeltaOperation::Delete(n) => { invert_other(&mut inverted, other, op, index, index + *n); index += len; } - Operation::Retain(_) => { + DeltaOperation::Retain(_) => { match op.has_attribute() { true => invert_other(&mut inverted, other, op, index, index + len), false => { @@ -496,7 +497,7 @@ where } index += len; } - Operation::Insert(_) => { + DeltaOperation::Insert(_) => { // tracing::trace!("invert insert: {} by delete {}", op, len); inverted.delete(len as usize); } @@ -507,7 +508,7 @@ where } /// Removes trailing retain operation with empty attributes, if present. -pub fn trim(delta: &mut Operations) +pub fn trim(delta: &mut DeltaOperations) where T: OperationAttributes, { @@ -519,20 +520,20 @@ where } fn invert_other( - base: &mut Operations, - other: &Operations, - operation: &Operation, + base: &mut DeltaOperations, + other: &DeltaOperations, + operation: &DeltaOperation, start: usize, end: usize, ) { tracing::trace!("invert op: {} [{}:{}]", operation, start, end); let other_ops = OperationIterator::from_interval(other, Interval::new(start, end)).ops(); other_ops.into_iter().for_each(|other_op| match operation { - Operation::Delete(_n) => { + DeltaOperation::Delete(_n) => { // tracing::trace!("invert delete: {} by add {}", n, other_op); base.add(other_op); } - Operation::Retain(_retain) => { + DeltaOperation::Retain(_retain) => { tracing::trace!( "invert attributes: {:?}, {:?}", operation.get_attributes(), @@ -541,15 +542,15 @@ fn invert_other( let inverted_attrs = operation.get_attributes().invert(&other_op.get_attributes()); base.retain(other_op.len(), inverted_attrs); } - Operation::Insert(_) => { + DeltaOperation::Insert(_) => { log::error!("Impossible to here. Insert operation should be treated as delete") } }); } fn transform_op_attribute( - left: &Option>, - right: &Option>, + left: &Option>, + right: &Option>, ) -> Result { if left.is_none() { if right.is_none() { @@ -563,7 +564,7 @@ fn transform_op_attribute( Ok(left.transform(&right)?.0) } -impl Operations +impl DeltaOperations where T: OperationAttributes + DeserializeOwned, { @@ -571,11 +572,11 @@ where /// /// ``` /// use lib_ot::core::OperationBuilder; - /// use lib_ot::text_delta::{TextDelta}; + /// use lib_ot::text_delta::{TextOperations}; /// let json = r#"[ /// {"retain":7,"attributes":{"bold":null}} /// ]"#; - /// let delta = TextDelta::from_json(json).unwrap(); + /// let delta = TextOperations::from_json(json).unwrap(); /// assert_eq!(delta.json_str(), r#"[{"retain":7,"attributes":{"bold":null}}]"#); /// ``` pub fn from_json(json: &str) -> Result { @@ -595,7 +596,7 @@ where } } -impl Operations +impl DeltaOperations where T: OperationAttributes + serde::Serialize, { @@ -616,36 +617,36 @@ where } } -impl FromStr for Operations +impl FromStr for DeltaOperations where T: OperationAttributes, { type Err = (); - fn from_str(s: &str) -> Result, Self::Err> { - let mut delta = Operations::with_capacity(1); - delta.add(Operation::Insert(s.into())); + fn from_str(s: &str) -> Result, Self::Err> { + let mut delta = DeltaOperations::with_capacity(1); + delta.add(DeltaOperation::Insert(s.into())); Ok(delta) } } -impl std::convert::TryFrom> for Operations +impl std::convert::TryFrom> for DeltaOperations where T: OperationAttributes + DeserializeOwned, { type Error = OTError; fn try_from(bytes: Vec) -> Result { - Operations::from_bytes(bytes) + DeltaOperations::from_bytes(bytes) } } -impl std::convert::TryFrom for Operations +impl std::convert::TryFrom for DeltaOperations where T: OperationAttributes + DeserializeOwned, { type Error = OTError; fn try_from(bytes: Bytes) -> Result { - Operations::from_bytes(&bytes) + DeltaOperations::from_bytes(&bytes) } } diff --git a/shared-lib/lib-ot/src/core/delta/ops_serde.rs b/shared-lib/lib-ot/src/core/delta/ops_serde.rs index f467fafa2f..a29b32926f 100644 --- a/shared-lib/lib-ot/src/core/delta/ops_serde.rs +++ b/shared-lib/lib-ot/src/core/delta/ops_serde.rs @@ -1,5 +1,5 @@ use crate::core::delta::operation::OperationAttributes; -use crate::core::delta::Operations; +use crate::core::delta::DeltaOperations; use serde::{ de::{SeqAccess, Visitor}, ser::SerializeSeq, @@ -7,7 +7,7 @@ use serde::{ }; use std::{fmt, marker::PhantomData}; -impl Serialize for Operations +impl Serialize for DeltaOperations where T: OperationAttributes + Serialize, { @@ -23,11 +23,11 @@ where } } -impl<'de, T> Deserialize<'de> for Operations +impl<'de, T> Deserialize<'de> for DeltaOperations where T: OperationAttributes + Deserialize<'de>, { - fn deserialize(deserializer: D) -> Result, D::Error> + fn deserialize(deserializer: D) -> Result, D::Error> where D: Deserializer<'de>, { @@ -37,7 +37,7 @@ where where T: OperationAttributes + Deserialize<'de>, { - type Value = Operations; + type Value = DeltaOperations; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("a sequence") @@ -48,7 +48,7 @@ where where A: SeqAccess<'de>, { - let mut o = Operations::default(); + let mut o = DeltaOperations::default(); while let Some(op) = seq.next_element()? { o.add(op); } diff --git a/shared-lib/lib-ot/src/core/node_tree/node.rs b/shared-lib/lib-ot/src/core/node_tree/node.rs index 908cfa3f18..557078f9f6 100644 --- a/shared-lib/lib-ot/src/core/node_tree/node.rs +++ b/shared-lib/lib-ot/src/core/node_tree/node.rs @@ -1,9 +1,9 @@ use super::node_serde::*; -use crate::core::attributes::{AttributeKey, AttributeValue, Attributes}; +use crate::core::attributes::{AttributeHashMap, AttributeKey, AttributeValue}; use crate::core::NodeBody::Delta; use crate::core::OperationTransform; use crate::errors::OTError; -use crate::text_delta::TextDelta; +use crate::text_delta::TextOperations; use serde::{Deserialize, Serialize}; #[derive(Default, Debug, Clone, Serialize, Deserialize, Eq, PartialEq)] @@ -11,9 +11,9 @@ pub struct NodeData { #[serde(rename = "type")] pub node_type: String, - #[serde(skip_serializing_if = "Attributes::is_empty")] + #[serde(skip_serializing_if = "AttributeHashMap::is_empty")] #[serde(default)] - pub attributes: Attributes, + pub attributes: AttributeHashMap, #[serde(serialize_with = "serialize_body")] #[serde(deserialize_with = "deserialize_body")] @@ -94,7 +94,7 @@ impl NodeDataBuilder { #[derive(Debug, Clone, PartialEq, Eq)] pub enum NodeBody { Empty, - Delta(TextDelta), + Delta(TextOperations), } impl std::default::Default for NodeBody { @@ -159,7 +159,10 @@ impl OperationTransform for NodeBody { #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "snake_case")] pub enum NodeBodyChangeset { - Delta { delta: TextDelta, inverted: TextDelta }, + Delta { + delta: TextOperations, + inverted: TextOperations, + }, } impl NodeBodyChangeset { @@ -179,14 +182,14 @@ impl NodeBodyChangeset { pub struct Node { pub node_type: String, pub body: NodeBody, - pub attributes: Attributes, + pub attributes: AttributeHashMap, } impl Node { pub fn new(node_type: &str) -> Node { Node { node_type: node_type.into(), - attributes: Attributes::new(), + attributes: AttributeHashMap::new(), body: NodeBody::Empty, } } diff --git a/shared-lib/lib-ot/src/core/node_tree/node_serde.rs b/shared-lib/lib-ot/src/core/node_tree/node_serde.rs index d1c2f74df1..71c8f64b45 100644 --- a/shared-lib/lib-ot/src/core/node_tree/node_serde.rs +++ b/shared-lib/lib-ot/src/core/node_tree/node_serde.rs @@ -1,5 +1,5 @@ use super::NodeBody; -use crate::text_delta::TextDelta; +use crate::text_delta::TextOperations; use serde::de::{self, MapAccess, Visitor}; use serde::ser::SerializeMap; use serde::{Deserializer, Serializer}; @@ -37,7 +37,7 @@ where where A: de::SeqAccess<'de>, { - let mut delta = TextDelta::default(); + let mut delta = TextOperations::default(); while let Some(op) = seq.next_element()? { delta.add(op); } @@ -49,7 +49,7 @@ where where V: MapAccess<'de>, { - let mut delta: Option = None; + let mut delta: Option = None; while let Some(key) = map.next_key()? { match key { "delta" => { diff --git a/shared-lib/lib-ot/src/core/node_tree/operation.rs b/shared-lib/lib-ot/src/core/node_tree/operation.rs index cdd2b99c7b..324cf73a6e 100644 --- a/shared-lib/lib-ot/src/core/node_tree/operation.rs +++ b/shared-lib/lib-ot/src/core/node_tree/operation.rs @@ -1,4 +1,4 @@ -use crate::core::attributes::Attributes; +use crate::core::attributes::AttributeHashMap; use crate::core::{NodeBodyChangeset, NodeData, Path}; use crate::errors::OTError; use serde::{Deserialize, Serialize}; @@ -13,8 +13,8 @@ pub enum NodeOperation { #[serde(rename = "update-attribute")] UpdateAttributes { path: Path, - new: Attributes, - old: Attributes, + new: AttributeHashMap, + old: AttributeHashMap, }, #[serde(rename = "update-body")] @@ -121,11 +121,11 @@ impl NodeOperation { } #[derive(Debug, Clone, Serialize, Deserialize, Default)] -pub struct NodeOperationList { +pub struct NodeOperations { operations: Vec>, } -impl NodeOperationList { +impl NodeOperations { pub fn into_inner(self) -> Vec> { self.operations } @@ -135,7 +135,7 @@ impl NodeOperationList { } } -impl std::ops::Deref for NodeOperationList { +impl std::ops::Deref for NodeOperations { type Target = Vec>; fn deref(&self) -> &Self::Target { @@ -143,19 +143,19 @@ impl std::ops::Deref for NodeOperationList { } } -impl std::ops::DerefMut for NodeOperationList { +impl std::ops::DerefMut for NodeOperations { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.operations } } -impl std::convert::From> for NodeOperationList { +impl std::convert::From> for NodeOperations { fn from(operations: Vec) -> Self { Self::new(operations) } } -impl NodeOperationList { +impl NodeOperations { pub fn new(operations: Vec) -> Self { Self { operations: operations.into_iter().map(Rc::new).collect(), diff --git a/shared-lib/lib-ot/src/core/node_tree/operation_serde.rs b/shared-lib/lib-ot/src/core/node_tree/operation_serde.rs index 439066b75b..d6dc2c49b7 100644 --- a/shared-lib/lib-ot/src/core/node_tree/operation_serde.rs +++ b/shared-lib/lib-ot/src/core/node_tree/operation_serde.rs @@ -1,5 +1,5 @@ use crate::core::{NodeBodyChangeset, Path}; -use crate::text_delta::TextDelta; +use crate::text_delta::TextOperations; use serde::de::{self, MapAccess, Visitor}; use serde::ser::SerializeMap; use serde::{Deserializer, Serializer}; @@ -88,8 +88,8 @@ where #[allow(dead_code)] struct DeltaBodyChangeset { - delta: Option, - inverted: Option, + delta: Option, + inverted: Option, error: PhantomData, } diff --git a/shared-lib/lib-ot/src/core/node_tree/transaction.rs b/shared-lib/lib-ot/src/core/node_tree/transaction.rs index 1f855698cf..e6cf72e59e 100644 --- a/shared-lib/lib-ot/src/core/node_tree/transaction.rs +++ b/shared-lib/lib-ot/src/core/node_tree/transaction.rs @@ -1,14 +1,14 @@ -use crate::core::attributes::Attributes; +use crate::core::attributes::AttributeHashMap; use crate::core::{NodeData, NodeOperation, NodeTree, Path}; use crate::errors::OTError; use indextree::NodeId; use std::rc::Rc; -use super::{NodeBodyChangeset, NodeOperationList}; +use super::{NodeBodyChangeset, NodeOperations}; #[derive(Debug, Clone, Default)] pub struct Transaction { - operations: NodeOperationList, + operations: NodeOperations, } impl Transaction { @@ -16,7 +16,7 @@ impl Transaction { Self::default() } - pub fn from_operations>(operations: T) -> Self { + pub fn from_operations>(operations: T) -> Self { Self { operations: operations.into(), } @@ -66,14 +66,14 @@ impl std::ops::DerefMut for Transaction { pub struct TransactionBuilder<'a> { node_tree: &'a NodeTree, - operations: NodeOperationList, + operations: NodeOperations, } impl<'a> TransactionBuilder<'a> { pub fn new(node_tree: &'a NodeTree) -> TransactionBuilder { TransactionBuilder { node_tree, - operations: NodeOperationList::default(), + operations: NodeOperations::default(), } } @@ -132,10 +132,10 @@ impl<'a> TransactionBuilder<'a> { self.insert_nodes_at_path(path, vec![node]) } - pub fn update_attributes_at_path(mut self, path: &Path, attributes: Attributes) -> Self { + pub fn update_attributes_at_path(mut self, path: &Path, attributes: AttributeHashMap) -> Self { match self.node_tree.get_node_at_path(path) { Some(node) => { - let mut old_attributes = Attributes::new(); + let mut old_attributes = AttributeHashMap::new(); for key in attributes.keys() { let old_attrs = &node.attributes; if let Some(value) = old_attrs.get(key.as_str()) { diff --git a/shared-lib/lib-ot/src/core/node_tree/tree.rs b/shared-lib/lib-ot/src/core/node_tree/tree.rs index fde8ccf20c..50a3e50226 100644 --- a/shared-lib/lib-ot/src/core/node_tree/tree.rs +++ b/shared-lib/lib-ot/src/core/node_tree/tree.rs @@ -1,10 +1,10 @@ -use crate::core::attributes::Attributes; +use crate::core::attributes::AttributeHashMap; use crate::core::{Node, NodeBodyChangeset, NodeData, NodeOperation, OperationTransform, Path, Transaction}; use crate::errors::{ErrorBuilder, OTError, OTErrorCode}; use indextree::{Arena, Children, FollowingSiblings, NodeId}; use std::rc::Rc; -use super::NodeOperationList; +use super::NodeOperations; /// pub struct NodeTree { @@ -26,11 +26,11 @@ impl NodeTree { } pub fn from_bytes(root_name: &str, bytes: Vec) -> Result { - let operations = NodeOperationList::from_bytes(bytes)?; + let operations = NodeOperations::from_bytes(bytes)?; Self::from_operations(root_name, operations) } - pub fn from_operations(root_name: &str, operations: NodeOperationList) -> Result { + pub fn from_operations(root_name: &str, operations: NodeOperations) -> Result { let mut node_tree = NodeTree::new(root_name); for operation in operations.into_inner().into_iter() { let _ = node_tree.apply_op(operation)?; @@ -252,9 +252,9 @@ impl NodeTree { } } - fn update_attributes(&mut self, path: &Path, attributes: Attributes) -> Result<(), OTError> { + fn update_attributes(&mut self, path: &Path, attributes: AttributeHashMap) -> Result<(), OTError> { self.mut_node_at_path(path, |node| { - let new_attributes = Attributes::compose(&node.attributes, &attributes)?; + let new_attributes = AttributeHashMap::compose(&node.attributes, &attributes)?; node.attributes = new_attributes; Ok(()) }) diff --git a/shared-lib/lib-ot/src/text_delta/attributes.rs b/shared-lib/lib-ot/src/text_delta/attributes.rs index 388f492bdf..b695d8a805 100644 --- a/shared-lib/lib-ot/src/text_delta/attributes.rs +++ b/shared-lib/lib-ot/src/text_delta/attributes.rs @@ -1,5 +1,5 @@ #![allow(non_snake_case)] -use crate::core::{AttributeEntry, AttributeKey, Attributes}; +use crate::core::{AttributeEntry, AttributeHashMap, AttributeKey}; use crate::text_delta::TextOperation; use crate::{inline_attribute_entry, inline_list_attribute_entry}; use lazy_static::lazy_static; @@ -8,11 +8,11 @@ use std::{collections::HashSet, iter::FromIterator}; use strum_macros::{AsRefStr, Display, EnumString}; #[inline(always)] -pub fn empty_attributes() -> Attributes { - Attributes::default() +pub fn empty_attributes() -> AttributeHashMap { + AttributeHashMap::default() } -pub fn attributes_except_header(op: &TextOperation) -> Attributes { +pub fn attributes_except_header(op: &TextOperation) -> AttributeHashMap { let mut attributes = op.get_attributes(); attributes.remove_key(BuildInTextAttributeKey::Header); attributes diff --git a/shared-lib/lib-ot/src/text_delta/delta.rs b/shared-lib/lib-ot/src/text_delta/delta.rs index e8eb3c3fd8..fc5cb4e150 100644 --- a/shared-lib/lib-ot/src/text_delta/delta.rs +++ b/shared-lib/lib-ot/src/text_delta/delta.rs @@ -1,5 +1,10 @@ -use crate::core::{Attributes, Operation, OperationBuilder, Operations}; +use crate::core::{AttributeHashMap, DeltaOperation, DeltaOperations, OperationBuilder, OperationTransform}; +use std::fmt::Debug; -pub type TextDelta = Operations; -pub type TextDeltaBuilder = OperationBuilder; -pub type TextOperation = Operation; +pub type TextOperations = DeltaOperations; +pub type TextOperationBuilder = OperationBuilder; +pub type TextOperation = DeltaOperation; + +// pub trait TextOperation2: Default + Debug + OperationTransform {} +// +// impl TextOperation2 for TextOperations {} diff --git a/shared-lib/lib-ot/tests/node/editor_test.rs b/shared-lib/lib-ot/tests/node/editor_test.rs index abd294ecc0..1695b015c0 100644 --- a/shared-lib/lib-ot/tests/node/editor_test.rs +++ b/shared-lib/lib-ot/tests/node/editor_test.rs @@ -2,7 +2,7 @@ use super::script::{NodeScript::*, *}; use lib_ot::core::AttributeBuilder; use lib_ot::{ core::{NodeData, Path}, - text_delta::TextDeltaBuilder, + text_delta::TextOperationBuilder, }; #[test] @@ -11,7 +11,7 @@ fn editor_deserialize_node_test() { let node: NodeData = serde_json::from_str(EXAMPLE_JSON).unwrap(); let path: Path = 0.into(); - let expected_delta = TextDeltaBuilder::new() + let expected_delta = TextOperationBuilder::new() .insert("👋 ") .insert_with_attributes( "Welcome to ", diff --git a/shared-lib/lib-ot/tests/node/operation_test.rs b/shared-lib/lib-ot/tests/node/operation_test.rs index a0be952afb..114b2abb01 100644 --- a/shared-lib/lib-ot/tests/node/operation_test.rs +++ b/shared-lib/lib-ot/tests/node/operation_test.rs @@ -3,7 +3,7 @@ use crate::node::script::NodeTest; use lib_ot::core::{AttributeBuilder, Node}; use lib_ot::{ core::{NodeBodyChangeset, NodeData, NodeDataBuilder, NodeOperation, Path}, - text_delta::TextDeltaBuilder, + text_delta::TextOperationBuilder, }; #[test] @@ -48,7 +48,7 @@ fn operation_update_node_attributes_serde_test() { #[test] fn operation_update_node_body_serialize_test() { - let delta = TextDeltaBuilder::new().insert("AppFlowy...").build(); + let delta = TextOperationBuilder::new().insert("AppFlowy...").build(); let inverted = delta.invert_str(""); let changeset = NodeBodyChangeset::Delta { delta, inverted }; let insert = NodeOperation::UpdateBody { diff --git a/shared-lib/lib-ot/tests/node/script.rs b/shared-lib/lib-ot/tests/node/script.rs index 678138e183..7c27763bc7 100644 --- a/shared-lib/lib-ot/tests/node/script.rs +++ b/shared-lib/lib-ot/tests/node/script.rs @@ -1,8 +1,8 @@ use lib_ot::core::{Node, Transaction}; use lib_ot::{ - core::attributes::Attributes, + core::attributes::AttributeHashMap, core::{NodeBody, NodeBodyChangeset, NodeData, NodeTree, Path, TransactionBuilder}, - text_delta::TextDelta, + text_delta::TextOperations, }; use std::collections::HashMap; @@ -14,7 +14,7 @@ pub enum NodeScript { }, UpdateAttributes { path: Path, - attributes: Attributes, + attributes: AttributeHashMap, }, UpdateBody { path: Path, @@ -38,7 +38,7 @@ pub enum NodeScript { }, AssertNodeDelta { path: Path, - expected: TextDelta, + expected: TextOperations, }, } diff --git a/shared-lib/lib-ot/tests/node/tree_test.rs b/shared-lib/lib-ot/tests/node/tree_test.rs index c1f1532385..98f9ee00ed 100644 --- a/shared-lib/lib-ot/tests/node/tree_test.rs +++ b/shared-lib/lib-ot/tests/node/tree_test.rs @@ -4,7 +4,7 @@ use lib_ot::core::NodeBody; use lib_ot::core::NodeBodyChangeset; use lib_ot::core::OperationTransform; use lib_ot::core::{NodeData, NodeDataBuilder, Path}; -use lib_ot::text_delta::TextDeltaBuilder; +use lib_ot::text_delta::TextOperationBuilder; #[test] fn node_insert_test() { @@ -293,8 +293,8 @@ fn node_update_body_test() { let path: Path = 0.into(); let s = "Hello".to_owned(); - let init_delta = TextDeltaBuilder::new().insert(&s).build(); - let delta = TextDeltaBuilder::new().retain(s.len()).insert(" AppFlowy").build(); + let init_delta = TextOperationBuilder::new().insert(&s).build(); + let delta = TextOperationBuilder::new().retain(s.len()).insert(" AppFlowy").build(); let inverted = delta.invert(&init_delta); let expected = init_delta.compose(&delta).unwrap();